@foxeltech/angular-ui 0.4.0 → 0.7.75

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 (189) hide show
  1. package/archivo/archivo-400-latin-ext.woff2 +0 -0
  2. package/archivo/archivo-400-latin.woff2 +0 -0
  3. package/archivo/archivo-400-vietnamese.woff2 +0 -0
  4. package/archivo/archivo-500-latin-ext.woff2 +0 -0
  5. package/archivo/archivo-500-latin.woff2 +0 -0
  6. package/archivo/archivo-500-vietnamese.woff2 +0 -0
  7. package/archivo/archivo-600-latin-ext.woff2 +0 -0
  8. package/archivo/archivo-600-latin.woff2 +0 -0
  9. package/archivo/archivo-600-vietnamese.woff2 +0 -0
  10. package/archivo/archivo-700-latin-ext.woff2 +0 -0
  11. package/archivo/archivo-700-latin.woff2 +0 -0
  12. package/archivo/archivo-700-vietnamese.woff2 +0 -0
  13. package/components.css +332 -30
  14. package/dialogs.css +2 -2
  15. package/familjen-grotesk/familjen-grotesk-400-latin-ext.woff2 +0 -0
  16. package/familjen-grotesk/familjen-grotesk-400-latin.woff2 +0 -0
  17. package/familjen-grotesk/familjen-grotesk-400-vietnamese.woff2 +0 -0
  18. package/familjen-grotesk/familjen-grotesk-500-latin-ext.woff2 +0 -0
  19. package/familjen-grotesk/familjen-grotesk-500-latin.woff2 +0 -0
  20. package/familjen-grotesk/familjen-grotesk-500-vietnamese.woff2 +0 -0
  21. package/familjen-grotesk/familjen-grotesk-600-latin-ext.woff2 +0 -0
  22. package/familjen-grotesk/familjen-grotesk-600-latin.woff2 +0 -0
  23. package/familjen-grotesk/familjen-grotesk-600-vietnamese.woff2 +0 -0
  24. package/familjen-grotesk/familjen-grotesk-700-latin-ext.woff2 +0 -0
  25. package/familjen-grotesk/familjen-grotesk-700-latin.woff2 +0 -0
  26. package/familjen-grotesk/familjen-grotesk-700-vietnamese.woff2 +0 -0
  27. package/fesm2022/foxeltech-angular-ui-chart.mjs +381 -40
  28. package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -1
  29. package/fesm2022/foxeltech-angular-ui-flow.mjs +176 -3
  30. package/fesm2022/foxeltech-angular-ui-flow.mjs.map +1 -1
  31. package/fesm2022/foxeltech-angular-ui-rich-text.mjs +2 -2
  32. package/fesm2022/foxeltech-angular-ui-rich-text.mjs.map +1 -1
  33. package/fesm2022/foxeltech-angular-ui.mjs +1327 -151
  34. package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
  35. package/fonts.css +558 -133
  36. package/ibm-plex-mono/ibm-plex-mono-400-cyrillic-ext.woff2 +0 -0
  37. package/ibm-plex-mono/ibm-plex-mono-400-cyrillic.woff2 +0 -0
  38. package/ibm-plex-mono/ibm-plex-mono-400-latin-ext.woff2 +0 -0
  39. package/ibm-plex-mono/ibm-plex-mono-400-latin.woff2 +0 -0
  40. package/ibm-plex-mono/ibm-plex-mono-400-vietnamese.woff2 +0 -0
  41. package/ibm-plex-mono/ibm-plex-mono-500-cyrillic-ext.woff2 +0 -0
  42. package/ibm-plex-mono/ibm-plex-mono-500-cyrillic.woff2 +0 -0
  43. package/ibm-plex-mono/ibm-plex-mono-500-latin-ext.woff2 +0 -0
  44. package/ibm-plex-mono/ibm-plex-mono-500-latin.woff2 +0 -0
  45. package/ibm-plex-mono/ibm-plex-mono-500-vietnamese.woff2 +0 -0
  46. package/ibm-plex-mono/ibm-plex-mono-600-cyrillic-ext.woff2 +0 -0
  47. package/ibm-plex-mono/ibm-plex-mono-600-cyrillic.woff2 +0 -0
  48. package/ibm-plex-mono/ibm-plex-mono-600-latin-ext.woff2 +0 -0
  49. package/ibm-plex-mono/ibm-plex-mono-600-latin.woff2 +0 -0
  50. package/ibm-plex-mono/ibm-plex-mono-600-vietnamese.woff2 +0 -0
  51. package/jetbrains-mono/jetbrains-mono-400-cyrillic-ext.woff2 +0 -0
  52. package/jetbrains-mono/jetbrains-mono-400-cyrillic.woff2 +0 -0
  53. package/jetbrains-mono/jetbrains-mono-400-greek.woff2 +0 -0
  54. package/jetbrains-mono/jetbrains-mono-400-latin-ext.woff2 +0 -0
  55. package/jetbrains-mono/jetbrains-mono-400-latin.woff2 +0 -0
  56. package/jetbrains-mono/jetbrains-mono-400-vietnamese.woff2 +0 -0
  57. package/jetbrains-mono/jetbrains-mono-500-cyrillic-ext.woff2 +0 -0
  58. package/jetbrains-mono/jetbrains-mono-500-cyrillic.woff2 +0 -0
  59. package/jetbrains-mono/jetbrains-mono-500-greek.woff2 +0 -0
  60. package/jetbrains-mono/jetbrains-mono-500-latin-ext.woff2 +0 -0
  61. package/jetbrains-mono/jetbrains-mono-500-latin.woff2 +0 -0
  62. package/jetbrains-mono/jetbrains-mono-500-vietnamese.woff2 +0 -0
  63. package/jetbrains-mono/jetbrains-mono-600-cyrillic-ext.woff2 +0 -0
  64. package/jetbrains-mono/jetbrains-mono-600-cyrillic.woff2 +0 -0
  65. package/jetbrains-mono/jetbrains-mono-600-greek.woff2 +0 -0
  66. package/jetbrains-mono/jetbrains-mono-600-latin-ext.woff2 +0 -0
  67. package/jetbrains-mono/jetbrains-mono-600-latin.woff2 +0 -0
  68. package/jetbrains-mono/jetbrains-mono-600-vietnamese.woff2 +0 -0
  69. package/jetbrains-mono/jetbrains-mono-700-cyrillic-ext.woff2 +0 -0
  70. package/jetbrains-mono/jetbrains-mono-700-cyrillic.woff2 +0 -0
  71. package/jetbrains-mono/jetbrains-mono-700-greek.woff2 +0 -0
  72. package/jetbrains-mono/jetbrains-mono-700-latin-ext.woff2 +0 -0
  73. package/jetbrains-mono/jetbrains-mono-700-latin.woff2 +0 -0
  74. package/jetbrains-mono/jetbrains-mono-700-vietnamese.woff2 +0 -0
  75. package/newsreader/newsreader-400-latin-ext.woff2 +0 -0
  76. package/newsreader/newsreader-400-latin.woff2 +0 -0
  77. package/newsreader/newsreader-400-vietnamese.woff2 +0 -0
  78. package/newsreader/newsreader-500-latin-ext.woff2 +0 -0
  79. package/newsreader/newsreader-500-latin.woff2 +0 -0
  80. package/newsreader/newsreader-500-vietnamese.woff2 +0 -0
  81. package/newsreader/newsreader-600-latin-ext.woff2 +0 -0
  82. package/newsreader/newsreader-600-latin.woff2 +0 -0
  83. package/newsreader/newsreader-600-vietnamese.woff2 +0 -0
  84. package/package.json +5 -2
  85. package/source-serif-4/source-serif-4-400-cyrillic-ext.woff2 +0 -0
  86. package/source-serif-4/source-serif-4-400-cyrillic.woff2 +0 -0
  87. package/source-serif-4/source-serif-4-400-greek.woff2 +0 -0
  88. package/source-serif-4/source-serif-4-400-latin-ext.woff2 +0 -0
  89. package/source-serif-4/source-serif-4-400-latin.woff2 +0 -0
  90. package/source-serif-4/source-serif-4-400-vietnamese.woff2 +0 -0
  91. package/source-serif-4/source-serif-4-600-cyrillic-ext.woff2 +0 -0
  92. package/source-serif-4/source-serif-4-600-cyrillic.woff2 +0 -0
  93. package/source-serif-4/source-serif-4-600-greek.woff2 +0 -0
  94. package/source-serif-4/source-serif-4-600-latin-ext.woff2 +0 -0
  95. package/source-serif-4/source-serif-4-600-latin.woff2 +0 -0
  96. package/source-serif-4/source-serif-4-600-vietnamese.woff2 +0 -0
  97. package/src/lib/styles/components.css +332 -30
  98. package/src/lib/styles/dialogs.css +2 -2
  99. package/src/lib/styles/fonts.css +558 -133
  100. package/src/lib/styles/tailwind.css +13 -1
  101. package/src/lib/styles/theme.css +642 -69
  102. package/src/lib/styles/tokens.css +81 -19
  103. package/src/lib/styles/utilities.css +16 -1
  104. package/src/lib/ui/components/bar-list/bar-list.component.html +29 -0
  105. package/src/lib/ui/components/button/button.component.html +9 -5
  106. package/src/lib/ui/components/checkbox/checkbox.component.html +1 -1
  107. package/src/lib/ui/components/code-block/code-block.component.html +8 -0
  108. package/src/lib/ui/components/drawer/drawer.component.html +35 -12
  109. package/src/lib/ui/components/drawer/drawer.component.scss +106 -18
  110. package/src/lib/ui/components/facets-rail/facets-rail.component.html +37 -0
  111. package/src/lib/ui/components/filter-pills/filter-pills.component.html +16 -0
  112. package/src/lib/ui/components/kanban-board/kanban-board.component.scss +9 -9
  113. package/src/lib/ui/components/list-row/list-row.component.html +20 -0
  114. package/src/lib/ui/components/master-detail/master-detail.component.css +79 -5
  115. package/src/lib/ui/components/master-detail/master-detail.component.html +57 -7
  116. package/src/lib/ui/components/pending-badge/pending-badge.component.html +15 -0
  117. package/src/lib/ui/components/pipeline-stepper/pipeline-stepper.component.html +45 -0
  118. package/src/lib/ui/components/project-card/project-card.component.html +102 -0
  119. package/src/lib/ui/components/radio-button/radio-button.component.html +1 -1
  120. package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.html +1 -1
  121. package/src/lib/ui/components/route-skeleton/route-skeleton.component.css +38 -0
  122. package/src/lib/ui/components/route-skeleton/route-skeleton.component.html +184 -0
  123. package/src/lib/ui/components/sample-frame/sample-frame.component.html +18 -0
  124. package/src/lib/ui/components/score-badge/score-badge.component.html +7 -0
  125. package/src/lib/ui/components/screenshot-frame/screenshot-frame.component.html +40 -0
  126. package/src/lib/ui/components/section-card/section-card.component.html +15 -6
  127. package/src/lib/ui/components/segmented/segmented.component.html +42 -0
  128. package/src/lib/ui/components/segmented/segmented.component.scss +12 -0
  129. package/src/lib/ui/components/skeleton-dashboard/skeleton-dashboard.component.html +24 -0
  130. package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +8 -8
  131. package/src/lib/ui/components/skeleton-facets/skeleton-facets.component.html +15 -0
  132. package/src/lib/ui/components/skeleton-frame/skeleton-frame.component.html +59 -0
  133. package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +6 -6
  134. package/src/lib/ui/components/slider/slider.component.html +2 -2
  135. package/src/lib/ui/components/sparkbar/sparkbar.component.html +14 -0
  136. package/src/lib/ui/components/stage-dots/stage-dots.component.html +13 -0
  137. package/src/lib/ui/components/stat-cards/stat-cards.component.html +44 -11
  138. package/src/lib/ui/components/status-dot/status-dot.component.html +13 -0
  139. package/src/lib/ui/components/switch/switch.component.html +1 -1
  140. package/src/lib/ui/components/tab-group/tab-group.component.html +37 -8
  141. package/src/lib/ui/components/tab-group/tab-group.component.scss +41 -1
  142. package/src/lib/ui/components/tag/tag.component.html +2 -2
  143. package/src/lib/ui/components/theme-picker/theme-picker.component.html +44 -0
  144. package/src/lib/ui/components/toast/toast.component.html +6 -6
  145. package/src/lib/ui/components/tree-diagram/tree-diagram.component.html +3 -3
  146. package/tailwind.css +13 -1
  147. package/theme.css +642 -69
  148. package/tokens.css +81 -19
  149. package/types/foxeltech-angular-ui-chart.d.ts +90 -3
  150. package/types/foxeltech-angular-ui-flow.d.ts +83 -1
  151. package/types/foxeltech-angular-ui.d.ts +909 -48
  152. package/utilities.css +16 -1
  153. package/BeVietnamPro/BeVietnamPro-Bold.woff2 +0 -0
  154. package/BeVietnamPro/BeVietnamPro-ExtraLight.woff2 +0 -0
  155. package/BeVietnamPro/BeVietnamPro-Light.woff2 +0 -0
  156. package/BeVietnamPro/BeVietnamPro-Medium.woff2 +0 -0
  157. package/BeVietnamPro/BeVietnamPro-Regular.woff2 +0 -0
  158. package/BeVietnamPro/BeVietnamPro-SemiBold.woff2 +0 -0
  159. package/BeVietnamPro/BeVietnamPro-Thin.woff2 +0 -0
  160. package/SpaceMono-Regular.woff2 +0 -0
  161. package/dm-sans/DMSans-Bold.woff2 +0 -0
  162. package/dm-sans/DMSans-Light.woff2 +0 -0
  163. package/dm-sans/DMSans-Medium.woff2 +0 -0
  164. package/dm-sans/DMSans-Regular.woff2 +0 -0
  165. package/dm-sans/DMSans-SemiBold.woff2 +0 -0
  166. package/dm-sans/DMSans-Thin.woff2 +0 -0
  167. package/orbitron/Orbitron-Bold.woff2 +0 -0
  168. package/orbitron/Orbitron-Medium.woff2 +0 -0
  169. package/orbitron/Orbitron-Regular.woff2 +0 -0
  170. package/orbitron/Orbitron-SemiBold.woff2 +0 -0
  171. package/roboto/Roboto-Black.woff2 +0 -0
  172. package/roboto/Roboto-BlackItalic.woff2 +0 -0
  173. package/roboto/Roboto-Bold.woff2 +0 -0
  174. package/roboto/Roboto-BoldCondensed.woff2 +0 -0
  175. package/roboto/Roboto-BoldCondensedItalic.woff2 +0 -0
  176. package/roboto/Roboto-BoldItalic.woff2 +0 -0
  177. package/roboto/Roboto-Condensed.woff2 +0 -0
  178. package/roboto/Roboto-CondensedItalic.woff2 +0 -0
  179. package/roboto/Roboto-Italic.woff2 +0 -0
  180. package/roboto/Roboto-Light.woff2 +0 -0
  181. package/roboto/Roboto-LightItalic.woff2 +0 -0
  182. package/roboto/Roboto-Medium.woff2 +0 -0
  183. package/roboto/Roboto-MediumItalic.woff2 +0 -0
  184. package/roboto/Roboto-Regular.woff2 +0 -0
  185. package/roboto/Roboto-Thin.woff2 +0 -0
  186. package/roboto/Roboto-ThinItalic.woff2 +0 -0
  187. package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.html +0 -21
  188. package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.scss +0 -0
  189. package/src/lib/ui/components/tab-component/tab.component.html +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { OnDestroy, Injector, DestroyRef, ApplicationRef, OnInit, AfterViewInit, ChangeDetectorRef, Type, EventEmitter, Provider, ModuleWithProviders, TemplateRef, ViewContainerRef, ElementRef, RendererFactory2, OnChanges, SimpleChanges, AfterContentInit, Renderer2, InjectionToken, QueryList, NgZone } from '@angular/core';
2
+ import { OnDestroy, Injector, DestroyRef, ApplicationRef, OnInit, AfterViewInit, ChangeDetectorRef, Type, EventEmitter, Provider, ModuleWithProviders, TemplateRef, ViewContainerRef, ElementRef, RendererFactory2, OnChanges, SimpleChanges, AfterContentInit, AfterViewChecked, Renderer2, InjectionToken, QueryList, NgZone } from '@angular/core';
3
3
  import * as _foxeltech_angular_ui from '@foxeltech/angular-ui';
4
4
  import { MatDialog, MatDialogRef, MatDialogConfig } from '@angular/material/dialog';
5
5
  import { MatPaginator, PageEvent } from '@angular/material/paginator';
@@ -261,22 +261,135 @@ declare class BaseDialogComponent<T = any> extends BaseComponent implements Afte
261
261
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseDialogComponent<any>, never, never, {}, {}, never, never, true, never>;
262
262
  }
263
263
 
264
+ /**
265
+ * Overlay chặn màn cho HÀNH ĐỘNG của người dùng (bấm nút, đổi trạng thái,
266
+ * xuất báo cáo…). `app.html` của host bind `fx-ui-loading-panel` vào
267
+ * `listenerAction`.
268
+ *
269
+ * ⚠️ **KHÔNG dùng cho điều hướng.** Channel `listener` + `start()`/`stop()` đã
270
+ * bị XOÁ ở 0.7.70 (Pha 3). Điều hướng dùng skeleton: `FxRouteSkeletonService`
271
+ * đọc `data.skeleton` của route đích và shell dựng `fx-ui-route-skeleton`.
272
+ *
273
+ * Vì sao xoá thay vì để lại: trước đó cả 46 call site đổ chung MỘT channel, lẫn
274
+ * hai ngữ nghĩa (điều hướng vs hành động). Sau khi skeleton thay phần điều
275
+ * hướng, `listener` không còn ai nghe — để lại là một cái bẫy: gọi `start()`
276
+ * tưởng có overlay mà thực tế không có gì hiện.
277
+ */
264
278
  declare class FxLoadingService {
265
- listener: EventEmitter<boolean>;
266
279
  listenerAction: EventEmitter<boolean>;
267
- start(): void;
268
- stop(): void;
269
280
  startAction(): void;
270
281
  stopAction(): void;
271
282
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FxLoadingService, never>;
272
283
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<FxLoadingService>;
273
284
  }
274
285
 
275
- declare class BaseResolver {
276
- loadingService: FxLoadingService;
277
- injector: Injector;
278
- constructor(loadingService: FxLoadingService, injector: Injector);
279
- baseResolverInit(): void;
286
+ /**
287
+ * Một KHỐI trong skeleton của màn. Ghép các khối này theo đúng thứ tự của màn
288
+ * thật thì skeleton mới khớp layout — bảng ra bảng, chart ra chart.
289
+ *
290
+ * - `heading` H1 + subline + `count` nút hành động (mặc định 2, 0 = không có)
291
+ * - `toolbar` search bar + `count` filter pill (mặc định 2)
292
+ * - `table` bảng, skeleton theo TỪNG Ô (`columns` / `rows`)
293
+ * - `cards` lưới card (catalog) — `count` / `cols`
294
+ * - `stat-cards` hàng stat tile rời — `count`
295
+ * - `kpi-strip` MỘT card chia cột, số to (kiểu `app-dash-kpi-row`) — `count`
296
+ * - `panels` lưới section-card có vùng chart — `count` / `cols`
297
+ * - `card` một section-card đơn
298
+ * - `tabs` dải tab
299
+ * - `facets` 3 cụm facets/list/detail
300
+ * - `detail` cụm card detail
301
+ * - `form` card form
302
+ */
303
+ type FxSkeletonBlockKind = 'heading' | 'toolbar' | 'table' | 'cards' | 'stat-cards' | 'kpi-strip' | 'panels' | 'card' | 'tabs' | 'facets' | 'detail' | 'form';
304
+ interface FxSkeletonBlockSpec {
305
+ kind: FxSkeletonBlockKind;
306
+ /**
307
+ * Số phần tử con:
308
+ * - `heading`: số nút hành động (0 = màn không có CTA)
309
+ * - `toolbar`: số filter pill
310
+ * - `panels` `cards` `stat-cards` `kpi-strip` `tabs`: số khối
311
+ */
312
+ count?: number;
313
+ /** `panels` `cards`: số cột ở breakpoint lớn. */
314
+ cols?: number;
315
+ /** `table`: số cột và số hàng. */
316
+ columns?: number;
317
+ rows?: number;
318
+ }
319
+ type FxSkeletonBlock = FxSkeletonBlockKind | FxSkeletonBlockSpec;
320
+ /**
321
+ * Tên gọn cho các layout dùng lại được. Route nên khai thẳng mảng block khi
322
+ * layout của nó khác preset — chính app biết layout của mình, không phải lib.
323
+ */
324
+ type FxSkeletonHint = 'table' | 'panels' | 'dashboard' | 'tabs-facets' | 'facets' | 'detail' | 'form';
325
+ /**
326
+ * Skeleton cho vùng NỘI DUNG trong lúc resolver của route đang chạy.
327
+ *
328
+ * ⚠️ Vì sao skeleton phải nằm ở shell chứ không ở từng màn: Angular **không
329
+ * tạo component cho tới khi resolver xong**, nên một màn không thể tự vẽ
330
+ * skeleton của chính nó trong lúc resolver của nó chạy. Thứ vẽ được phải tồn
331
+ * tại TRƯỚC component đó → shell + router event. Xem `FxRouteSkeletonService`.
332
+ */
333
+ declare class RouteSkeletonComponent {
334
+ /** Tên preset, hoặc mảng block mô tả đúng layout của màn. */
335
+ readonly hint: _angular_core.InputSignal<FxSkeletonHint | FxSkeletonBlock[] | null>;
336
+ readonly blocks: _angular_core.Signal<FxSkeletonBlockSpec[]>;
337
+ cols(b: FxSkeletonBlockSpec): number[];
338
+ rows(b: FxSkeletonBlockSpec): number[];
339
+ items(b: FxSkeletonBlockSpec, fallback: number): number[];
340
+ /** Lớp lưới cho `panels`/`cards` — Tailwind v4 không có safelist nên phải
341
+ * là chuỗi tĩnh, không ghép động. */
342
+ gridClass(b: FxSkeletonBlockSpec): string;
343
+ /** Header ngắn hơn ô dữ liệu, cột đầu rộng nhất (thường là tên). */
344
+ headWidth(c: number): number;
345
+ /**
346
+ * Bề rộng đổi theo cả hàng và cột — cùng bề rộng thì khối skeleton trông
347
+ * như một hình chữ nhật đặc, mất cảm giác "từng field".
348
+ */
349
+ cellWidth(r: number, c: number): number;
350
+ barHeight(i: number): number;
351
+ readonly bars: number[];
352
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RouteSkeletonComponent, never>;
353
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<RouteSkeletonComponent, "fx-ui-route-skeleton", never, { "hint": { "alias": "hint"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
354
+ }
355
+
356
+ /**
357
+ * Khai trên route: `data: { skeleton: 'table' }` (tên preset) hoặc
358
+ * `data: { skeleton: ['heading', 'toolbar', 'table'] }` (mảng block, mô tả
359
+ * ĐÚNG layout của màn — bảng ra bảng, chart ra chart).
360
+ */
361
+ declare const FX_SKELETON_DATA_KEY = "skeleton";
362
+ /**
363
+ * Đọc `data.skeleton` của route đích rồi bật/tắt skeleton cho vùng nội dung.
364
+ *
365
+ * ⚠️ Vì sao phải nghe router event chứ không để từng màn tự lo: Angular
366
+ * **không tạo component cho tới khi resolver xong**, nên trong lúc resolver
367
+ * của một màn chạy thì component đó chưa tồn tại — không có gì để vẽ
368
+ * skeleton. Chỉ shell (tồn tại trước) làm được.
369
+ *
370
+ * Mốc dùng là `RoutesRecognized` — event ĐẦU TIÊN mang `RouterStateSnapshot`,
371
+ * và nó xảy ra TRƯỚC `ResolveStart`. `NavigationStart` thì chưa biết route
372
+ * đích nên không đọc được hint.
373
+ */
374
+ declare class FxRouteSkeletonService {
375
+ private readonly router;
376
+ private readonly _hint;
377
+ /** Hint đang hiển thị, `null` = không vẽ skeleton. */
378
+ readonly hint: _angular_core.Signal<FxSkeletonHint | FxSkeletonBlock[] | null>;
379
+ readonly active: _angular_core.Signal<boolean>;
380
+ /**
381
+ * Điều hướng nhanh hơn mốc này thì KHÔNG vẽ skeleton — tránh nháy một
382
+ * nhịp khi resolver trả về gần như tức thì (dữ liệu đã cache).
383
+ */
384
+ private readonly graceMs;
385
+ private timer?;
386
+ private started;
387
+ constructor();
388
+ /** Gọi một lần từ shell (host và mỗi remote standalone). */
389
+ start(): void;
390
+ private clearTimer;
391
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FxRouteSkeletonService, never>;
392
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<FxRouteSkeletonService>;
280
393
  }
281
394
 
282
395
  interface FxListRequest {
@@ -292,11 +405,12 @@ interface FxListResolverContext {
292
405
  pageSize: number;
293
406
  }
294
407
  /**
295
- * Functional replacement for the copy-pasted list-resolver class:
296
- * starts the loading overlay, runs one API request, and on failure stops the
297
- * overlay and shows a parsed error toast the exact convention every
298
- * BaseResolver subclass hand-rolls today. BaseResolver stays for existing
299
- * classes; new routes should use this factory.
408
+ * Chạy MỘT request cho list resolver, lỗi thì hiện toast đã parse.
409
+ *
410
+ * ⚠️ KHÔNG còn bật overlay chặn màn: điều hướng dùng skeleton
411
+ * (`FxRouteSkeletonService` + `data.skeleton` trên route). `BaseResolver` đã bị
412
+ * xoá 0.7.70 mọi resolver giờ là `@Injectable()` thuần hoặc dùng factory
413
+ * này.
300
414
  *
301
415
  * Usage:
302
416
  * resolve: { histories: fxListResolver(ScanManagementApi, (route, state, ctx) =>
@@ -509,6 +623,14 @@ declare class FxUtils {
509
623
  static convertColorFromVariable(name: string, alpha?: number, options?: {
510
624
  legacyCommaSyntax?: boolean;
511
625
  }): string;
626
+ /**
627
+ * Status/severity string → tag tone.
628
+ *
629
+ * Coerces instead of trusting the argument: every caller feeds this raw API
630
+ * values, and a numeric or null field used to throw
631
+ * "key.toLowerCase is not a function" and take the whole screen down.
632
+ * Non-string input simply falls through to the default tone.
633
+ */
512
634
  static getTagClass(key: string, isCriticalExist?: boolean): TagType;
513
635
  static validateEmail(value: string): boolean;
514
636
  /** Safe deep accessor with the org-wide empty placeholder. */
@@ -547,9 +669,16 @@ declare class FxUtils {
547
669
  * helpers return `null` for "no meaningful value" and the `toneText` /
548
670
  * `toneBg` / `toneBadge` wrappers fall back to a neutral class.
549
671
  *
550
- * Every emitted utility must appear below as a WHOLE literal string — the
551
- * Tailwind content scanner (v4 has no safelist) only sees complete class
552
- * names. Never rebuild these with string interpolation.
672
+ * Every emitted Tailwind UTILITY must appear below as a WHOLE literal string —
673
+ * the Tailwind content scanner (v4 has no safelist) only sees complete class
674
+ * names. Never rebuild those with string interpolation.
675
+ *
676
+ * ⚠️ Ngoại lệ có chủ đích: `tone-tint-*`, `tone-fg-*`, `tone-dot-*` và
677
+ * `tone-dot-chart-*` là CLASS CSS THẬT khai trong components.css, KHÔNG phải
678
+ * utility Tailwind — chúng luôn tồn tại trong stylesheet nên ghép chuỗi
679
+ * `tone-fg-${tone}` là an toàn. Đó chính là lý do chọn class thay vì utility:
680
+ * ngoài việc tránh xung đột tên (`warning` trong theme Tailwind trỏ vào bộ
681
+ * LEGACY `--og-tone-*`), nó còn xoá hẳn bẫy "class ghép chuỗi bị vô hình".
553
682
  */
554
683
  type Tone = 'critical' | 'danger' | 'warning' | 'success' | 'information';
555
684
  /** Severity / risk-level string → tone (Critical & High → danger, Medium → warning, Low → success). */
@@ -572,7 +701,50 @@ declare function toneText(tone: Tone | null): string;
572
701
  /** Tone → background colour class, with a neutral fallback when there is no value. */
573
702
  declare function toneBg(tone: Tone | null): string;
574
703
  /** Tone → soft pill/badge classes (tinted bg + matching text), neutral fallback. */
575
- declare function toneBadge(tone: Tone | null): string;
704
+ /**
705
+ * Badge severity MẶC ĐỊNH — nền MỀM theo thang đo, Critical ra **đỏ sẫm**.
706
+ *
707
+ * ⚠️ Trước đây hàm này trả nền ĐẶC (`tone-tint-*`, Critical = đen `--og-text`)
708
+ * vì demo có biến thể `.og-badge--solid`. Nhưng demo chỉ dùng biến thể đó ở
709
+ * ĐÚNG MỘT chỗ — badge severity trong danh sách findings — còn app mình gọi
710
+ * `toneBadge()` ở khắp nơi (`project-card`, `score-badge`, `list-row`,
711
+ * `severity-badges`, `tab-group`, badge trong hàng…). Kết quả: pill đen tràn
712
+ * ra mọi màn, anh Tú báo 3 lần (03/09). Nên MẶC ĐỊNH đảo về nền mềm; muốn
713
+ * pill đen thì gọi `toneBadgeSolid()` một cách tường minh.
714
+ */
715
+ declare function toneBadge(tone: Tone | string | null | undefined): string;
716
+ /**
717
+ * Badge severity nền ĐẶC (Critical = `--og-text`, chữ `--og-surface`) — đúng
718
+ * `.og-badge--solid` của demo. CHỈ dùng cho badge severity đứng một mình ở
719
+ * nơi cần nhấn mạnh nhất; đừng dùng cho badge có chấm bên trong (chấm sẽ chìm).
720
+ */
721
+ declare function toneBadgeSolid(tone: Tone | string | null | undefined): string;
722
+ /** Chỉ MÀU của tông, không kèm hình dạng pill — cho ô icon, chip, ô nền. */
723
+ declare function toneTint(tone: Tone | string | null | undefined): string;
724
+ /**
725
+ * CHỮ theo tông — dùng thành viên dễ đọc nhất của mỗi họ severity, KHÔNG phải
726
+ * ramp chart (ramp có `warning #f59e0b` chỉ 2.15:1 trên nền trắng). Xem
727
+ * `.tone-fg-*` trong components.css.
728
+ */
729
+ declare function toneFg(tone: Tone | string | null | undefined): string;
730
+ /**
731
+ * Tông THANG ĐO — cho filter chip severity. Critical ra ĐỎ SẪM (nền mềm pha
732
+ * từ ramp `--og-sev-*`) thay vì pill đen đặc của `toneTint()`: chip filter là
733
+ * một thang đo, không phải badge severity của một finding. Xem `.tone-scale-*`.
734
+ */
735
+ declare function toneScale(tone: Tone | string | null | undefined): string;
736
+ /** Viền theo tông — cho panel trạng thái (dropzone upload…). */
737
+ declare function toneBorder(tone: Tone | string | null | undefined): string;
738
+ /**
739
+ * CHẤM trạng thái trong hàng (`● Confirmed`) — demo dùng màu SEMANTIC
740
+ * (`.og-statusdot--*`), không phải ramp chart.
741
+ */
742
+ declare function toneDot(tone: Tone | string | null | undefined): string;
743
+ /**
744
+ * CHẤM LEGEND của chart — phải TRÙNG màu cung donut nên dùng ramp
745
+ * `--og-sev-*`. Đừng dùng cho chấm trạng thái trong hàng.
746
+ */
747
+ declare function toneDotChart(tone: Tone | string | null | undefined): string;
576
748
  /**
577
749
  * Tone → resolved CSS colour string for ECharts / canvas where a Tailwind
578
750
  * class can't be used (e.g. per-slice pie `itemStyle.color`). Emits the
@@ -580,6 +752,25 @@ declare function toneBadge(tone: Tone | null): string;
580
752
  */
581
753
  declare function toneColor(tone: Tone | null, alpha?: number): string;
582
754
 
755
+ /**
756
+ * Feature gating for the V2 rollout.
757
+ *
758
+ * Each app owns its own `environment.features` block, so the flags are passed
759
+ * in rather than read here — the library has no environment of its own.
760
+ *
761
+ * readonly knowledge = featureEnabled(environment.features, 'knowledge');
762
+ *
763
+ * Why a helper instead of `environment.features?.x`: call sites were drifting
764
+ * between truthy checks and `=== true`, some behind an `as any` cast that hides
765
+ * a typo in the flag name. One function keeps the semantics identical
766
+ * everywhere — a flag counts as on only when it is exactly `true`, so a missing
767
+ * block, a missing key or a stale string value all read as off.
768
+ */
769
+ type FxFeatureFlags = Record<string, boolean | undefined> | undefined | null;
770
+ declare function featureEnabled(flags: FxFeatureFlags, name: string): boolean;
771
+ /** Convenience for templates that gate on several flags at once. */
772
+ declare function anyFeatureEnabled(flags: FxFeatureFlags, ...names: string[]): boolean;
773
+
583
774
  declare class FxValidators {
584
775
  /**
585
776
  * Name fields: firstName, lastName, groupName, projectName, displayName
@@ -741,18 +932,54 @@ declare class BreadcrumbService {
741
932
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<BreadcrumbService>;
742
933
  }
743
934
 
935
+ /** The six OgeniumDashboards themes. */
936
+ type OgTheme = 'porcelain' | 'charcoal' | 'ivory' | 'studio' | 'blueprint' | 'terminal';
937
+ declare const OG_THEMES: readonly OgTheme[];
938
+ declare const OG_LIGHT_THEMES: readonly OgTheme[];
939
+ /** Display metadata for theme pickers — accent/page swatches are brand constants. */
940
+ interface OgThemeMeta {
941
+ name: OgTheme;
942
+ label: string;
943
+ accent: string;
944
+ pageBg: string;
945
+ dark: boolean;
946
+ }
947
+ declare const OG_THEME_META: readonly OgThemeMeta[];
948
+ /**
949
+ * Theme NGƯỜI DÙNG được chọn (anh Tú chốt 31/08): chỉ còn một cặp
950
+ * light/dark. Bốn theme còn lại vẫn tồn tại đầy đủ trong theme.css và
951
+ * setTheme() vẫn nhận — chúng dùng cho trang /themes của demo và cho
952
+ * harness screenshot chạy ma trận 6 theme; chỉ **giấu khỏi picker**.
953
+ * Muốn mở lại: thêm tên vào mảng này, không phải dựng lại token.
954
+ */
955
+ declare const OG_PICKER_THEMES: readonly OgTheme[];
956
+ /** OG_THEME_META đã lọc theo OG_PICKER_THEMES — nguồn duy nhất cho mọi picker. */
957
+ declare const OG_PICKER_THEME_META: readonly OgThemeMeta[];
958
+ /**
959
+ * V2 theme switching: one `data-og-theme` attribute on <html> selects the
960
+ * --og-* token block (theme.css). During the migration window the service
961
+ * also mirrors the legacy `light_theme` class on <body> so remotes built
962
+ * against the pre-V2 stylesheet keep resolving the correct palette
963
+ * (see the SKEW SHIELD note in theme.css).
964
+ */
744
965
  declare class ThemeService {
745
966
  private renderer;
746
967
  private lightClass;
747
968
  private theme$;
748
969
  themeStorageKey: string;
749
970
  constructor(rendererFactory: RendererFactory2);
971
+ /** Primary API: activate one of the six V2 themes. */
972
+ setTheme(theme: OgTheme): void;
973
+ themeChanges(): Observable<OgTheme>;
974
+ getCurrentTheme(): OgTheme;
975
+ isLight(): boolean;
976
+ /** @deprecated V2: use setTheme(). Maps light→porcelain, dark→charcoal. */
750
977
  setLightMode(enable: boolean): void;
978
+ /** @deprecated V2: use setTheme(). Flips between the two default themes. */
751
979
  toggleTheme(): void;
752
- themeChanges(): rxjs.Observable<"light" | "dark">;
753
- getCurrentTheme(): 'light' | 'dark';
754
- isLight(): boolean;
755
980
  getLogoPath(): string;
981
+ private isLightTheme;
982
+ private readSavedTheme;
756
983
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeService, never>;
757
984
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<ThemeService>;
758
985
  }
@@ -977,7 +1204,7 @@ declare class DndUploadComponent {
977
1204
  declare class ButtonComponent {
978
1205
  label: string;
979
1206
  readonly disabled: _angular_core.InputSignal<boolean>;
980
- readonly buttonVariant: _angular_core.InputSignal<"default" | "success" | "primary" | "alternative">;
1207
+ readonly buttonVariant: _angular_core.InputSignal<"default" | "success" | "primary" | "cta" | "alternative">;
981
1208
  icon?: any;
982
1209
  readonly class: _angular_core.InputSignal<any>;
983
1210
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -1059,6 +1286,9 @@ declare class LoadingPanel {
1059
1286
 
1060
1287
  declare class SearchBarComponent extends FxComponent<string> implements AfterViewInit {
1061
1288
  private ref;
1289
+ /** FxComponent leaves `value` undefined; without ngModel the input would
1290
+ render the literal string "undefined". */
1291
+ value: string;
1062
1292
  readonly placeholder: _angular_core.InputSignal<string>;
1063
1293
  readonly search: _angular_core.OutputEmitterRef<string>;
1064
1294
  readonly valueChange: _angular_core.OutputEmitterRef<string>;
@@ -1072,21 +1302,58 @@ declare class SearchBarComponent extends FxComponent<string> implements AfterVie
1072
1302
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SearchBarComponent, "fx-ui-search-bar", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, { "search": "search"; "valueChange": "valueChange"; }, never, never, true, never>;
1073
1303
  }
1074
1304
 
1305
+ /**
1306
+ * Một tab của `fx-ui-tab-group`.
1307
+ *
1308
+ * ⚠️ Nội dung tab PHẢI bọc trong `<ng-template>`:
1309
+ *
1310
+ * ```html
1311
+ * <fx-ui-tab [label]="'Components'">
1312
+ * <ng-template>
1313
+ * <app-info-components … />
1314
+ * </ng-template>
1315
+ * </fx-ui-tab>
1316
+ * ```
1317
+ *
1318
+ * Vì sao bắt buộc: trước đây tab dùng `<ng-content>` bọc trong `<ng-template>`
1319
+ * của CHÍNH nó. Cách đó **không hoãn được gì** — `<ng-content>` chỉ CHIẾU node,
1320
+ * còn node do view khai báo (component cha) tạo **eager**. Kết quả: mọi tab đều
1321
+ * khởi tạo và gọi API ngay khi vào màn, dù người dùng chưa mở (đo được trên
1322
+ * scan-info: cả 8 cụm cùng fetch). Nhận `TemplateRef` từ cha thì nội dung chỉ
1323
+ * được dựng khi tab-group stamp template đó.
1324
+ *
1325
+ * Hệ quả cần biết: đổi tab sẽ **huỷ** nội dung tab cũ và dựng lại khi quay lại
1326
+ * — đúng bản chất lazy, giống `matTabContent` của Material.
1327
+ *
1328
+ * `descendants: false` để chỉ bắt `<ng-template>` là con TRỰC TIẾP, tránh nuốt
1329
+ * nhầm template lồng sâu bên trong nội dung tab.
1330
+ */
1075
1331
  declare class TabComponent {
1076
1332
  readonly label: _angular_core.InputSignal<string>;
1077
1333
  icon?: string;
1334
+ /** Trailing count badge (V2 'page' variant); null/undefined hides it. */
1335
+ readonly count: _angular_core.InputSignal<number | null>;
1336
+ /** Tints the count badge (e.g. vulnerabilities tab shows a danger count). */
1337
+ readonly tone: _angular_core.InputSignal<Tone | null>;
1078
1338
  readonly content: _angular_core.Signal<TemplateRef<any>>;
1079
1339
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabComponent, never>;
1080
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TabComponent, "fx-ui-tab", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; }; }, {}, never, ["*"], true, never>;
1340
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TabComponent, "fx-ui-tab", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; }; "count": { "alias": "count"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; }, {}, ["content"], never, true, never>;
1081
1341
  }
1082
1342
 
1083
- declare class TabGroupComponent implements AfterContentInit {
1343
+ declare class TabGroupComponent implements AfterContentInit, AfterViewChecked, OnChanges {
1084
1344
  private renderer;
1085
1345
  private cdr;
1086
1346
  readonly tabs: _angular_core.Signal<readonly TabComponent[]>;
1087
1347
  activeIndex: number;
1348
+ /** Emitted on user selection — enables [(activeIndex)] two-way binding. */
1349
+ readonly activeIndexChange: _angular_core.OutputEmitterRef<number>;
1350
+ /** 'page' = the V2 workspace tab strip (larger hit area, count badges). */
1351
+ readonly variant: _angular_core.InputSignal<"default" | "page">;
1088
1352
  readonly tabListRef: _angular_core.Signal<ElementRef<HTMLElement>>;
1089
- readonly underlineRef: _angular_core.Signal<ElementRef<HTMLElement>>;
1353
+ readonly underlineRef: _angular_core.Signal<ElementRef<HTMLElement> | undefined>;
1354
+ readonly pagePillRef: _angular_core.Signal<ElementRef<HTMLElement> | undefined>;
1355
+ /** Last applied pill geometry — skip DOM writes when nothing moved. */
1356
+ private pillState;
1090
1357
  canScrollLeft: boolean;
1091
1358
  canScrollRight: boolean;
1092
1359
  private animateDelay;
@@ -1095,8 +1362,19 @@ declare class TabGroupComponent implements AfterContentInit {
1095
1362
  constructor(renderer: Renderer2);
1096
1363
  ngAfterContentInit(): void;
1097
1364
  selectTab(index: number): void;
1365
+ badgeClass(tab: TabComponent): string;
1098
1366
  /** Roving tablist keyboard nav: arrows move AND activate (selection follows focus). */
1099
1367
  onTabKeydown(event: KeyboardEvent, index: number): void;
1368
+ /** Parent-driven activeIndex (deep-link ?tab=, quick-links) must also move the pill. */
1369
+ ngOnChanges(changes: SimpleChanges): void;
1370
+ /**
1371
+ * Re-measure every view check: catches label-width changes (language switch,
1372
+ * count arriving) with cached geometry so the DOM write only happens when
1373
+ * the pill actually moved.
1374
+ */
1375
+ ngAfterViewChecked(): void;
1376
+ /** Slide the 'page' pill to the active tab (offset* is scroll-content relative). */
1377
+ private updatePagePill;
1100
1378
  private updateUnderlinePosition;
1101
1379
  private scrollToActiveTab;
1102
1380
  scroll(direction: 'left' | 'right'): void;
@@ -1104,7 +1382,7 @@ declare class TabGroupComponent implements AfterContentInit {
1104
1382
  private updateScrollButtons;
1105
1383
  onResize(): void;
1106
1384
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabGroupComponent, never>;
1107
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TabGroupComponent, "fx-ui-tab-group", never, { "activeIndex": { "alias": "activeIndex"; "required": false; }; }, {}, ["tabs"], never, true, never>;
1385
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TabGroupComponent, "fx-ui-tab-group", never, { "activeIndex": { "alias": "activeIndex"; "required": false; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, { "activeIndexChange": "activeIndexChange"; }, ["tabs"], never, true, never>;
1108
1386
  }
1109
1387
 
1110
1388
  /**
@@ -1217,13 +1495,6 @@ declare class SwitchComponent extends FxComponent<any> implements AfterViewInit
1217
1495
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SwitchComponent, "fx-ui-switch", never, { "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "onSwitch": "onSwitch"; }, never, never, true, never>;
1218
1496
  }
1219
1497
 
1220
- declare class SkeletonTableLoadingComponent {
1221
- readonly columns: _angular_core.InputSignal<number>;
1222
- readonly rows: _angular_core.InputSignal<number>;
1223
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonTableLoadingComponent, never>;
1224
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonTableLoadingComponent, "fx-ui-skeleton-table-loading", never, { "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1225
- }
1226
-
1227
1498
  declare class CircleProgressBar {
1228
1499
  readonly percent: _angular_core.InputSignal<number>;
1229
1500
  readonly showPercent: _angular_core.InputSignal<boolean>;
@@ -1304,6 +1575,8 @@ interface DrawerItem {
1304
1575
  id: string;
1305
1576
  label: string;
1306
1577
  icon: string;
1578
+ /** V2: renders as a non-interactive section caption (flat nav, no accordion). */
1579
+ heading?: boolean;
1307
1580
  route?: string;
1308
1581
  children?: DrawerItem[];
1309
1582
  action?: () => void;
@@ -1313,8 +1586,15 @@ declare class DrawerComponent implements OnInit, OnDestroy {
1313
1586
  private router;
1314
1587
  private cdr;
1315
1588
  readonly items: _angular_core.InputSignal<DrawerItem[]>;
1589
+ /** V2: bottom-pinned section (Administration group) — same item rendering,
1590
+ separated by a rule, above the [drawerFooter] slot and version. */
1591
+ readonly footerItems: _angular_core.InputSignal<DrawerItem[]>;
1316
1592
  isExpanded: boolean;
1317
1593
  logo?: string;
1594
+ /** Wordmark cạnh logo, chỉ hiện khi drawer mở. Bỏ trống = chỉ có mark. */
1595
+ logoText?: string;
1596
+ /** Dòng phụ dưới logoText (tagline/workspace). Chỉ hiện khi drawer mở. */
1597
+ logoSubtext?: string;
1318
1598
  version?: string;
1319
1599
  readonly toggleExpanded: _angular_core.OutputEmitterRef<boolean>;
1320
1600
  readonly itemClicked: _angular_core.OutputEmitterRef<DrawerItem>;
@@ -1334,13 +1614,14 @@ declare class DrawerComponent implements OnInit, OnDestroy {
1334
1614
  getAccordionState(itemId: string): string;
1335
1615
  getDrawerState(): string;
1336
1616
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DrawerComponent, never>;
1337
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DrawerComponent, "fx-ui-drawer", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "isExpanded": { "alias": "isExpanded"; "required": false; }; "logo": { "alias": "logo"; "required": false; }; "version": { "alias": "version"; "required": false; }; }, { "toggleExpanded": "toggleExpanded"; "itemClicked": "itemClicked"; }, never, never, true, never>;
1617
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DrawerComponent, "fx-ui-drawer", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "footerItems": { "alias": "footerItems"; "required": false; "isSignal": true; }; "isExpanded": { "alias": "isExpanded"; "required": false; }; "logo": { "alias": "logo"; "required": false; }; "logoText": { "alias": "logoText"; "required": false; }; "logoSubtext": { "alias": "logoSubtext"; "required": false; }; "version": { "alias": "version"; "required": false; }; }, { "toggleExpanded": "toggleExpanded"; "itemClicked": "itemClicked"; }, never, ["[drawerFooter]"], true, never>;
1338
1618
  }
1339
1619
 
1340
1620
  /** Row-card skeleton placeholder for master-detail list panes. */
1341
1621
  declare class SkeletonListComponent {
1342
1622
  readonly rows: _angular_core.InputSignal<number>;
1343
- range(n: number): number[];
1623
+ /** computed, không phải method: method trả mảng MỚI mỗi lần render. */
1624
+ readonly rowList: _angular_core.Signal<number[]>;
1344
1625
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonListComponent, never>;
1345
1626
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonListComponent, "fx-ui-skeleton-list", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1346
1627
  }
@@ -1351,12 +1632,21 @@ declare class SkeletonDetailComponent {
1351
1632
  readonly cards: _angular_core.InputSignal<number>;
1352
1633
  /** Rows per content card. */
1353
1634
  readonly rows: _angular_core.InputSignal<number>;
1354
- range(n: number): number[];
1635
+ /** computed, không phải method: method trả mảng MỚI mỗi lần render. */
1636
+ readonly cardList: _angular_core.Signal<number[]>;
1637
+ readonly rowList: _angular_core.Signal<number[]>;
1355
1638
  rowWidth(i: number): number;
1356
1639
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonDetailComponent, never>;
1357
1640
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonDetailComponent, "fx-ui-skeleton-detail", never, { "cards": { "alias": "cards"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1358
1641
  }
1359
1642
 
1643
+ interface FxStatCardDelta {
1644
+ /** Caller-formatted delta text (e.g. "+12%", "-3"). */
1645
+ value: string;
1646
+ direction: 'up' | 'down';
1647
+ /** Delta colour — up is not always good (findings up = danger). */
1648
+ tone?: Tone | null;
1649
+ }
1360
1650
  interface FxStatCard {
1361
1651
  /** Caller-translated caption. */
1362
1652
  label: string;
@@ -1365,17 +1655,33 @@ interface FxStatCard {
1365
1655
  icon?: string;
1366
1656
  /** Colours the number and the icon box; null/undefined renders neutral. */
1367
1657
  tone?: Tone | null;
1658
+ /** V2 StatGrid: trend chip beside the number. */
1659
+ delta?: FxStatCardDelta;
1660
+ /** V2 StatGrid: mini bar-trend under the caption. */
1661
+ spark?: number[];
1662
+ /** variant 'figure': caller-formatted sub-caption under the number ("+1 since 4.8.0"). */
1663
+ sub?: string;
1664
+ /** Colours the sub-caption; null/undefined renders muted. */
1665
+ subTone?: Tone | null;
1368
1666
  }
1369
1667
  /** KPI tile row: big number + tinted icon box + caption, in a responsive grid. */
1370
1668
  declare class StatCardsComponent {
1371
1669
  readonly cards: _angular_core.InputSignal<FxStatCard[]>;
1670
+ /**
1671
+ * 'tile' (default): tinted icon box + number + caption — the pre-V2 look.
1672
+ * 'figure': the V2 design's KPI column — caption on top, large figure-font
1673
+ * number, toned sub-caption underneath (no icon box).
1674
+ */
1675
+ readonly variant: _angular_core.InputSignal<"figure" | "tile">;
1372
1676
  /** Grid columns; defaults to one column per card. */
1373
1677
  cols?: number;
1374
1678
  get gridColumns(): string;
1375
1679
  numClass(card: FxStatCard): string;
1376
1680
  boxClass(card: FxStatCard): string;
1681
+ deltaClass(card: FxStatCard): string;
1682
+ subClass(card: FxStatCard): string;
1377
1683
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatCardsComponent, never>;
1378
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatCardsComponent, "fx-ui-stat-cards", never, { "cards": { "alias": "cards"; "required": false; "isSignal": true; }; "cols": { "alias": "cols"; "required": false; }; }, {}, never, never, true, never>;
1684
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatCardsComponent, "fx-ui-stat-cards", never, { "cards": { "alias": "cards"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "cols": { "alias": "cols"; "required": false; }; }, {}, never, never, true, never>;
1379
1685
  }
1380
1686
 
1381
1687
  /** Centered "no data" block. The message is caller-translated (no i18n in lib). */
@@ -1412,6 +1718,106 @@ declare class FilterChipsComponent {
1412
1718
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FilterChipsComponent, "fx-ui-filter-chips", never, { "options": { "alias": "options"; "required": false; }; "value": { "alias": "value"; "required": false; }; "toneOverrides": { "alias": "toneOverrides"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
1413
1719
  }
1414
1720
 
1721
+ interface FxFilterPillOption {
1722
+ /** '' (empty) is the conventional "All" pill. */
1723
+ value: string;
1724
+ /** Caller-translated label. */
1725
+ label: string;
1726
+ /** Shown muted beside the label; null/undefined renders no count. */
1727
+ count?: number | null;
1728
+ }
1729
+ /**
1730
+ * V2 filter pills — the quick-filter row above ranked lists (design refs 02,
1731
+ * 03, 11): outlined capsules with a muted count, the active one filled with
1732
+ * the primary text colour.
1733
+ *
1734
+ * Distinct from `fx-ui-filter-chips`, which tints each chip by its severity
1735
+ * tone and carries no count. Presentational: the caller owns the filter state.
1736
+ *
1737
+ * <fx-ui-filter-pills [options]="pills" [value]="filters.status"
1738
+ * (valueChange)="filters.status = $event; refresh()" />
1739
+ */
1740
+ declare class FilterPillsComponent {
1741
+ readonly options: _angular_core.InputSignal<FxFilterPillOption[]>;
1742
+ /** Accepts undefined so screens can bind an optional filter-bag key. */
1743
+ readonly value: _angular_core.InputSignal<string | undefined>;
1744
+ readonly valueChange: _angular_core.OutputEmitterRef<string>;
1745
+ isActive(option: FxFilterPillOption): boolean;
1746
+ /**
1747
+ * Pill ĐANG CHỌN dùng **accent** (xanh), không phải nền đen — khớp demo:
1748
+ * design ref 11 vẽ pill "All 40" là pill accent. Nền đen `--og-text` chỉ
1749
+ * dành cho badge severity Critical (`.og-badge--solid`), không dùng cho
1750
+ * trạng thái chọn của filter (anh Tú chốt 03/09).
1751
+ */
1752
+ pillClass(option: FxFilterPillOption): string;
1753
+ countClass(option: FxFilterPillOption): string;
1754
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FilterPillsComponent, never>;
1755
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FilterPillsComponent, "fx-ui-filter-pills", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
1756
+ }
1757
+
1758
+ /**
1759
+ * V2 stage progress dots — the walkthrough position indicator on the attack
1760
+ * chain toolbar (design refs 04, 07): one dot per stage, the current one drawn
1761
+ * as a wider accent bar, visited ones solid, the rest faint.
1762
+ *
1763
+ * <fx-ui-stage-dots [count]="8" [current]="stageIndex()"
1764
+ * (dotClick)="goToStage($event)" />
1765
+ */
1766
+ declare class StageDotsComponent {
1767
+ readonly count: _angular_core.InputSignal<number>;
1768
+ /** 0-based current stage; -1 (default) means none selected yet. */
1769
+ readonly current: _angular_core.InputSignal<number>;
1770
+ /** Emit the clicked stage index; wire it to make the dots navigable. */
1771
+ readonly dotClick: _angular_core.OutputEmitterRef<number>;
1772
+ readonly dots: _angular_core.Signal<number[]>;
1773
+ dotClass(index: number): string;
1774
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StageDotsComponent, never>;
1775
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StageDotsComponent, "fx-ui-stage-dots", never, { "count": { "alias": "count"; "required": false; "isSignal": true; }; "current": { "alias": "current"; "required": false; "isSignal": true; }; }, { "dotClick": "dotClick"; }, never, never, true, never>;
1776
+ }
1777
+
1778
+ /**
1779
+ * V2 evidence code block — the mono panel that carries a process tree, a
1780
+ * command line or any captured text (design ref 05, "Process tree").
1781
+ *
1782
+ * Whitespace is preserved and the box scrolls on its own rather than pushing
1783
+ * the page wide, so ASCII trees survive narrow viewports.
1784
+ *
1785
+ * <fx-ui-code-block [label]="'analyze.processTree' | translate" [code]="tree" />
1786
+ */
1787
+ declare class CodeBlockComponent {
1788
+ readonly code: _angular_core.InputSignal<string>;
1789
+ /** Caller-translated caption above the box; omit for a bare block. */
1790
+ readonly label: _angular_core.InputSignal<string>;
1791
+ /** Scroll cap; empty grows with the content. */
1792
+ readonly maxHeight: _angular_core.InputSignal<string>;
1793
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CodeBlockComponent, never>;
1794
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CodeBlockComponent, "fx-ui-code-block", never, { "code": { "alias": "code"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1795
+ }
1796
+
1797
+ /**
1798
+ * V2 captured-evidence frame — a faux window chrome (traffic lights + mono file
1799
+ * name + timestamp) around a screenshot, with a placeholder when the image is
1800
+ * missing (design ref 05, "Screenshot").
1801
+ *
1802
+ * <fx-ui-screenshot-frame [label]="'analyze.screenshot' | translate"
1803
+ * fileName="chain-05.png" timestamp="09:42:18"
1804
+ * [src]="url" [caption]="caption" />
1805
+ */
1806
+ declare class ScreenshotFrameComponent {
1807
+ /** Caller-translated caption above the frame; omit for a bare frame. */
1808
+ readonly label: _angular_core.InputSignal<string>;
1809
+ readonly fileName: _angular_core.InputSignal<string>;
1810
+ readonly timestamp: _angular_core.InputSignal<string>;
1811
+ /** Image URL; empty renders the placeholder body. */
1812
+ readonly src: _angular_core.InputSignal<string>;
1813
+ /** Caller-translated line under (or inside) the frame. */
1814
+ readonly caption: _angular_core.InputSignal<string>;
1815
+ readonly alt: _angular_core.InputSignal<string>;
1816
+ readonly height: _angular_core.InputSignal<string>;
1817
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ScreenshotFrameComponent, never>;
1818
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ScreenshotFrameComponent, "fx-ui-screenshot-frame", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "fileName": { "alias": "fileName"; "required": false; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": false; "isSignal": true; }; "src": { "alias": "src"; "required": false; "isSignal": true; }; "caption": { "alias": "caption"; "required": false; "isSignal": true; }; "alt": { "alias": "alt"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1819
+ }
1820
+
1415
1821
  /** Thin tone-coloured progress/score bar with optional label and caption. */
1416
1822
  declare class MeterComponent {
1417
1823
  value: number;
@@ -1426,16 +1832,24 @@ declare class MeterComponent {
1426
1832
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MeterComponent, "fx-ui-meter", never, { "value": { "alias": "value"; "required": false; }; "max": { "alias": "max"; "required": false; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; }; "caption": { "alias": "caption"; "required": false; }; }, {}, never, never, true, never>;
1427
1833
  }
1428
1834
 
1429
- /** Detail-panel section: card with an icon + heading header and projected body. */
1835
+ /**
1836
+ * Panel section: card with a header and projected body.
1837
+ * - titleStyle 'heading' (default): icon + heading, the pre-V2 look
1838
+ * - titleStyle 'eyebrow': the V2 design's panel header — small tracked
1839
+ * caption on the left, muted [aside] text on the right
1840
+ */
1430
1841
  declare class SectionCardComponent {
1431
1842
  /** Caller-translated heading. */
1432
1843
  readonly title: _angular_core.InputSignal<string>;
1433
1844
  /** hero-icon name; omitted → text-only header. */
1434
1845
  icon?: any;
1435
1846
  readonly iconTone: _angular_core.InputSignal<Tone | null>;
1847
+ readonly titleStyle: _angular_core.InputSignal<"heading" | "eyebrow">;
1848
+ /** Caller-translated right-aligned hint (eyebrow style). */
1849
+ readonly aside: _angular_core.InputSignal<string>;
1436
1850
  get iconClass(): string;
1437
1851
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SectionCardComponent, never>;
1438
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionCardComponent, "fx-ui-section-card", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; }; "iconTone": { "alias": "iconTone"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1852
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionCardComponent, "fx-ui-section-card", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; }; "iconTone": { "alias": "iconTone"; "required": false; "isSignal": true; }; "titleStyle": { "alias": "titleStyle"; "required": false; "isSignal": true; }; "aside": { "alias": "aside"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1439
1853
  }
1440
1854
 
1441
1855
  /**
@@ -1490,11 +1904,13 @@ declare class SeverityBadgesComponent {
1490
1904
  }
1491
1905
 
1492
1906
  /**
1493
- * Two-column master-detail shell driven by a BaseMasterDetailComponent.
1494
- * The host page projects its own header/filters and supplies templates for
1495
- * the parts that vary per entity:
1907
+ * Master-detail shell driven by a BaseMasterDetailComponent. Two-column by
1908
+ * default; projecting a [mdFacets] block (V2 lookup screens) adds a third
1909
+ * facets-rail column before the list. The host page projects its own
1910
+ * header/filters and supplies templates for the parts that vary per entity:
1496
1911
  *
1497
1912
  * <fx-ui-master-detail [table]="this" [emptyMessage]="'noData' | translate">
1913
+ * <div mdFacets>…<fx-ui-facets-rail …/>…</div> <!-- optional, V2 -->
1498
1914
  * <div mdHeader>…title / stat cards…</div>
1499
1915
  * <div mdFilters>…search bar / filter chips…</div>
1500
1916
  * <ng-template #row let-item let-selected="selected">…row body…</ng-template>
@@ -1504,26 +1920,45 @@ declare class SeverityBadgesComponent {
1504
1920
  * The list behaves as a single-select listbox: the selected option is the
1505
1921
  * tab stop, ArrowUp/Down/Home/End move the selection.
1506
1922
  */
1507
- declare class MasterDetailComponent implements AfterViewInit {
1923
+ declare class MasterDetailComponent implements AfterViewInit, AfterContentInit {
1924
+ private hostEl;
1925
+ /** True when the host projected a [mdFacets] block — switches to 3 columns. */
1926
+ hasFacets: boolean;
1508
1927
  table: BaseMasterDetailComponent<any>;
1509
1928
  /** Fixed list-pane width on lg+ viewports (stacked full-width below). */
1510
1929
  readonly listWidth: _angular_core.InputSignal<string>;
1511
- readonly maxListHeight: _angular_core.InputSignal<string>;
1930
+ /**
1931
+ * Chiều cao CHUNG của cả ba cụm (facets / list / detail). Mặc định trừ phần
1932
+ * chrome phía trên (topbar + tab strip + context line) khỏi viewport để
1933
+ * bảng ba cột vừa đúng một màn, không kéo trang cuộn theo.
1934
+ * Chỉ có tác dụng từ 1080px — xem `.fx-md-row` trong CSS.
1935
+ */
1936
+ readonly paneHeight: _angular_core.InputSignal<string>;
1512
1937
  readonly pageSizeOptions: _angular_core.InputSignal<number[]>;
1513
1938
  /** Labels come in via inputs — the lib carries no i18n. */
1514
1939
  readonly emptyMessage: _angular_core.InputSignal<string>;
1515
1940
  readonly listLabel: _angular_core.InputSignal<string>;
1516
1941
  readonly skeletonCards: _angular_core.InputSignal<number>;
1942
+ /** 'prevnext' renders the V2 "X of Y" + Prev/Next controls instead of the
1943
+ Material paginator (which stays in the DOM, hidden — it is the paging
1944
+ engine BaseTable subscribes to). */
1945
+ readonly paginationStyle: _angular_core.InputSignal<"paginator" | "prevnext">;
1946
+ /** Caller-translated Prev/Next labels ("X of Y" is numeric). */
1947
+ readonly prevLabel: _angular_core.InputSignal<string>;
1948
+ readonly nextLabel: _angular_core.InputSignal<string>;
1517
1949
  readonly rowTemplate: _angular_core.Signal<TemplateRef<any>>;
1518
1950
  readonly detailTemplate: _angular_core.Signal<TemplateRef<any>>;
1519
1951
  readonly paginator: _angular_core.Signal<MatPaginator>;
1520
1952
  readonly uid: string;
1953
+ ngAfterContentInit(): void;
1521
1954
  ngAfterViewInit(): void;
1955
+ /** "X of Y" range text for the prevnext pagination style. */
1956
+ rangeText(): string;
1522
1957
  isSelected(row: any): boolean;
1523
1958
  optionId(index: number): string;
1524
1959
  onKeydown(event: KeyboardEvent, index: number): void;
1525
1960
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MasterDetailComponent, never>;
1526
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MasterDetailComponent, "fx-ui-master-detail", never, { "table": { "alias": "table"; "required": false; }; "listWidth": { "alias": "listWidth"; "required": false; "isSignal": true; }; "maxListHeight": { "alias": "maxListHeight"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "listLabel": { "alias": "listLabel"; "required": false; "isSignal": true; }; "skeletonCards": { "alias": "skeletonCards"; "required": false; "isSignal": true; }; }, {}, ["rowTemplate", "detailTemplate"], ["[mdHeader]", "[mdFilters]"], true, never>;
1961
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MasterDetailComponent, "fx-ui-master-detail", never, { "table": { "alias": "table"; "required": false; }; "listWidth": { "alias": "listWidth"; "required": false; "isSignal": true; }; "paneHeight": { "alias": "paneHeight"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "listLabel": { "alias": "listLabel"; "required": false; "isSignal": true; }; "skeletonCards": { "alias": "skeletonCards"; "required": false; "isSignal": true; }; "paginationStyle": { "alias": "paginationStyle"; "required": false; "isSignal": true; }; "prevLabel": { "alias": "prevLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; }, {}, ["rowTemplate", "detailTemplate"], ["[mdFacets]", "[mdHeader]", "[mdFilters]"], true, never>;
1527
1962
  }
1528
1963
 
1529
1964
  interface FxMenuItem {
@@ -1557,6 +1992,432 @@ declare class MenuComponent {
1557
1992
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MenuComponent, "fx-ui-menu", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "select": "select"; }, never, ["*"], true, never>;
1558
1993
  }
1559
1994
 
1995
+ /**
1996
+ * V2 theme picker — dropdown các theme OgeniumDashboards cho chọn
1997
+ * (OG_PICKER_THEME_META: porcelain/charcoal), mỗi dòng có swatch accent +
1998
+ * page. Drives ThemeService.setTheme(); replaces the pre-V2 sun/moon toggle
1999
+ * (behavior-layer rule: mat-menu stays inside the lib, apps never import
2000
+ * @angular/material directly).
2001
+ *
2002
+ * <fx-ui-theme-picker />
2003
+ */
2004
+ declare class ThemePickerComponent {
2005
+ private themeService;
2006
+ readonly themes: readonly OgThemeMeta[];
2007
+ readonly current: _angular_core.Signal<OgTheme>;
2008
+ /** Tra trên bộ ĐẦY ĐỦ: theme đang active có thể là một trong 4 theme đã ẩn
2009
+ khỏi picker (deep-link /themes, localStorage cũ) — nhãn vẫn phải đúng. */
2010
+ currentMeta(): OgThemeMeta;
2011
+ select(theme: OgTheme): void;
2012
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemePickerComponent, never>;
2013
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ThemePickerComponent, "fx-ui-theme-picker", never, {}, {}, never, never, true, never>;
2014
+ }
2015
+
2016
+ /**
2017
+ * "Waiting on the backend" marker (anh Tú 29/08).
2018
+ *
2019
+ * Put this on any UI the V2 design calls for but no endpoint feeds yet, so the
2020
+ * gap is visible in the product instead of living only in a backlog file.
2021
+ * `grep -r "fx-ui-pending-badge"` then lists every outstanding field.
2022
+ *
2023
+ * <fx-ui-pending-badge [field]="'confirmed-chains weekly series'" />
2024
+ *
2025
+ * Keep the copy factual: it states that data is missing, never fakes a value.
2026
+ */
2027
+ declare class PendingBadgeComponent {
2028
+ /** Caller-translated chip text. */
2029
+ readonly label: _angular_core.InputSignal<string>;
2030
+ /**
2031
+ * What exactly is missing — shown as the title tooltip so a reviewer can read
2032
+ * the required field without opening the code.
2033
+ */
2034
+ readonly field: _angular_core.InputSignal<string>;
2035
+ /** 'chip' (default) sits inline; 'dot' is a bare marker for dense rows. */
2036
+ readonly variant: _angular_core.InputSignal<"chip" | "dot">;
2037
+ get tooltip(): string;
2038
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PendingBadgeComponent, never>;
2039
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PendingBadgeComponent, "fx-ui-pending-badge", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "field": { "alias": "field"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2040
+ }
2041
+
2042
+ /**
2043
+ * Wraps UI that is rendered from PLACEHOLDER data so the layout can be
2044
+ * reviewed before its endpoint exists (anh Tú 29/08: "muốn có full giao diện
2045
+ * trước để review").
2046
+ *
2047
+ * The frame makes the status unmistakable — dashed outline, a corner label and
2048
+ * the pending marker naming the missing field — so sample shapes can never be
2049
+ * mistaken for measured values. Drop the wrapper (and the sample input) the
2050
+ * moment the API lands.
2051
+ *
2052
+ * The pending chip is inlined rather than composed from fx-ui-pending-badge:
2053
+ * one lib component importing another inside the same barrel tripped NG0919
2054
+ * (metadata read before definition) in consuming apps.
2055
+ *
2056
+ * <fx-ui-sample-frame [field]="'weekly activity'" [label]="'Sample layout'">
2057
+ * …chart rendered from sample series…
2058
+ * </fx-ui-sample-frame>
2059
+ */
2060
+ declare class SampleFrameComponent {
2061
+ /** Caller-translated corner label. */
2062
+ readonly label: _angular_core.InputSignal<string>;
2063
+ /** Field the backend still owes — shown on the pending badge tooltip. */
2064
+ readonly field: _angular_core.InputSignal<string>;
2065
+ /** Caller-translated pending-chip text. */
2066
+ readonly pendingLabel: _angular_core.InputSignal<string>;
2067
+ get tooltip(): string;
2068
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SampleFrameComponent, never>;
2069
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SampleFrameComponent, "fx-ui-sample-frame", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "field": { "alias": "field"; "required": false; "isSignal": true; }; "pendingLabel": { "alias": "pendingLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2070
+ }
2071
+
2072
+ /**
2073
+ * V2 score badge — the risk/score chip used on attack-path rows, dashboard
2074
+ * panels and project tiles. Colour comes from the 0–100 risk band unless an
2075
+ * explicit tone is given (bands: ≥90 critical, ≥70 danger, ≥40 warning, else
2076
+ * success — same thresholds as value-tone's scoreTone on a 0–100 scale).
2077
+ */
2078
+ declare class ScoreBadgeComponent {
2079
+ readonly score: _angular_core.InputSignal<string | number>;
2080
+ /** Denominator shown as "98 / 100"; omit for a bare score. */
2081
+ readonly outOf: _angular_core.InputSignal<number | null>;
2082
+ /** Overrides the band-derived tone. */
2083
+ readonly tone: _angular_core.InputSignal<Tone | null>;
2084
+ readonly size: _angular_core.InputSignal<"sm" | "md" | "lg">;
2085
+ readonly resolvedTone: _angular_core.Signal<Tone | null>;
2086
+ badgeClass(): string;
2087
+ sizeClass(): string;
2088
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ScoreBadgeComponent, never>;
2089
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ScoreBadgeComponent, "fx-ui-score-badge", never, { "score": { "alias": "score"; "required": true; "isSignal": true; }; "outOf": { "alias": "outOf"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2090
+ }
2091
+
2092
+ /**
2093
+ * V2 StatusDot — tiny tone-coloured indicator used in list rows, project
2094
+ * cards and stat grids. Optional pulse for "live" states (running scans).
2095
+ *
2096
+ * <fx-ui-status-dot tone="success" />
2097
+ * <fx-ui-status-dot tone="warning" [pulse]="true" />
2098
+ */
2099
+ declare class StatusDotComponent {
2100
+ readonly tone: _angular_core.InputSignal<Tone | null>;
2101
+ /** Diameter in px. */
2102
+ readonly size: _angular_core.InputSignal<number>;
2103
+ readonly pulse: _angular_core.InputSignal<boolean>;
2104
+ dotClass(): string;
2105
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatusDotComponent, never>;
2106
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusDotComponent, "fx-ui-status-dot", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "pulse": { "alias": "pulse"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2107
+ }
2108
+
2109
+ /**
2110
+ * V2 sparkbar — inline mini bar-trend (risk trend on project cards, deltas in
2111
+ * stat grids). Pure DOM, token-coloured; no chart engine.
2112
+ *
2113
+ * <fx-ui-sparkbar [values]="[3, 5, 2, 8, 6]" />
2114
+ */
2115
+ declare class SparkbarComponent {
2116
+ readonly values: _angular_core.InputSignal<number[]>;
2117
+ /** Bar colour; null renders the accent. */
2118
+ readonly tone: _angular_core.InputSignal<Tone | null>;
2119
+ readonly height: _angular_core.InputSignal<number>;
2120
+ readonly bars: _angular_core.Signal<number[]>;
2121
+ barClass(): string;
2122
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkbarComponent, never>;
2123
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkbarComponent, "fx-ui-sparkbar", never, { "values": { "alias": "values"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2124
+ }
2125
+
2126
+ interface FxSegmentedOption {
2127
+ value: string | number;
2128
+ /** Caller-translated label. */
2129
+ label: string;
2130
+ /** Optional hero-icon before the label. */
2131
+ icon?: string;
2132
+ /** Optional trailing count chip. */
2133
+ count?: number;
2134
+ disabled?: boolean;
2135
+ }
2136
+ /**
2137
+ * V2 segmented control — mode toggles (Essentials/Advanced), Catalog/Table
2138
+ * view switches, sub-navigation inside a tab. Generic n-option control; the
2139
+ * semantics live with the caller.
2140
+ *
2141
+ * Rendered as a compact pill group (anh Tú 29/08): equal-width options inside
2142
+ * a rounded-full track, with a single "thumb" that SLIDES to the active
2143
+ * option (transform transition — no per-button background repaint).
2144
+ *
2145
+ * <fx-ui-segmented [options]="modes" [(value)]="mode" />
2146
+ */
2147
+ declare class SegmentedComponent {
2148
+ readonly options: _angular_core.InputSignal<FxSegmentedOption[]>;
2149
+ readonly value: _angular_core.ModelSignal<string | number | null>;
2150
+ /** Accessible name for the group. */
2151
+ readonly ariaLabel: _angular_core.InputSignal<string>;
2152
+ /**
2153
+ * Both variants share the pill shape; they differ in the thumb fill:
2154
+ * 'default': raised surface thumb — view switches (Catalog/Table, ref 10).
2155
+ * 'pill': accent-filled thumb — the Essential/Advanced depth toggle
2156
+ * (design refs 04/05).
2157
+ */
2158
+ readonly variant: _angular_core.InputSignal<"default" | "pill">;
2159
+ /** Index the sliding thumb sits on; -1 hides it (no/unknown selection). */
2160
+ readonly activeIndex: _angular_core.Signal<number>;
2161
+ /** Equal-width tracks → the thumb is 1/n of the inner width and slides by
2162
+ * multiples of its own width. Pure CSS transform, nothing to measure. */
2163
+ readonly thumbWidth: _angular_core.Signal<string>;
2164
+ readonly thumbTransform: _angular_core.Signal<string>;
2165
+ select(option: FxSegmentedOption): void;
2166
+ thumbClass(): string;
2167
+ optionClass(option: FxSegmentedOption): string;
2168
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SegmentedComponent, never>;
2169
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SegmentedComponent, "fx-ui-segmented", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
2170
+ }
2171
+
2172
+ interface FxListRowBadge {
2173
+ /** Caller-translated label. */
2174
+ label: string;
2175
+ tone?: Tone | null;
2176
+ }
2177
+ /**
2178
+ * V2 ListRow — presentational body for master-detail #row templates and other
2179
+ * selectable lists: status dot + title, trailing badges, meta line. Extra
2180
+ * content projects below the meta line.
2181
+ *
2182
+ * <ng-template #row let-item>
2183
+ * <fx-ui-list-row
2184
+ * [title]="item.name"
2185
+ * [meta]="item.version + ' · ' + item.date"
2186
+ * [dotTone]="statusTone(item)"
2187
+ * [badges]="[{ label: item.severity, tone: severityTone(item.severity) }]"
2188
+ * />
2189
+ * </ng-template>
2190
+ */
2191
+ declare class ListRowComponent {
2192
+ readonly title: _angular_core.InputSignal<string>;
2193
+ readonly meta: _angular_core.InputSignal<string>;
2194
+ readonly badges: _angular_core.InputSignal<FxListRowBadge[]>;
2195
+ readonly dotTone: _angular_core.InputSignal<Tone | null | undefined>;
2196
+ readonly dotPulse: _angular_core.InputSignal<boolean>;
2197
+ badgeClass(badge: FxListRowBadge): string;
2198
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ListRowComponent, never>;
2199
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ListRowComponent, "fx-ui-list-row", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "badges": { "alias": "badges"; "required": false; "isSignal": true; }; "dotTone": { "alias": "dotTone"; "required": false; "isSignal": true; }; "dotPulse": { "alias": "dotPulse"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2200
+ }
2201
+
2202
+ interface FxBarListItem {
2203
+ /** Caller-translated label. */
2204
+ label: string;
2205
+ value: number;
2206
+ /** Shown instead of the raw value (e.g. "9.8", "82%"). */
2207
+ valueLabel?: string;
2208
+ /** Bar colour; null/undefined renders the accent. */
2209
+ tone?: Tone | null;
2210
+ /** Secondary line under the label. */
2211
+ meta?: string;
2212
+ /** Free-form identifier handed back on (select). */
2213
+ data?: any;
2214
+ }
2215
+ /**
2216
+ * V2 BarList — ranked horizontal bars ("Top projects by risk", "Top critical
2217
+ * attack paths"). Pure DOM (accessible, token-native, clickable) — charts via
2218
+ * ECharts are for time series, not rankings.
2219
+ *
2220
+ * <fx-ui-bar-list [items]="topRisk" (select)="open($event)" />
2221
+ */
2222
+ declare class BarListComponent {
2223
+ readonly items: _angular_core.InputSignal<FxBarListItem[]>;
2224
+ /** Rows render as buttons only when true (a (select) listener exists). */
2225
+ readonly interactive: _angular_core.InputSignal<boolean>;
2226
+ readonly select: _angular_core.OutputEmitterRef<FxBarListItem>;
2227
+ readonly max: _angular_core.Signal<number>;
2228
+ widthOf(item: FxBarListItem): number;
2229
+ barClass(item: FxBarListItem): string;
2230
+ onSelect(item: FxBarListItem): void;
2231
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BarListComponent, never>;
2232
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BarListComponent, "fx-ui-bar-list", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, { "select": "select"; }, never, never, true, never>;
2233
+ }
2234
+
2235
+ interface FxFacetOption {
2236
+ value: string | number;
2237
+ /** Caller-translated label. */
2238
+ label: string;
2239
+ count?: number;
2240
+ /** Optional tone dot before the label (severity facets). */
2241
+ tone?: Tone | null;
2242
+ }
2243
+ interface FxFacetGroup {
2244
+ id: string;
2245
+ /** Caller-translated group heading. */
2246
+ label: string;
2247
+ /** Multi-select (checkbox semantics); default single-select toggle. */
2248
+ multi?: boolean;
2249
+ options: FxFacetOption[];
2250
+ }
2251
+ type FxFacetSelection = Record<string, (string | number)[]>;
2252
+ /**
2253
+ * V2 facets rail — the first column of 3-column lookup screens: filter groups
2254
+ * with counts + a Reset link. Presentational: filtering itself stays in the
2255
+ * page (feed the emitted selection into BaseMasterDetail filters).
2256
+ *
2257
+ * <div mdFacets>
2258
+ * <fx-ui-facets-rail [groups]="facetGroups" [selection]="facets"
2259
+ * (selectionChange)="onFacets($event)" />
2260
+ * </div>
2261
+ */
2262
+ declare class FacetsRailComponent {
2263
+ readonly groups: _angular_core.InputSignal<FxFacetGroup[]>;
2264
+ readonly selection: _angular_core.InputSignal<FxFacetSelection>;
2265
+ /** Caller-translated label for the reset affordance. */
2266
+ readonly resetLabel: _angular_core.InputSignal<string>;
2267
+ readonly selectionChange: _angular_core.OutputEmitterRef<FxFacetSelection>;
2268
+ readonly hasSelection: _angular_core.Signal<boolean>;
2269
+ isSelected(group: FxFacetGroup, option: FxFacetOption): boolean;
2270
+ toggle(group: FxFacetGroup, option: FxFacetOption): void;
2271
+ reset(): void;
2272
+ toneClass(option: FxFacetOption): string;
2273
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FacetsRailComponent, never>;
2274
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FacetsRailComponent, "fx-ui-facets-rail", never, { "groups": { "alias": "groups"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "resetLabel": { "alias": "resetLabel"; "required": false; "isSignal": true; }; }, { "selectionChange": "selectionChange"; }, never, never, true, never>;
2275
+ }
2276
+
2277
+ interface FxProjectCardChip {
2278
+ /** Caller-translated label. */
2279
+ label: string;
2280
+ tone?: Tone | null;
2281
+ }
2282
+ interface FxProjectCardMetric {
2283
+ /** Caller-formatted figure ("128", "--"). */
2284
+ value: string | number;
2285
+ /** Caller-translated caption under the figure. */
2286
+ label: string;
2287
+ }
2288
+ interface FxProjectCard {
2289
+ name: string;
2290
+ description?: string;
2291
+ /** 1–2 char initials rendered in an accent-soft square (design 12). */
2292
+ avatar?: string;
2293
+ /** Small line under the name (schedule / scope) with an optional hero-icon. */
2294
+ sub?: {
2295
+ icon?: string;
2296
+ label: string;
2297
+ };
2298
+ /** Score chip top-right ("High · 82"); rendered as a toned pill. */
2299
+ score?: string | number;
2300
+ scoreTone?: Tone | null;
2301
+ /** Caption under the score chip (kept for pre-V2 callers). */
2302
+ scoreLabel?: string;
2303
+ /** Risk-trend sparkbar values (pre-V2 look; prefer `trend`). */
2304
+ spark?: number[];
2305
+ /**
2306
+ * Design-12 risk trend: one toned block per period, oldest first, with a
2307
+ * caption line underneath ("risk trend" · "128 analyses").
2308
+ */
2309
+ trend?: {
2310
+ tones: (Tone | null)[];
2311
+ caption?: string;
2312
+ aside?: string;
2313
+ };
2314
+ chips?: FxProjectCardChip[];
2315
+ /** Metric columns (Binaries · Findings · …): figure + caption. */
2316
+ metrics?: FxProjectCardMetric[];
2317
+ /** Footer meta line (e.g. "Last analysis · 2d ago"). */
2318
+ meta?: string;
2319
+ /** Footer link label right of the meta ("Open ›"); the whole card emits (open). */
2320
+ openLabel?: string;
2321
+ /** Free-form identifier handed back on (open). */
2322
+ data?: any;
2323
+ }
2324
+ /**
2325
+ * V2 project card — the Project Management catalog tile (design 12): initials
2326
+ * avatar + name + schedule line, toned score chip, risk-trend blocks, metric
2327
+ * columns and a "Last analysis · … / Open ›" footer.
2328
+ *
2329
+ * <fx-ui-project-card [card]="project" (open)="goTo(project)" />
2330
+ */
2331
+ declare class ProjectCardComponent {
2332
+ readonly card: _angular_core.InputSignal<FxProjectCard>;
2333
+ readonly open: _angular_core.OutputEmitterRef<FxProjectCard>;
2334
+ scoreChipClass(): string;
2335
+ chipClass(chip: FxProjectCardChip): string;
2336
+ blockClass(tone: Tone | null): string;
2337
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ProjectCardComponent, never>;
2338
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ProjectCardComponent, "fx-ui-project-card", never, { "card": { "alias": "card"; "required": true; "isSignal": true; }; }, { "open": "open"; }, never, never, true, never>;
2339
+ }
2340
+
2341
+ type FxPipelineStageState = 'pending' | 'active' | 'done' | 'error';
2342
+ interface FxPipelineStage {
2343
+ id: string;
2344
+ /** Caller-translated label. */
2345
+ label: string;
2346
+ state?: FxPipelineStageState;
2347
+ /** Small line under the label (e.g. "optional", a duration). */
2348
+ description?: string;
2349
+ }
2350
+ /**
2351
+ * V2 pipeline stepper — the New Analysis 7-stage pipeline header. Renders the
2352
+ * stage strip only; the page owns the stage bodies (project the current one
2353
+ * below). Stage states are data — the parent decides what is done/active.
2354
+ *
2355
+ * <fx-ui-pipeline-stepper [stages]="stages" (stageClick)="goTo($event)">
2356
+ * …current stage body…
2357
+ * </fx-ui-pipeline-stepper>
2358
+ */
2359
+ declare class PipelineStepperComponent {
2360
+ readonly stages: _angular_core.InputSignal<FxPipelineStage[]>;
2361
+ /** Only done stages are click-navigable (review a completed step). */
2362
+ readonly clickable: _angular_core.InputSignal<boolean>;
2363
+ readonly stageClick: _angular_core.OutputEmitterRef<number>;
2364
+ stateOf(stage: FxPipelineStage): FxPipelineStageState;
2365
+ circleClass(stage: FxPipelineStage): string;
2366
+ labelClass(stage: FxPipelineStage): string;
2367
+ connectorClass(stage: FxPipelineStage): string;
2368
+ canClick(stage: FxPipelineStage): boolean;
2369
+ onStageClick(stage: FxPipelineStage, index: number): void;
2370
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PipelineStepperComponent, never>;
2371
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PipelineStepperComponent, "fx-ui-pipeline-stepper", never, { "stages": { "alias": "stages"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "stageClick": "stageClick"; }, never, ["*"], true, never>;
2372
+ }
2373
+
2374
+ /** Facets-rail skeleton: N nhóm, mỗi nhóm một eyebrow + vài dòng lựa chọn. */
2375
+ declare class SkeletonFacetsComponent {
2376
+ readonly groups: _angular_core.InputSignal<number>;
2377
+ readonly rows: _angular_core.InputSignal<number>;
2378
+ readonly groupList: _angular_core.Signal<number[]>;
2379
+ readonly rowList: _angular_core.Signal<number[]>;
2380
+ rowWidth(i: number): number;
2381
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonFacetsComponent, never>;
2382
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonFacetsComponent, "fx-ui-skeleton-facets", never, { "groups": { "alias": "groups"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2383
+ }
2384
+
2385
+ /** Dashboard skeleton: một hàng KPI + N panel có vùng chart. */
2386
+ declare class SkeletonDashboardComponent {
2387
+ readonly kpis: _angular_core.InputSignal<number>;
2388
+ readonly panels: _angular_core.InputSignal<number>;
2389
+ readonly kpiList: _angular_core.Signal<number[]>;
2390
+ readonly panelList: _angular_core.Signal<number[]>;
2391
+ readonly barList: _angular_core.Signal<number[]>;
2392
+ /** Chiều cao cột giả — dựng hình chart mà không cần dữ liệu. */
2393
+ barHeight(i: number): number;
2394
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonDashboardComponent, never>;
2395
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonDashboardComponent, "fx-ui-skeleton-dashboard", never, { "kpis": { "alias": "kpis"; "required": false; "isSignal": true; }; "panels": { "alias": "panels"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2396
+ }
2397
+
2398
+ /**
2399
+ * Skeleton của cả AppFrame (drawer + topbar + vùng nội dung).
2400
+ *
2401
+ * Chỉ dùng cho giai đoạn **bootstrap**, khi shell của host còn CHƯA tồn tại
2402
+ * (App.ngOnInit đang kiểm tenant + session, router chưa initialNavigation).
2403
+ * Mọi điều hướng SAU đó đã có shell thật → dùng `fx-ui-route-skeleton` bên
2404
+ * trong vùng nội dung, đừng vẽ lại cả frame.
2405
+ *
2406
+ * ⚠️ `contentHint` là thứ làm F5 không còn vẽ hình generic. Lần điều hướng ĐẦU
2407
+ * tạo ra chính `HomeComponent` — nơi chứa `fx-ui-route-skeleton` — nên vùng nội
2408
+ * dung không thể tự vẽ skeleton của route ở lần đó. Truyền hint vào đây để
2409
+ * frame dựng đúng composition của màn đích ngay từ F5.
2410
+ */
2411
+ declare class SkeletonFrameComponent {
2412
+ readonly navItems: _angular_core.InputSignal<number>;
2413
+ /** Composition của route đích; null thì vẽ khối generic. */
2414
+ readonly contentHint: _angular_core.InputSignal<FxSkeletonHint | FxSkeletonBlock[] | null>;
2415
+ readonly navList: _angular_core.Signal<number[]>;
2416
+ navWidth(i: number): number;
2417
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonFrameComponent, never>;
2418
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonFrameComponent, "fx-ui-skeleton-frame", never, { "navItems": { "alias": "navItems"; "required": false; "isSignal": true; }; "contentHint": { "alias": "contentHint"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2419
+ }
2420
+
1560
2421
  declare class ConfirmationDialogComponent {
1561
2422
  private ref;
1562
2423
  bindings: any;
@@ -1585,9 +2446,9 @@ declare class ConfirmationDialogComponent {
1585
2446
  */
1586
2447
  declare class UiModule {
1587
2448
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiModule, never>;
1588
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<UiModule, never, [typeof i1$1.FormsModule, typeof i1$1.ReactiveFormsModule, typeof i2.RouterModule, typeof HasPermissionDirective, typeof TrimOnBlurDirective, typeof InputComponent, typeof SelectComponent, typeof RadioButtonComponent, typeof CheckboxComponent, typeof DndUploadComponent, typeof ButtonComponent, typeof RadioButtonToggleComponent, typeof DatetimePicker, typeof LoadingPanel, typeof SearchBarComponent, typeof TabGroupComponent, typeof TabComponent, typeof HeroIconComponent, typeof ToastComponent, typeof ToastContainerComponent, typeof TagComponent, typeof SliderComponent, typeof SwitchComponent, typeof SkeletonTableLoadingComponent, typeof CircleProgressBar, typeof TreeDiagram, typeof TableCell, typeof KanbanBoardComponent, typeof DrawerComponent, typeof SkeletonListComponent, typeof SkeletonDetailComponent, typeof StatCardsComponent, typeof EmptyStateComponent, typeof FilterChipsComponent, typeof MeterComponent, typeof SectionCardComponent, typeof InfoFieldComponent, typeof SeverityBadgesComponent, typeof MasterDetailComponent, typeof MenuComponent, typeof ConfirmationDialogComponent], [typeof InputComponent, typeof SelectComponent, typeof RadioButtonComponent, typeof CheckboxComponent, typeof DndUploadComponent, typeof ButtonComponent, typeof RadioButtonToggleComponent, typeof DatetimePicker, typeof LoadingPanel, typeof SearchBarComponent, typeof TabGroupComponent, typeof TabComponent, typeof HeroIconComponent, typeof ToastComponent, typeof ToastContainerComponent, typeof TagComponent, typeof SliderComponent, typeof SwitchComponent, typeof SkeletonTableLoadingComponent, typeof CircleProgressBar, typeof TreeDiagram, typeof TableCell, typeof KanbanBoardComponent, typeof DrawerComponent, typeof SkeletonListComponent, typeof SkeletonDetailComponent, typeof StatCardsComponent, typeof EmptyStateComponent, typeof FilterChipsComponent, typeof MeterComponent, typeof SectionCardComponent, typeof InfoFieldComponent, typeof SeverityBadgesComponent, typeof MasterDetailComponent, typeof MenuComponent, typeof ConfirmationDialogComponent, typeof i1$1.FormsModule, typeof i1$1.ReactiveFormsModule, typeof i2.RouterModule, typeof HasPermissionDirective, typeof TrimOnBlurDirective]>;
2449
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<UiModule, never, [typeof i1$1.FormsModule, typeof i1$1.ReactiveFormsModule, typeof i2.RouterModule, typeof HasPermissionDirective, typeof TrimOnBlurDirective, typeof InputComponent, typeof SelectComponent, typeof RadioButtonComponent, typeof CheckboxComponent, typeof DndUploadComponent, typeof ButtonComponent, typeof RadioButtonToggleComponent, typeof DatetimePicker, typeof LoadingPanel, typeof SearchBarComponent, typeof TabGroupComponent, typeof TabComponent, typeof HeroIconComponent, typeof ToastComponent, typeof ToastContainerComponent, typeof TagComponent, typeof SliderComponent, typeof SwitchComponent, typeof CircleProgressBar, typeof TreeDiagram, typeof TableCell, typeof KanbanBoardComponent, typeof DrawerComponent, typeof SkeletonListComponent, typeof SkeletonDetailComponent, typeof StatCardsComponent, typeof EmptyStateComponent, typeof FilterChipsComponent, typeof FilterPillsComponent, typeof StageDotsComponent, typeof CodeBlockComponent, typeof ScreenshotFrameComponent, typeof MeterComponent, typeof SectionCardComponent, typeof InfoFieldComponent, typeof SeverityBadgesComponent, typeof MasterDetailComponent, typeof MenuComponent, typeof ThemePickerComponent, typeof PendingBadgeComponent, typeof SampleFrameComponent, typeof ScoreBadgeComponent, typeof StatusDotComponent, typeof SparkbarComponent, typeof SegmentedComponent, typeof ListRowComponent, typeof BarListComponent, typeof FacetsRailComponent, typeof ProjectCardComponent, typeof PipelineStepperComponent, typeof SkeletonFacetsComponent, typeof SkeletonDashboardComponent, typeof SkeletonFrameComponent, typeof RouteSkeletonComponent, typeof ConfirmationDialogComponent], [typeof InputComponent, typeof SelectComponent, typeof RadioButtonComponent, typeof CheckboxComponent, typeof DndUploadComponent, typeof ButtonComponent, typeof RadioButtonToggleComponent, typeof DatetimePicker, typeof LoadingPanel, typeof SearchBarComponent, typeof TabGroupComponent, typeof TabComponent, typeof HeroIconComponent, typeof ToastComponent, typeof ToastContainerComponent, typeof TagComponent, typeof SliderComponent, typeof SwitchComponent, typeof CircleProgressBar, typeof TreeDiagram, typeof TableCell, typeof KanbanBoardComponent, typeof DrawerComponent, typeof SkeletonListComponent, typeof SkeletonDetailComponent, typeof StatCardsComponent, typeof EmptyStateComponent, typeof FilterChipsComponent, typeof FilterPillsComponent, typeof StageDotsComponent, typeof CodeBlockComponent, typeof ScreenshotFrameComponent, typeof MeterComponent, typeof SectionCardComponent, typeof InfoFieldComponent, typeof SeverityBadgesComponent, typeof MasterDetailComponent, typeof MenuComponent, typeof ThemePickerComponent, typeof PendingBadgeComponent, typeof SampleFrameComponent, typeof ScoreBadgeComponent, typeof StatusDotComponent, typeof SparkbarComponent, typeof SegmentedComponent, typeof ListRowComponent, typeof BarListComponent, typeof FacetsRailComponent, typeof ProjectCardComponent, typeof PipelineStepperComponent, typeof SkeletonFacetsComponent, typeof SkeletonDashboardComponent, typeof SkeletonFrameComponent, typeof RouteSkeletonComponent, typeof ConfirmationDialogComponent, typeof i1$1.FormsModule, typeof i1$1.ReactiveFormsModule, typeof i2.RouterModule, typeof HasPermissionDirective, typeof TrimOnBlurDirective]>;
1589
2450
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<UiModule>;
1590
2451
  }
1591
2452
 
1592
- export { AuthInterceptor, AuthStateService, BaseComponent, BaseDialogComponent, BaseMasterDetailComponent, BaseResolver, BaseTableComponent, BreadcrumbService, ButtonComponent, CheckboxComponent, CircleProgressBar, ConfirmationDialogComponent, DatetimePicker, DndUploadComponent, DrawerComponent, EmptyStateComponent, FX_ICON_SPRITE_URL, FilterChipsComponent, FxComponent, FxDialogService, FxLoadingService, FxStorageService, FxToastrService, FxUtils, FxValidators, HasPermissionDirective, HeroIconComponent, HttpLoaderFactory, HttpWrapper, InfoFieldComponent, InputComponent, KanbanBoardComponent, LoadingPanel, MasterDetailComponent, MenuComponent, MeterComponent, NotificationService, PermissionGuard, PermissionService, RadioButtonComponent, RadioButtonToggleComponent, RealtimeTableSync, SearchBarComponent, SectionCardComponent, SelectComponent, SeverityBadgesComponent, SkeletonDetailComponent, SkeletonListComponent, SkeletonTableLoadingComponent, SliderComponent, StatCardsComponent, SwitchComponent, TabComponent, TabGroupComponent, TableCell, TagComponent, ThemeService, ToastComponent, ToastContainerComponent, TranslationModule, TranslationService, TreeDiagram, TrimOnBlurDirective, UiModule, countTone, createApi, fxListResolver, scoreTone, severityTone, toneBadge, toneBg, toneColor, toneText };
1593
- export type { Breadcrumb, ColumnChangedEvent, ErrorMessages, FxApiClass, FxConfirmOptions, FxFilterChipOption, FxListRequest, FxListResolverContext, FxMenuItem, FxSeverityBadge, FxStatCard, FxTableFilters, IRadioButton, KanbanColumn, NotificationCallback, NotificationConnectOptions, RealtimeTableEvent, RealtimeTableSyncOptions, TableResult, TagType, ToastData, Tone, TreeNode, UploadResult };
2453
+ export { AuthInterceptor, AuthStateService, BarListComponent, BaseComponent, BaseDialogComponent, BaseMasterDetailComponent, BaseTableComponent, BreadcrumbService, ButtonComponent, CheckboxComponent, CircleProgressBar, CodeBlockComponent, ConfirmationDialogComponent, DatetimePicker, DndUploadComponent, DrawerComponent, EmptyStateComponent, FX_ICON_SPRITE_URL, FX_SKELETON_DATA_KEY, FacetsRailComponent, FilterChipsComponent, FilterPillsComponent, FxComponent, FxDialogService, FxLoadingService, FxRouteSkeletonService, FxStorageService, FxToastrService, FxUtils, FxValidators, HasPermissionDirective, HeroIconComponent, HttpLoaderFactory, HttpWrapper, InfoFieldComponent, InputComponent, KanbanBoardComponent, ListRowComponent, LoadingPanel, MasterDetailComponent, MenuComponent, MeterComponent, NotificationService, OG_LIGHT_THEMES, OG_PICKER_THEMES, OG_PICKER_THEME_META, OG_THEMES, OG_THEME_META, PendingBadgeComponent, PermissionGuard, PermissionService, PipelineStepperComponent, ProjectCardComponent, RadioButtonComponent, RadioButtonToggleComponent, RealtimeTableSync, RouteSkeletonComponent, SampleFrameComponent, ScoreBadgeComponent, ScreenshotFrameComponent, SearchBarComponent, SectionCardComponent, SegmentedComponent, SelectComponent, SeverityBadgesComponent, SkeletonDashboardComponent, SkeletonDetailComponent, SkeletonFacetsComponent, SkeletonFrameComponent, SkeletonListComponent, SliderComponent, SparkbarComponent, StageDotsComponent, StatCardsComponent, StatusDotComponent, SwitchComponent, TabComponent, TabGroupComponent, TableCell, TagComponent, ThemePickerComponent, ThemeService, ToastComponent, ToastContainerComponent, TranslationModule, TranslationService, TreeDiagram, TrimOnBlurDirective, UiModule, anyFeatureEnabled, countTone, createApi, featureEnabled, fxListResolver, scoreTone, severityTone, toneBadge, toneBadgeSolid, toneBg, toneBorder, toneColor, toneDot, toneDotChart, toneFg, toneScale, toneText, toneTint };
2454
+ export type { Breadcrumb, ColumnChangedEvent, DrawerItem, ErrorMessages, FxApiClass, FxBarListItem, FxConfirmOptions, FxFacetGroup, FxFacetOption, FxFacetSelection, FxFeatureFlags, FxFilterChipOption, FxFilterPillOption, FxListRequest, FxListResolverContext, FxListRowBadge, FxMenuItem, FxPipelineStage, FxPipelineStageState, FxProjectCard, FxProjectCardChip, FxProjectCardMetric, FxSegmentedOption, FxSeverityBadge, FxSkeletonBlock, FxSkeletonBlockKind, FxSkeletonBlockSpec, FxSkeletonHint, FxStatCard, FxStatCardDelta, FxTableFilters, IRadioButton, KanbanColumn, NotificationCallback, NotificationConnectOptions, OgTheme, OgThemeMeta, RealtimeTableEvent, RealtimeTableSyncOptions, TableResult, TagType, ToastData, Tone, TreeNode, UploadResult };