@foxeltech/angular-ui 0.7.44 → 0.7.83

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 (53) hide show
  1. package/components.css +345 -19
  2. package/familjen-grotesk/familjen-grotesk-400-latin-ext.woff2 +0 -0
  3. package/familjen-grotesk/familjen-grotesk-400-latin.woff2 +0 -0
  4. package/familjen-grotesk/familjen-grotesk-400-vietnamese.woff2 +0 -0
  5. package/familjen-grotesk/familjen-grotesk-500-latin-ext.woff2 +0 -0
  6. package/familjen-grotesk/familjen-grotesk-500-latin.woff2 +0 -0
  7. package/familjen-grotesk/familjen-grotesk-500-vietnamese.woff2 +0 -0
  8. package/familjen-grotesk/familjen-grotesk-600-latin-ext.woff2 +0 -0
  9. package/familjen-grotesk/familjen-grotesk-600-latin.woff2 +0 -0
  10. package/familjen-grotesk/familjen-grotesk-600-vietnamese.woff2 +0 -0
  11. package/familjen-grotesk/familjen-grotesk-700-latin-ext.woff2 +0 -0
  12. package/familjen-grotesk/familjen-grotesk-700-latin.woff2 +0 -0
  13. package/familjen-grotesk/familjen-grotesk-700-vietnamese.woff2 +0 -0
  14. package/fesm2022/foxeltech-angular-ui-chart.mjs +197 -24
  15. package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -1
  16. package/fesm2022/foxeltech-angular-ui.mjs +585 -125
  17. package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
  18. package/fonts.css +104 -3
  19. package/package.json +1 -1
  20. package/src/lib/styles/components.css +345 -19
  21. package/src/lib/styles/fonts.css +104 -3
  22. package/src/lib/styles/tailwind.css +12 -0
  23. package/src/lib/styles/theme.css +160 -114
  24. package/src/lib/styles/tokens.css +25 -0
  25. package/src/lib/styles/utilities.css +18 -1
  26. package/src/lib/ui/components/button/button.component.html +2 -0
  27. package/src/lib/ui/components/drawer/drawer.component.scss +3 -1
  28. package/src/lib/ui/components/facets-rail/facets-rail.component.html +1 -6
  29. package/src/lib/ui/components/master-detail/master-detail.component.css +65 -13
  30. package/src/lib/ui/components/master-detail/master-detail.component.html +26 -8
  31. package/src/lib/ui/components/pending-badge/pending-badge.component.html +2 -2
  32. package/src/lib/ui/components/project-card/project-card.component.html +7 -3
  33. package/src/lib/ui/components/route-skeleton/route-skeleton.component.css +38 -0
  34. package/src/lib/ui/components/route-skeleton/route-skeleton.component.html +184 -0
  35. package/src/lib/ui/components/sample-frame/sample-frame.component.html +6 -7
  36. package/src/lib/ui/components/section-card/section-card.component.html +4 -6
  37. package/src/lib/ui/components/segmented/segmented.component.html +3 -1
  38. package/src/lib/ui/components/skeleton-dashboard/skeleton-dashboard.component.html +24 -0
  39. package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +8 -8
  40. package/src/lib/ui/components/skeleton-facets/skeleton-facets.component.html +15 -0
  41. package/src/lib/ui/components/skeleton-frame/skeleton-frame.component.html +59 -0
  42. package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +6 -6
  43. package/src/lib/ui/components/switch/switch.component.html +1 -1
  44. package/src/lib/ui/components/toast/toast.component.html +6 -6
  45. package/tailwind.css +12 -0
  46. package/theme.css +160 -114
  47. package/tokens.css +25 -0
  48. package/types/foxeltech-angular-ui-chart.d.ts +76 -1
  49. package/types/foxeltech-angular-ui.d.ts +318 -39
  50. package/utilities.css +18 -1
  51. package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.html +0 -21
  52. package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.scss +0 -0
  53. package/src/lib/ui/components/tab-component/tab.component.html +0 -1
@@ -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) =>
@@ -555,9 +669,16 @@ declare class FxUtils {
555
669
  * helpers return `null` for "no meaningful value" and the `toneText` /
556
670
  * `toneBg` / `toneBadge` wrappers fall back to a neutral class.
557
671
  *
558
- * Every emitted utility must appear below as a WHOLE literal string — the
559
- * Tailwind content scanner (v4 has no safelist) only sees complete class
560
- * 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".
561
682
  */
562
683
  type Tone = 'critical' | 'danger' | 'warning' | 'success' | 'information';
563
684
  /** Severity / risk-level string → tone (Critical & High → danger, Medium → warning, Low → success). */
@@ -580,7 +701,66 @@ declare function toneText(tone: Tone | null): string;
580
701
  /** Tone → background colour class, with a neutral fallback when there is no value. */
581
702
  declare function toneBg(tone: Tone | null): string;
582
703
  /** Tone → soft pill/badge classes (tinted bg + matching text), neutral fallback. */
583
- 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
+ /**
723
+ * Chỉ MÀU của tông, không kèm hình dạng pill — cho ô icon, chip, ô nền.
724
+ *
725
+ * ⚠️ Đây là họ SOLID: `tone-tint-critical` đặt `background: --og-text`
726
+ * (gần đen) VÀ `color: --og-surface` (trắng) trên CÙNG element.
727
+ *
728
+ * Hệ quả bắt buộc nhớ:
729
+ * 1. Chỉ dùng cho **badge một phần tử**. Với hộp nhiều dòng thì con sẽ cần màu
730
+ * chữ riêng, và nếu con ghi đè bằng `toneFg()` (đỏ sẫm) thì thành đỏ sẫm
731
+ * trên gần đen — không đọc được. Đã bị đúng vậy ở hộp RISK của
732
+ * `info-binary-detail` (anh Tú 03/09).
733
+ * 2. **KHÔNG** đặt `toneFg()` lên phần tử con của một phần tử đã có
734
+ * `toneTint()` — nó phá màu tương phản mà `toneTint` vừa đặt.
735
+ *
736
+ * Hộp/khối nhiều dòng thì dùng `toneScale()`: nền nhạt (color-mix 12%) + chữ
737
+ * đúng tông, con chỉ cần THỪA HƯỞNG.
738
+ */
739
+ declare function toneTint(tone: Tone | string | null | undefined): string;
740
+ /**
741
+ * CHỮ theo tông — dùng thành viên dễ đọc nhất của mỗi họ severity, KHÔNG phải
742
+ * ramp chart (ramp có `warning #f59e0b` chỉ 2.15:1 trên nền trắng). Xem
743
+ * `.tone-fg-*` trong components.css.
744
+ */
745
+ declare function toneFg(tone: Tone | string | null | undefined): string;
746
+ /**
747
+ * Tông THANG ĐO — cho filter chip severity. Critical ra ĐỎ SẪM (nền mềm pha
748
+ * từ ramp `--og-sev-*`) thay vì pill đen đặc của `toneTint()`: chip filter là
749
+ * một thang đo, không phải badge severity của một finding. Xem `.tone-scale-*`.
750
+ */
751
+ declare function toneScale(tone: Tone | string | null | undefined): string;
752
+ /** Viền theo tông — cho panel trạng thái (dropzone upload…). */
753
+ declare function toneBorder(tone: Tone | string | null | undefined): string;
754
+ /**
755
+ * CHẤM trạng thái trong hàng (`● Confirmed`) — demo dùng màu SEMANTIC
756
+ * (`.og-statusdot--*`), không phải ramp chart.
757
+ */
758
+ declare function toneDot(tone: Tone | string | null | undefined): string;
759
+ /**
760
+ * CHẤM LEGEND của chart — phải TRÙNG màu cung donut nên dùng ramp
761
+ * `--og-sev-*`. Đừng dùng cho chấm trạng thái trong hàng.
762
+ */
763
+ declare function toneDotChart(tone: Tone | string | null | undefined): string;
584
764
  /**
585
765
  * Tone → resolved CSS colour string for ECharts / canvas where a Tailwind
586
766
  * class can't be used (e.g. per-slice pie `itemStyle.color`). Emits the
@@ -1040,7 +1220,7 @@ declare class DndUploadComponent {
1040
1220
  declare class ButtonComponent {
1041
1221
  label: string;
1042
1222
  readonly disabled: _angular_core.InputSignal<boolean>;
1043
- readonly buttonVariant: _angular_core.InputSignal<"default" | "success" | "primary" | "alternative">;
1223
+ readonly buttonVariant: _angular_core.InputSignal<"default" | "success" | "primary" | "cta" | "alternative">;
1044
1224
  icon?: any;
1045
1225
  readonly class: _angular_core.InputSignal<any>;
1046
1226
  readonly loading: _angular_core.InputSignal<boolean>;
@@ -1138,6 +1318,32 @@ declare class SearchBarComponent extends FxComponent<string> implements AfterVie
1138
1318
  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>;
1139
1319
  }
1140
1320
 
1321
+ /**
1322
+ * Một tab của `fx-ui-tab-group`.
1323
+ *
1324
+ * ⚠️ Nội dung tab PHẢI bọc trong `<ng-template>`:
1325
+ *
1326
+ * ```html
1327
+ * <fx-ui-tab [label]="'Components'">
1328
+ * <ng-template>
1329
+ * <app-info-components … />
1330
+ * </ng-template>
1331
+ * </fx-ui-tab>
1332
+ * ```
1333
+ *
1334
+ * Vì sao bắt buộc: trước đây tab dùng `<ng-content>` bọc trong `<ng-template>`
1335
+ * của CHÍNH nó. Cách đó **không hoãn được gì** — `<ng-content>` chỉ CHIẾU node,
1336
+ * còn node do view khai báo (component cha) tạo **eager**. Kết quả: mọi tab đều
1337
+ * 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
1338
+ * scan-info: cả 8 cụm cùng fetch). Nhận `TemplateRef` từ cha thì nội dung chỉ
1339
+ * được dựng khi tab-group stamp template đó.
1340
+ *
1341
+ * Hệ quả cần biết: đổi tab sẽ **huỷ** nội dung tab cũ và dựng lại khi quay lại
1342
+ * — đúng bản chất lazy, giống `matTabContent` của Material.
1343
+ *
1344
+ * `descendants: false` để chỉ bắt `<ng-template>` là con TRỰC TIẾP, tránh nuốt
1345
+ * nhầm template lồng sâu bên trong nội dung tab.
1346
+ */
1141
1347
  declare class TabComponent {
1142
1348
  readonly label: _angular_core.InputSignal<string>;
1143
1349
  icon?: string;
@@ -1147,7 +1353,7 @@ declare class TabComponent {
1147
1353
  readonly tone: _angular_core.InputSignal<Tone | null>;
1148
1354
  readonly content: _angular_core.Signal<TemplateRef<any>>;
1149
1355
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabComponent, never>;
1150
- 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; }; }, {}, never, ["*"], true, never>;
1356
+ 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>;
1151
1357
  }
1152
1358
 
1153
1359
  declare class TabGroupComponent implements AfterContentInit, AfterViewChecked, OnChanges {
@@ -1305,13 +1511,6 @@ declare class SwitchComponent extends FxComponent<any> implements AfterViewInit
1305
1511
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SwitchComponent, "fx-ui-switch", never, { "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "onSwitch": "onSwitch"; }, never, never, true, never>;
1306
1512
  }
1307
1513
 
1308
- declare class SkeletonTableLoadingComponent {
1309
- readonly columns: _angular_core.InputSignal<number>;
1310
- readonly rows: _angular_core.InputSignal<number>;
1311
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonTableLoadingComponent, never>;
1312
- 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>;
1313
- }
1314
-
1315
1514
  declare class CircleProgressBar {
1316
1515
  readonly percent: _angular_core.InputSignal<number>;
1317
1516
  readonly showPercent: _angular_core.InputSignal<boolean>;
@@ -1437,7 +1636,8 @@ declare class DrawerComponent implements OnInit, OnDestroy {
1437
1636
  /** Row-card skeleton placeholder for master-detail list panes. */
1438
1637
  declare class SkeletonListComponent {
1439
1638
  readonly rows: _angular_core.InputSignal<number>;
1440
- range(n: number): number[];
1639
+ /** computed, không phải method: method trả mảng MỚI mỗi lần render. */
1640
+ readonly rowList: _angular_core.Signal<number[]>;
1441
1641
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonListComponent, never>;
1442
1642
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonListComponent, "fx-ui-skeleton-list", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1443
1643
  }
@@ -1448,7 +1648,9 @@ declare class SkeletonDetailComponent {
1448
1648
  readonly cards: _angular_core.InputSignal<number>;
1449
1649
  /** Rows per content card. */
1450
1650
  readonly rows: _angular_core.InputSignal<number>;
1451
- range(n: number): number[];
1651
+ /** computed, không phải method: method trả mảng MỚI mỗi lần render. */
1652
+ readonly cardList: _angular_core.Signal<number[]>;
1653
+ readonly rowList: _angular_core.Signal<number[]>;
1452
1654
  rowWidth(i: number): number;
1453
1655
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonDetailComponent, never>;
1454
1656
  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>;
@@ -1557,6 +1759,12 @@ declare class FilterPillsComponent {
1557
1759
  readonly value: _angular_core.InputSignal<string | undefined>;
1558
1760
  readonly valueChange: _angular_core.OutputEmitterRef<string>;
1559
1761
  isActive(option: FxFilterPillOption): boolean;
1762
+ /**
1763
+ * Pill ĐANG CHỌN dùng **accent** (xanh), không phải nền đen — khớp demo:
1764
+ * design ref 11 vẽ pill "All 40" là pill accent. Nền đen `--og-text` chỉ
1765
+ * dành cho badge severity Critical (`.og-badge--solid`), không dùng cho
1766
+ * trạng thái chọn của filter (anh Tú chốt 03/09).
1767
+ */
1560
1768
  pillClass(option: FxFilterPillOption): string;
1561
1769
  countClass(option: FxFilterPillOption): string;
1562
1770
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FilterPillsComponent, never>;
@@ -1645,6 +1853,10 @@ declare class MeterComponent {
1645
1853
  * - titleStyle 'heading' (default): icon + heading, the pre-V2 look
1646
1854
  * - titleStyle 'eyebrow': the V2 design's panel header — small tracked
1647
1855
  * caption on the left, muted [aside] text on the right
1856
+ *
1857
+ * The host is a flex column (not the custom element's inline default) so that
1858
+ * in a CSS grid row every card stretches to the row height and panels line up
1859
+ * (anh Tú 04/09); a footer projected with `mt-auto` sticks to the bottom.
1648
1860
  */
1649
1861
  declare class SectionCardComponent {
1650
1862
  /** Caller-translated heading. */
@@ -1735,7 +1947,13 @@ declare class MasterDetailComponent implements AfterViewInit, AfterContentInit {
1735
1947
  table: BaseMasterDetailComponent<any>;
1736
1948
  /** Fixed list-pane width on lg+ viewports (stacked full-width below). */
1737
1949
  readonly listWidth: _angular_core.InputSignal<string>;
1738
- readonly maxListHeight: _angular_core.InputSignal<string>;
1950
+ /**
1951
+ * Chiều cao CHUNG của cả ba cụm (facets / list / detail). Mặc định trừ phần
1952
+ * chrome phía trên (topbar + tab strip + context line) khỏi viewport để
1953
+ * bảng ba cột vừa đúng một màn, không kéo trang cuộn theo.
1954
+ * Chỉ có tác dụng từ 1080px — xem `.fx-md-row` trong CSS.
1955
+ */
1956
+ readonly paneHeight: _angular_core.InputSignal<string>;
1739
1957
  readonly pageSizeOptions: _angular_core.InputSignal<number[]>;
1740
1958
  /** Labels come in via inputs — the lib carries no i18n. */
1741
1959
  readonly emptyMessage: _angular_core.InputSignal<string>;
@@ -1760,7 +1978,7 @@ declare class MasterDetailComponent implements AfterViewInit, AfterContentInit {
1760
1978
  optionId(index: number): string;
1761
1979
  onKeydown(event: KeyboardEvent, index: number): void;
1762
1980
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MasterDetailComponent, never>;
1763
- 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; }; "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>;
1981
+ 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>;
1764
1982
  }
1765
1983
 
1766
1984
  interface FxMenuItem {
@@ -1825,6 +2043,7 @@ declare class ThemePickerComponent {
1825
2043
  * <fx-ui-pending-badge [field]="'confirmed-chains weekly series'" />
1826
2044
  *
1827
2045
  * Keep the copy factual: it states that data is missing, never fakes a value.
2046
+ * Styling is neutral on purpose (anh Tú 04/09): a hint, not a warning.
1828
2047
  */
1829
2048
  declare class PendingBadgeComponent {
1830
2049
  /** Caller-translated chip text. */
@@ -1846,10 +2065,11 @@ declare class PendingBadgeComponent {
1846
2065
  * reviewed before its endpoint exists (anh Tú 29/08: "muốn có full giao diện
1847
2066
  * trước để review").
1848
2067
  *
1849
- * The frame makes the status unmistakable dashed outline, a corner label and
1850
- * the pending marker naming the missing field so sample shapes can never be
1851
- * mistaken for measured values. Drop the wrapper (and the sample input) the
1852
- * moment the API lands.
2068
+ * The marker is deliberately quiet (anh 04/09: no yellow frame, just a
2069
+ * subtle "Pending API" chip): a neutral chip above the block, with the label
2070
+ * and missing field in its tooltip. The content itself is non-interactive so
2071
+ * sample shapes are never mistaken for live state. Drop the wrapper (and the
2072
+ * sample input) the moment the API lands.
1853
2073
  *
1854
2074
  * The pending chip is inlined rather than composed from fx-ui-pending-badge:
1855
2075
  * one lib component importing another inside the same barrel tripped NG0919
@@ -1860,7 +2080,7 @@ declare class PendingBadgeComponent {
1860
2080
  * </fx-ui-sample-frame>
1861
2081
  */
1862
2082
  declare class SampleFrameComponent {
1863
- /** Caller-translated corner label. */
2083
+ /** Caller-translated block label — surfaces in the chip tooltip only. */
1864
2084
  readonly label: _angular_core.InputSignal<string>;
1865
2085
  /** Field the backend still owes — shown on the pending badge tooltip. */
1866
2086
  readonly field: _angular_core.InputSignal<string>;
@@ -1958,17 +2178,29 @@ declare class SegmentedComponent {
1958
2178
  * (design refs 04/05).
1959
2179
  */
1960
2180
  readonly variant: _angular_core.InputSignal<"default" | "pill">;
2181
+ /**
2182
+ * 'equal' (default): every segment takes the same width (view toggles such
2183
+ * as Catalog | Table). 'content': each segment is as wide as its label —
2184
+ * the demo's detail-pane tabs ("Affected software · Summary · Evidence"),
2185
+ * where equal columns would truncate the long label in a narrow pane.
2186
+ */
2187
+ readonly fit: _angular_core.InputSignal<"equal" | "content">;
2188
+ private readonly optionEls;
2189
+ /** Measured box of the active segment — only used when fit === 'content'. */
2190
+ private readonly thumbBox;
2191
+ constructor();
1961
2192
  /** Index the sliding thumb sits on; -1 hides it (no/unknown selection). */
1962
2193
  readonly activeIndex: _angular_core.Signal<number>;
1963
2194
  /** Equal-width tracks → the thumb is 1/n of the inner width and slides by
1964
2195
  * multiples of its own width. Pure CSS transform, nothing to measure. */
1965
2196
  readonly thumbWidth: _angular_core.Signal<string>;
1966
2197
  readonly thumbTransform: _angular_core.Signal<string>;
2198
+ readonly gridClass: _angular_core.Signal<"auto-cols-auto" | "auto-cols-fr">;
1967
2199
  select(option: FxSegmentedOption): void;
1968
2200
  thumbClass(): string;
1969
2201
  optionClass(option: FxSegmentedOption): string;
1970
2202
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SegmentedComponent, never>;
1971
- 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>;
2203
+ 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; }; "fit": { "alias": "fit"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
1972
2204
  }
1973
2205
 
1974
2206
  interface FxListRowBadge {
@@ -2173,6 +2405,53 @@ declare class PipelineStepperComponent {
2173
2405
  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>;
2174
2406
  }
2175
2407
 
2408
+ /** Facets-rail skeleton: N nhóm, mỗi nhóm một eyebrow + vài dòng lựa chọn. */
2409
+ declare class SkeletonFacetsComponent {
2410
+ readonly groups: _angular_core.InputSignal<number>;
2411
+ readonly rows: _angular_core.InputSignal<number>;
2412
+ readonly groupList: _angular_core.Signal<number[]>;
2413
+ readonly rowList: _angular_core.Signal<number[]>;
2414
+ rowWidth(i: number): number;
2415
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonFacetsComponent, never>;
2416
+ 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>;
2417
+ }
2418
+
2419
+ /** Dashboard skeleton: một hàng KPI + N panel có vùng chart. */
2420
+ declare class SkeletonDashboardComponent {
2421
+ readonly kpis: _angular_core.InputSignal<number>;
2422
+ readonly panels: _angular_core.InputSignal<number>;
2423
+ readonly kpiList: _angular_core.Signal<number[]>;
2424
+ readonly panelList: _angular_core.Signal<number[]>;
2425
+ readonly barList: _angular_core.Signal<number[]>;
2426
+ /** Chiều cao cột giả — dựng hình chart mà không cần dữ liệu. */
2427
+ barHeight(i: number): number;
2428
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonDashboardComponent, never>;
2429
+ 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>;
2430
+ }
2431
+
2432
+ /**
2433
+ * Skeleton của cả AppFrame (drawer + topbar + vùng nội dung).
2434
+ *
2435
+ * Chỉ dùng cho giai đoạn **bootstrap**, khi shell của host còn CHƯA tồn tại
2436
+ * (App.ngOnInit đang kiểm tenant + session, router chưa initialNavigation).
2437
+ * Mọi điều hướng SAU đó đã có shell thật → dùng `fx-ui-route-skeleton` bên
2438
+ * trong vùng nội dung, đừng vẽ lại cả frame.
2439
+ *
2440
+ * ⚠️ `contentHint` là thứ làm F5 không còn vẽ hình generic. Lần điều hướng ĐẦU
2441
+ * tạo ra chính `HomeComponent` — nơi chứa `fx-ui-route-skeleton` — nên vùng nội
2442
+ * dung không thể tự vẽ skeleton của route ở lần đó. Truyền hint vào đây để
2443
+ * frame dựng đúng composition của màn đích ngay từ F5.
2444
+ */
2445
+ declare class SkeletonFrameComponent {
2446
+ readonly navItems: _angular_core.InputSignal<number>;
2447
+ /** Composition của route đích; null thì vẽ khối generic. */
2448
+ readonly contentHint: _angular_core.InputSignal<FxSkeletonHint | FxSkeletonBlock[] | null>;
2449
+ readonly navList: _angular_core.Signal<number[]>;
2450
+ navWidth(i: number): number;
2451
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonFrameComponent, never>;
2452
+ 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>;
2453
+ }
2454
+
2176
2455
  declare class ConfirmationDialogComponent {
2177
2456
  private ref;
2178
2457
  bindings: any;
@@ -2201,9 +2480,9 @@ declare class ConfirmationDialogComponent {
2201
2480
  */
2202
2481
  declare class UiModule {
2203
2482
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiModule, never>;
2204
- 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 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 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 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 ConfirmationDialogComponent, typeof i1$1.FormsModule, typeof i1$1.ReactiveFormsModule, typeof i2.RouterModule, typeof HasPermissionDirective, typeof TrimOnBlurDirective]>;
2483
+ 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]>;
2205
2484
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<UiModule>;
2206
2485
  }
2207
2486
 
2208
- export { AuthInterceptor, AuthStateService, BarListComponent, BaseComponent, BaseDialogComponent, BaseMasterDetailComponent, BaseResolver, BaseTableComponent, BreadcrumbService, ButtonComponent, CheckboxComponent, CircleProgressBar, CodeBlockComponent, ConfirmationDialogComponent, DatetimePicker, DndUploadComponent, DrawerComponent, EmptyStateComponent, FX_ICON_SPRITE_URL, FacetsRailComponent, FilterChipsComponent, FilterPillsComponent, FxComponent, FxDialogService, FxLoadingService, 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, SampleFrameComponent, ScoreBadgeComponent, ScreenshotFrameComponent, SearchBarComponent, SectionCardComponent, SegmentedComponent, SelectComponent, SeverityBadgesComponent, SkeletonDetailComponent, SkeletonListComponent, SkeletonTableLoadingComponent, 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, toneBg, toneColor, toneText };
2209
- 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, FxStatCard, FxStatCardDelta, FxTableFilters, IRadioButton, KanbanColumn, NotificationCallback, NotificationConnectOptions, OgTheme, OgThemeMeta, RealtimeTableEvent, RealtimeTableSyncOptions, TableResult, TagType, ToastData, Tone, TreeNode, UploadResult };
2487
+ 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 };
2488
+ 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 };
package/utilities.css CHANGED
@@ -18,8 +18,25 @@
18
18
  @apply flex flex-row items-center px-semi;
19
19
  }
20
20
 
21
+ /* Nhãn "eyebrow" (tiêu đề panel, nhóm facet) — spec CUỐI của demo sau khi
22
+ lớp override đè lên base: font MONO, 11.5px, weight 600, letter-spacing
23
+ 0.02em và KHÔNG viết hoa. Base DS viết hoa + tracking 0.08em, nhưng
24
+ override đặt `text-transform: none` nên demo hiển thị chữ thường. */
25
+ @utility txt-eyebrow {
26
+ font-family: var(--og-font-mono);
27
+ font-size: var(--og-fs-xs);
28
+ font-weight: 600;
29
+ letter-spacing: 0.02em;
30
+ color: rgb(var(--og-text-muted));
31
+ }
32
+
21
33
  @utility card-common {
22
- @apply text-left px-xl py-large border border-border-default rounded-lg shadow-sm transition-colors duration-500 ease-in-out;
34
+ @apply text-left px-xl py-large border border-border-default rounded-lg transition-colors duration-500 ease-in-out;
35
+ /* Demo `.og-panel` / `.og-statgrid`: hairline border + two soft layers.
36
+ Replaces Tailwind shadow-sm, which reads harder at the edges. */
37
+ box-shadow:
38
+ 0 1px 2px rgb(0 0 0 / 0.04),
39
+ 0 3px 8px rgb(0 0 0 / 0.05);
23
40
  }
24
41
 
25
42
  @utility tag-common {
@@ -1,21 +0,0 @@
1
- <div class="w-full animate-pulse space-y-normal">
2
- <div
3
- class="grid gap-small"
4
- [ngStyle]="{ 'grid-template-columns': 'repeat(' + columns() + ', minmax(0, 1fr))' }"
5
- >
6
- @for(col of [].constructor(columns()); track col) {
7
- <div class="h-6 bg-bg-hover rounded"></div>
8
- }
9
- </div>
10
-
11
- @for(row of [].constructor(rows()); track row) {
12
- <div
13
- class="grid gap-small"
14
- [ngStyle]="{ 'grid-template-columns': 'repeat(' + columns() + ', minmax(0, 1fr))' }"
15
- >
16
- @for(col of [].constructor(columns()); track col) {
17
- <div class="h-7 bg-bg-hover rounded"></div>
18
- }
19
- </div>
20
- }
21
- </div>
@@ -1 +0,0 @@
1
- <ng-template><ng-content></ng-content></ng-template>