@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.
- package/archivo/archivo-400-latin-ext.woff2 +0 -0
- package/archivo/archivo-400-latin.woff2 +0 -0
- package/archivo/archivo-400-vietnamese.woff2 +0 -0
- package/archivo/archivo-500-latin-ext.woff2 +0 -0
- package/archivo/archivo-500-latin.woff2 +0 -0
- package/archivo/archivo-500-vietnamese.woff2 +0 -0
- package/archivo/archivo-600-latin-ext.woff2 +0 -0
- package/archivo/archivo-600-latin.woff2 +0 -0
- package/archivo/archivo-600-vietnamese.woff2 +0 -0
- package/archivo/archivo-700-latin-ext.woff2 +0 -0
- package/archivo/archivo-700-latin.woff2 +0 -0
- package/archivo/archivo-700-vietnamese.woff2 +0 -0
- package/components.css +332 -30
- package/dialogs.css +2 -2
- package/familjen-grotesk/familjen-grotesk-400-latin-ext.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-400-latin.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-400-vietnamese.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-500-latin-ext.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-500-latin.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-500-vietnamese.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-600-latin-ext.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-600-latin.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-600-vietnamese.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-700-latin-ext.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-700-latin.woff2 +0 -0
- package/familjen-grotesk/familjen-grotesk-700-vietnamese.woff2 +0 -0
- package/fesm2022/foxeltech-angular-ui-chart.mjs +381 -40
- package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -1
- package/fesm2022/foxeltech-angular-ui-flow.mjs +176 -3
- package/fesm2022/foxeltech-angular-ui-flow.mjs.map +1 -1
- package/fesm2022/foxeltech-angular-ui-rich-text.mjs +2 -2
- package/fesm2022/foxeltech-angular-ui-rich-text.mjs.map +1 -1
- package/fesm2022/foxeltech-angular-ui.mjs +1327 -151
- package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
- package/fonts.css +558 -133
- package/ibm-plex-mono/ibm-plex-mono-400-cyrillic-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-cyrillic.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-latin-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-latin.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-vietnamese.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-cyrillic-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-cyrillic.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-latin-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-latin.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-vietnamese.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-cyrillic-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-cyrillic.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-latin-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-latin.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-vietnamese.woff2 +0 -0
- package/newsreader/newsreader-400-latin-ext.woff2 +0 -0
- package/newsreader/newsreader-400-latin.woff2 +0 -0
- package/newsreader/newsreader-400-vietnamese.woff2 +0 -0
- package/newsreader/newsreader-500-latin-ext.woff2 +0 -0
- package/newsreader/newsreader-500-latin.woff2 +0 -0
- package/newsreader/newsreader-500-vietnamese.woff2 +0 -0
- package/newsreader/newsreader-600-latin-ext.woff2 +0 -0
- package/newsreader/newsreader-600-latin.woff2 +0 -0
- package/newsreader/newsreader-600-vietnamese.woff2 +0 -0
- package/package.json +5 -2
- package/source-serif-4/source-serif-4-400-cyrillic-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-cyrillic.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-greek.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-latin-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-latin.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-vietnamese.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-cyrillic-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-cyrillic.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-greek.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-latin-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-latin.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-vietnamese.woff2 +0 -0
- package/src/lib/styles/components.css +332 -30
- package/src/lib/styles/dialogs.css +2 -2
- package/src/lib/styles/fonts.css +558 -133
- package/src/lib/styles/tailwind.css +13 -1
- package/src/lib/styles/theme.css +642 -69
- package/src/lib/styles/tokens.css +81 -19
- package/src/lib/styles/utilities.css +16 -1
- package/src/lib/ui/components/bar-list/bar-list.component.html +29 -0
- package/src/lib/ui/components/button/button.component.html +9 -5
- package/src/lib/ui/components/checkbox/checkbox.component.html +1 -1
- package/src/lib/ui/components/code-block/code-block.component.html +8 -0
- package/src/lib/ui/components/drawer/drawer.component.html +35 -12
- package/src/lib/ui/components/drawer/drawer.component.scss +106 -18
- package/src/lib/ui/components/facets-rail/facets-rail.component.html +37 -0
- package/src/lib/ui/components/filter-pills/filter-pills.component.html +16 -0
- package/src/lib/ui/components/kanban-board/kanban-board.component.scss +9 -9
- package/src/lib/ui/components/list-row/list-row.component.html +20 -0
- package/src/lib/ui/components/master-detail/master-detail.component.css +79 -5
- package/src/lib/ui/components/master-detail/master-detail.component.html +57 -7
- package/src/lib/ui/components/pending-badge/pending-badge.component.html +15 -0
- package/src/lib/ui/components/pipeline-stepper/pipeline-stepper.component.html +45 -0
- package/src/lib/ui/components/project-card/project-card.component.html +102 -0
- package/src/lib/ui/components/radio-button/radio-button.component.html +1 -1
- package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.html +1 -1
- package/src/lib/ui/components/route-skeleton/route-skeleton.component.css +38 -0
- package/src/lib/ui/components/route-skeleton/route-skeleton.component.html +184 -0
- package/src/lib/ui/components/sample-frame/sample-frame.component.html +18 -0
- package/src/lib/ui/components/score-badge/score-badge.component.html +7 -0
- package/src/lib/ui/components/screenshot-frame/screenshot-frame.component.html +40 -0
- package/src/lib/ui/components/section-card/section-card.component.html +15 -6
- package/src/lib/ui/components/segmented/segmented.component.html +42 -0
- package/src/lib/ui/components/segmented/segmented.component.scss +12 -0
- package/src/lib/ui/components/skeleton-dashboard/skeleton-dashboard.component.html +24 -0
- package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +8 -8
- package/src/lib/ui/components/skeleton-facets/skeleton-facets.component.html +15 -0
- package/src/lib/ui/components/skeleton-frame/skeleton-frame.component.html +59 -0
- package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +6 -6
- package/src/lib/ui/components/slider/slider.component.html +2 -2
- package/src/lib/ui/components/sparkbar/sparkbar.component.html +14 -0
- package/src/lib/ui/components/stage-dots/stage-dots.component.html +13 -0
- package/src/lib/ui/components/stat-cards/stat-cards.component.html +44 -11
- package/src/lib/ui/components/status-dot/status-dot.component.html +13 -0
- package/src/lib/ui/components/switch/switch.component.html +1 -1
- package/src/lib/ui/components/tab-group/tab-group.component.html +37 -8
- package/src/lib/ui/components/tab-group/tab-group.component.scss +41 -1
- package/src/lib/ui/components/tag/tag.component.html +2 -2
- package/src/lib/ui/components/theme-picker/theme-picker.component.html +44 -0
- package/src/lib/ui/components/toast/toast.component.html +6 -6
- package/src/lib/ui/components/tree-diagram/tree-diagram.component.html +3 -3
- package/tailwind.css +13 -1
- package/theme.css +642 -69
- package/tokens.css +81 -19
- package/types/foxeltech-angular-ui-chart.d.ts +90 -3
- package/types/foxeltech-angular-ui-flow.d.ts +83 -1
- package/types/foxeltech-angular-ui.d.ts +909 -48
- package/utilities.css +16 -1
- package/BeVietnamPro/BeVietnamPro-Bold.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-ExtraLight.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Light.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Medium.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Regular.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-SemiBold.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Thin.woff2 +0 -0
- package/SpaceMono-Regular.woff2 +0 -0
- package/dm-sans/DMSans-Bold.woff2 +0 -0
- package/dm-sans/DMSans-Light.woff2 +0 -0
- package/dm-sans/DMSans-Medium.woff2 +0 -0
- package/dm-sans/DMSans-Regular.woff2 +0 -0
- package/dm-sans/DMSans-SemiBold.woff2 +0 -0
- package/dm-sans/DMSans-Thin.woff2 +0 -0
- package/orbitron/Orbitron-Bold.woff2 +0 -0
- package/orbitron/Orbitron-Medium.woff2 +0 -0
- package/orbitron/Orbitron-Regular.woff2 +0 -0
- package/orbitron/Orbitron-SemiBold.woff2 +0 -0
- package/roboto/Roboto-Black.woff2 +0 -0
- package/roboto/Roboto-BlackItalic.woff2 +0 -0
- package/roboto/Roboto-Bold.woff2 +0 -0
- package/roboto/Roboto-BoldCondensed.woff2 +0 -0
- package/roboto/Roboto-BoldCondensedItalic.woff2 +0 -0
- package/roboto/Roboto-BoldItalic.woff2 +0 -0
- package/roboto/Roboto-Condensed.woff2 +0 -0
- package/roboto/Roboto-CondensedItalic.woff2 +0 -0
- package/roboto/Roboto-Italic.woff2 +0 -0
- package/roboto/Roboto-Light.woff2 +0 -0
- package/roboto/Roboto-LightItalic.woff2 +0 -0
- package/roboto/Roboto-Medium.woff2 +0 -0
- package/roboto/Roboto-MediumItalic.woff2 +0 -0
- package/roboto/Roboto-Regular.woff2 +0 -0
- package/roboto/Roboto-Thin.woff2 +0 -0
- package/roboto/Roboto-ThinItalic.woff2 +0 -0
- package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.html +0 -21
- package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.scss +0 -0
- package/src/lib/ui/components/tab-component/tab.component.html +0 -1
package/tokens.css
CHANGED
|
@@ -3,16 +3,60 @@
|
|
|
3
3
|
* Replaces the old JS preset (tailwind.config.js / lodash.merge sharing).
|
|
4
4
|
*
|
|
5
5
|
* Colour tokens point at the runtime RGB-triplet variables from theme.css
|
|
6
|
-
* (
|
|
7
|
-
* working; opacity modifiers like bg-critical/10 are
|
|
8
|
-
* color-mix() and need no <alpha-value> plumbing.
|
|
6
|
+
* (OgeniumDashboards --og-* per [data-og-theme] on <html>, porcelain default)
|
|
7
|
+
* so theme switching keeps working; opacity modifiers like bg-critical/10 are
|
|
8
|
+
* handled by v4's color-mix() and need no <alpha-value> plumbing.
|
|
9
9
|
*/
|
|
10
10
|
/* `inline` is load-bearing: without it the rgb(var(--x)) values are baked
|
|
11
|
-
into :root once, so
|
|
11
|
+
into :root once, so [data-og-theme]'s runtime triplet overrides never reach
|
|
12
12
|
the utilities. inline makes every utility carry rgb(var(--x)) itself and
|
|
13
13
|
resolve at the element that uses it — same behavior as v3. */
|
|
14
14
|
@theme inline {
|
|
15
|
-
/*
|
|
15
|
+
/* ---- OG palette — use these in new/restyled markup ---- */
|
|
16
|
+
--color-page: rgb(var(--og-page-bg));
|
|
17
|
+
--color-surface: rgb(var(--og-surface));
|
|
18
|
+
--color-surface-raised: rgb(var(--og-surface-raised));
|
|
19
|
+
--color-surface-sunken: rgb(var(--og-surface-sunken));
|
|
20
|
+
--color-border: rgb(var(--og-border));
|
|
21
|
+
--color-border-subtle: rgb(var(--og-border-subtle));
|
|
22
|
+
--color-strong: rgb(var(--og-text));
|
|
23
|
+
--color-body: rgb(var(--og-text-body));
|
|
24
|
+
--color-muted: rgb(var(--og-text-muted));
|
|
25
|
+
--color-faint: rgb(var(--og-text-faint));
|
|
26
|
+
--color-accent: rgb(var(--og-accent));
|
|
27
|
+
--color-accent-fg: rgb(var(--og-accent-fg));
|
|
28
|
+
--color-accent-contrast: rgb(var(--og-accent-contrast));
|
|
29
|
+
--color-accent-soft: rgb(var(--og-accent-soft-bg));
|
|
30
|
+
--color-accent-soft-fg: rgb(var(--og-accent-soft-fg));
|
|
31
|
+
--color-positive: rgb(var(--og-positive));
|
|
32
|
+
--color-positive-soft: rgb(var(--og-positive-soft-bg));
|
|
33
|
+
--color-negative: rgb(var(--og-negative));
|
|
34
|
+
--color-negative-soft: rgb(var(--og-negative-soft-bg));
|
|
35
|
+
--color-warning-soft: rgb(var(--og-warning-soft-bg));
|
|
36
|
+
--color-neutral-soft: rgb(var(--og-neutral-soft-bg));
|
|
37
|
+
--color-neutral-soft-fg: rgb(var(--og-neutral-soft-fg));
|
|
38
|
+
--color-track: rgb(var(--og-track));
|
|
39
|
+
|
|
40
|
+
/* ---- CTA (New Analysis / New Scan) ----
|
|
41
|
+
Demo dùng một màu CỐ ĐỊNH cho nút hành động chính (`.bi-newbtn`), không
|
|
42
|
+
đổi theo theme và KHÔNG phải accent — nên để literal ở đây thay vì thành
|
|
43
|
+
token theme. Nguồn: lớp override của design, #c2582a / hover #b34e24. */
|
|
44
|
+
/* ---- Severity ramp CHO CHART ----
|
|
45
|
+
Màu literal đo trên demo (Critical #7f1d1d · High #dc2626 · Medium
|
|
46
|
+
#f59e0b · Low #16a34a; bộ dark nâng L cho đủ tương phản). TÁCH khỏi
|
|
47
|
+
`--color-critical/danger/warning/success` — mấy tên đó trỏ vào bộ LEGACY
|
|
48
|
+
`--og-tone-*` dùng cho text/nền, không phải màu chart của design. */
|
|
49
|
+
--color-sev-critical: rgb(var(--og-sev-critical));
|
|
50
|
+
--color-sev-danger: rgb(var(--og-sev-danger));
|
|
51
|
+
--color-sev-warning: rgb(var(--og-sev-warning));
|
|
52
|
+
--color-sev-success: rgb(var(--og-sev-success));
|
|
53
|
+
|
|
54
|
+
--color-cta: #c2582a;
|
|
55
|
+
--color-cta-hover: #b34e24;
|
|
56
|
+
|
|
57
|
+
/* ---- Legacy colour names (@deprecated — remove after the V2 campaign;
|
|
58
|
+
they resolve through the alias layer in theme.css, so every existing
|
|
59
|
+
class already renders the OG palette) ---- */
|
|
16
60
|
--color-gradient-primary-start: rgb(var(--gradient-primary-start));
|
|
17
61
|
--color-gradient-primary-end: rgb(var(--gradient-primary-end));
|
|
18
62
|
--color-gradient-success-start: rgb(var(--gradient-success-start));
|
|
@@ -46,6 +90,14 @@
|
|
|
46
90
|
--color-button-primary: rgb(var(--button-primary));
|
|
47
91
|
|
|
48
92
|
/* Breakpoints (v3 custom screens) */
|
|
93
|
+
/* ⚠️ THANG NÀY KHÔNG PHẢI MẶC ĐỊNH CỦA TAILWIND (640/768/1024/1280).
|
|
94
|
+
`lg` ở đây là **1080px**, không phải 1024px — đã gây lỗi "màn lg mà render
|
|
95
|
+
layout sm" (03/09): mọi viewport 1024-1079 (rất dễ gặp khi OS scaling
|
|
96
|
+
125-150% hoặc browser zoom) rơi xuống layout nhỏ. Anh Tú chốt GIỮ thang
|
|
97
|
+
này; đổi nó sẽ dịch ngưỡng của mọi `lg:`/`xl:` trong 5 app.
|
|
98
|
+
👉 Layout nào cần biết "có đủ chỗ thật hay không" thì dùng CONTAINER QUERY
|
|
99
|
+
theo bề rộng của chính nó (xem master-detail.component.css), đừng bám `lg:`.
|
|
100
|
+
`xl` là 1920px nên màn 1900px KHÔNG BAO GIỜ đạt `xl:`. */
|
|
49
101
|
--breakpoint-sm: 480px;
|
|
50
102
|
--breakpoint-md: 720px;
|
|
51
103
|
--breakpoint-lg: 1080px;
|
|
@@ -61,14 +113,22 @@
|
|
|
61
113
|
--shadow-2xl: 0 25px 50px -12px rgb(var(--shadow-color) / 0.25);
|
|
62
114
|
--inset-shadow-sm: inset 0 2px 4px 0 rgb(var(--shadow-color) / 0.05);
|
|
63
115
|
|
|
64
|
-
/*
|
|
65
|
-
|
|
66
|
-
--radius:
|
|
67
|
-
--radius-
|
|
68
|
-
--radius-
|
|
69
|
-
--radius-
|
|
70
|
-
|
|
71
|
-
|
|
116
|
+
/* Radius is a THEME variable in V2 (blueprint/terminal are square, ivory
|
|
117
|
+
controls are pills) — never hardcode border-radius in components. */
|
|
118
|
+
--radius-frame: var(--og-radius-frame);
|
|
119
|
+
--radius-card: var(--og-radius-card);
|
|
120
|
+
--radius-control: var(--og-radius-control);
|
|
121
|
+
--radius-pill: var(--og-radius-pill);
|
|
122
|
+
/* Legacy fixed scale remapped onto the theme radii so blueprint/terminal go
|
|
123
|
+
square with zero template edits. `rounded-full` stays Tailwind-native
|
|
124
|
+
9999px — avatars/dots must remain circular in every theme. */
|
|
125
|
+
--radius-sm: var(--og-radius-control);
|
|
126
|
+
--radius: var(--og-radius-control);
|
|
127
|
+
--radius-md: var(--og-radius-control);
|
|
128
|
+
--radius-lg: var(--og-radius-card);
|
|
129
|
+
--radius-xl: var(--og-radius-card);
|
|
130
|
+
--radius-2xl: var(--og-radius-card);
|
|
131
|
+
--radius-3xl: var(--og-radius-frame);
|
|
72
132
|
|
|
73
133
|
/* Named spacing scale (gap-small, p-semi, mb-large, …) */
|
|
74
134
|
--spacing-xs: 0.125rem;
|
|
@@ -79,12 +139,14 @@
|
|
|
79
139
|
--spacing-xl: 1.25rem;
|
|
80
140
|
--spacing-2xl: 1.5rem;
|
|
81
141
|
|
|
82
|
-
/* Font families
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
--font-
|
|
86
|
-
--font-
|
|
87
|
-
--font-
|
|
142
|
+
/* Font families — theme variables (blueprint/terminal switch to mono).
|
|
143
|
+
V2 set: Archivo (body/display), JetBrains Mono / IBM Plex Mono (mono),
|
|
144
|
+
Source Serif 4 (prose), Newsreader (ivory/blueprint display). */
|
|
145
|
+
--font-body: var(--og-font-body);
|
|
146
|
+
--font-display: var(--og-font-display);
|
|
147
|
+
--font-mono: var(--og-font-mono);
|
|
148
|
+
--font-prose: var(--og-font-prose);
|
|
149
|
+
--font-figure: var(--og-font-figure);
|
|
88
150
|
|
|
89
151
|
/* Font-size overrides (v3 preset values) */
|
|
90
152
|
--text-xs: 0.75rem;
|
|
@@ -2,7 +2,7 @@ import * as _angular_core from '@angular/core';
|
|
|
2
2
|
import { OnChanges, AfterViewInit, OnDestroy, ElementRef, ChangeDetectorRef } from '@angular/core';
|
|
3
3
|
import { EChartsOption, ECharts } from 'echarts';
|
|
4
4
|
|
|
5
|
-
type IChartType = 'bar' | 'pie' | 'sunburst' | 'auto';
|
|
5
|
+
type IChartType = 'bar' | 'pie' | 'sunburst' | 'line' | 'area-trend' | 'auto';
|
|
6
6
|
declare class ChartComponent implements OnChanges, AfterViewInit, OnDestroy {
|
|
7
7
|
private ref;
|
|
8
8
|
private cdr;
|
|
@@ -15,28 +15,109 @@ declare class ChartComponent implements OnChanges, AfterViewInit, OnDestroy {
|
|
|
15
15
|
readonly pieLegendAlign: _angular_core.InputSignal<string | number>;
|
|
16
16
|
readonly pieLegendPosition: _angular_core.InputSignal<string | number>;
|
|
17
17
|
readonly showPieLabel: _angular_core.InputSignal<boolean>;
|
|
18
|
+
/** Hide the built-in legend (panels that render their own legend beside the
|
|
19
|
+
donut); the donut then centres in the container. */
|
|
20
|
+
readonly showPieLegend: _angular_core.InputSignal<boolean>;
|
|
21
|
+
/** Caption under the donut's centre total (design: "42 / confirmed"). */
|
|
22
|
+
readonly pieCenterLabel: _angular_core.InputSignal<string>;
|
|
18
23
|
readonly mobileWidth: _angular_core.InputSignal<number>;
|
|
24
|
+
/** Override font for canvas text; empty = follow the theme's --og-font-figure. */
|
|
19
25
|
readonly labelFontFamily: _angular_core.InputSignal<string>;
|
|
20
26
|
readonly emptyText: _angular_core.InputSignal<string>;
|
|
21
27
|
readonly chartClick: _angular_core.OutputEmitterRef<any>;
|
|
22
28
|
readonly chartInit: _angular_core.OutputEmitterRef<ECharts>;
|
|
23
29
|
chartOptions: EChartsOption;
|
|
24
30
|
isEmpty: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* ⚠️ Cổng cho `<div echarts>` trong template. Trước đây div render NGAY với
|
|
33
|
+
* `chartOptions = {}`, nên NgxEchartsDirective khởi tạo chart bằng options
|
|
34
|
+
* RỖNG; options thật gán vào giữa lúc `await createChart()` của lần đó ⇒
|
|
35
|
+
* onOptionsChange() thấy `chart == null` và createChart() LẦN HAI trên cùng
|
|
36
|
+
* DOM node ⇒ "[ECharts] There is a chart instance already initialized on the
|
|
37
|
+
* dom.". Chỉ dựng directive khi đã có options thật ⇒ đúng một lần init.
|
|
38
|
+
*/
|
|
39
|
+
hasOptions: boolean;
|
|
25
40
|
labelFontSize: number;
|
|
26
41
|
private chartInstance?;
|
|
27
42
|
private resizeObserver?;
|
|
28
43
|
private intersectionObserver?;
|
|
29
44
|
private canInit;
|
|
45
|
+
private destroyed;
|
|
46
|
+
/**
|
|
47
|
+
* ⚠️ Đang chờ init đầu tiên của directive hoàn tất?
|
|
48
|
+
*
|
|
49
|
+
* NgxEchartsDirective đăng ký `changeFilter.notFirstAndEmpty('options', …)`:
|
|
50
|
+
* lần gán `options` ĐẦU bị bỏ qua (ngAfterViewInit lo), lần gán THỨ HAI gọi
|
|
51
|
+
* onOptionsChange(). Mà onOptionsChange() chỉ createChart() khi `this.chart`
|
|
52
|
+
* còn null — và nó null suốt thời gian `await createChart()` của lần đầu.
|
|
53
|
+
* Nên nếu ta gán `chartOptions` (object mới) trong khoảng await đó thì
|
|
54
|
+
* init() chạy HAI LẦN trên cùng DOM node ⇒
|
|
55
|
+
* "[ECharts] There is a chart instance already initialized on the dom."
|
|
56
|
+
*
|
|
57
|
+
* Cách chặn: trong khoảng chờ, giữ options ở `deferredOptions` chứ không đụng
|
|
58
|
+
* vào property đang bind; init xong thì áp một lần qua instance.
|
|
59
|
+
*/
|
|
60
|
+
private awaitingFirstInit;
|
|
61
|
+
private deferredOptions?;
|
|
62
|
+
private pendingFrames;
|
|
30
63
|
private isMobile;
|
|
31
64
|
private containerWidth;
|
|
32
65
|
constructor(ref: ElementRef<HTMLElement>, cdr: ChangeDetectorRef);
|
|
33
66
|
ngAfterViewInit(): void;
|
|
34
67
|
ngOnChanges(): void;
|
|
35
68
|
ngOnDestroy(): void;
|
|
69
|
+
/**
|
|
70
|
+
* ⚠️ RACE TRONG NGX-ECHARTS v20 — nguồn của
|
|
71
|
+
* "[ECharts] There is a chart instance already initialized on the dom."
|
|
72
|
+
*
|
|
73
|
+
* NgxEchartsDirective.onOptionsChange() làm:
|
|
74
|
+
* this.chart = await this.createChart(); // ← destroy có thể rơi vào đây
|
|
75
|
+
* this.chart$.next(this.chart);
|
|
76
|
+
* this.chartInit.emit(this.chart);
|
|
77
|
+
*
|
|
78
|
+
* Destroy đúng lúc đang await thì ngOnDestroy → dispose() thấy `this.chart == null`
|
|
79
|
+
* nên KHÔNG dispose gì. Sau đó await resolve, gán một instance ECharts còn sống cho
|
|
80
|
+
* directive đã chết → instance MỒ CÔI, vẫn nằm trong registry của echarts gắn với
|
|
81
|
+
* DOM node đó. Angular tái dùng node ⇒ init() lần sau báo "already initialized".
|
|
82
|
+
*
|
|
83
|
+
* Không thể bắt qua (chartInit): Angular v20 TỪ CHỐI emit trên OutputRef đã destroy
|
|
84
|
+
* (chỉ log NG0953, listener không hề được gọi). Nên đường duy nhất là hỏi thẳng
|
|
85
|
+
* echarts xem node còn instance nào không, ở các macrotask SAU destroy.
|
|
86
|
+
*/
|
|
87
|
+
private sweepOrphanInstance;
|
|
88
|
+
/** rAF có thể huỷ được khi destroy — tránh chạm instance đã dispose. */
|
|
89
|
+
private schedule;
|
|
90
|
+
/** Instance còn dùng được? (đã dispose thì mọi API echarts đều ném lỗi) */
|
|
91
|
+
private get liveChart();
|
|
36
92
|
onThemeChange(): void;
|
|
37
93
|
onChartClick(event: any): void;
|
|
38
|
-
onChartInit(
|
|
94
|
+
onChartInit(raw: any): void;
|
|
95
|
+
/**
|
|
96
|
+
* @returns true nếu trạng thái responsive THỰC SỰ đổi (nên dựng lại options).
|
|
97
|
+
*
|
|
98
|
+
* Trả về boolean là điều then chốt cho animation lúc chart xuất hiện — xem
|
|
99
|
+
* ghi chú ở `forceMediaRecalc`.
|
|
100
|
+
*/
|
|
39
101
|
private updateResponsiveState;
|
|
102
|
+
/**
|
|
103
|
+
* ⚠️ CHỈ dựng lại options khi kích thước thật sự đổi — nếu không thì
|
|
104
|
+
* **animation lúc chart xuất hiện bị giết**.
|
|
105
|
+
*
|
|
106
|
+
* Đường đi: `onChartInit` → schedule(forceMediaRecalc) → chạy ở frame KẾ
|
|
107
|
+
* TIẾP. Nếu chỗ này vô điều kiện `rebuildChart()` (clear + setOption notMerge)
|
|
108
|
+
* thì nó xoá sạch và vẽ lại từ đầu ~16ms sau lần vẽ đầu, trong khi animation
|
|
109
|
+
* xuất hiện dài ~1000ms ⇒ người dùng thấy chart hiện ra đứng im.
|
|
110
|
+
*
|
|
111
|
+
* Đo được: lần xuất hiện đầu 1/12 frame khác nhau (đứng yên) trong khi vẽ lại
|
|
112
|
+
* bằng `theme-changed` cho 9/12 → animation của ECharts vẫn bật, chỉ lần đầu
|
|
113
|
+
* bị cắt.
|
|
114
|
+
*
|
|
115
|
+
* Trước Pha 0 lỗi này bị che: lần init đầu dùng `chartOptions = {}` nên
|
|
116
|
+
* animation xuất hiện xảy ra ở lần cập nhật SAU, tức sau khi forceMediaRecalc
|
|
117
|
+
* đã chạy xong. Cổng `hasOptions` đưa options thật về ngay lần init nên lộ ra.
|
|
118
|
+
*
|
|
119
|
+
* `resize()` thì luôn gọi được — nó không cắt animation.
|
|
120
|
+
*/
|
|
40
121
|
private forceMediaRecalc;
|
|
41
122
|
private rebuildChart;
|
|
42
123
|
private checkEmpty;
|
|
@@ -44,9 +125,15 @@ declare class ChartComponent implements OnChanges, AfterViewInit, OnDestroy {
|
|
|
44
125
|
private calcPieLayout;
|
|
45
126
|
private detectType;
|
|
46
127
|
private buildOptions;
|
|
128
|
+
private categoryAxis;
|
|
129
|
+
private valueAxis;
|
|
130
|
+
/** Canvas không ăn var() — resolve font stack thật tại render; chart đã
|
|
131
|
+
rebuild theo event theme-changed nên tự đổi font khi đổi theme
|
|
132
|
+
(blueprint/terminal dùng mono qua --og-font-figure). */
|
|
133
|
+
private resolvedFontFamily;
|
|
47
134
|
private resolvePalette;
|
|
48
135
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChartComponent, never>;
|
|
49
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChartComponent, "fx-ui-chart", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "palette": { "alias": "palette"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "pieLegendAlign": { "alias": "pieLegendAlign"; "required": false; "isSignal": true; }; "pieLegendPosition": { "alias": "pieLegendPosition"; "required": false; "isSignal": true; }; "showPieLabel": { "alias": "showPieLabel"; "required": false; "isSignal": true; }; "mobileWidth": { "alias": "mobileWidth"; "required": false; "isSignal": true; }; "labelFontFamily": { "alias": "labelFontFamily"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; }, { "chartClick": "chartClick"; "chartInit": "chartInit"; }, never, never, true, never>;
|
|
136
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChartComponent, "fx-ui-chart", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "palette": { "alias": "palette"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "pieLegendAlign": { "alias": "pieLegendAlign"; "required": false; "isSignal": true; }; "pieLegendPosition": { "alias": "pieLegendPosition"; "required": false; "isSignal": true; }; "showPieLabel": { "alias": "showPieLabel"; "required": false; "isSignal": true; }; "showPieLegend": { "alias": "showPieLegend"; "required": false; "isSignal": true; }; "pieCenterLabel": { "alias": "pieCenterLabel"; "required": false; "isSignal": true; }; "mobileWidth": { "alias": "mobileWidth"; "required": false; "isSignal": true; }; "labelFontFamily": { "alias": "labelFontFamily"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; }, { "chartClick": "chartClick"; "chartInit": "chartInit"; }, never, never, true, never>;
|
|
50
137
|
}
|
|
51
138
|
|
|
52
139
|
export { ChartComponent };
|
|
@@ -1,6 +1,87 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
2
|
import { Node, Edge, Connection } from 'ngx-vflow';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* What a chain node represents. Structural kinds (`entry`, `convergence`,
|
|
6
|
+
* `impact`, `stage`) can be derived from the graph itself; the validation kinds
|
|
7
|
+
* (`mitigation`, `review`, `not-reproduced`) come from an analyst verdict.
|
|
8
|
+
*/
|
|
9
|
+
type FxChainNodeKind = 'entry' | 'convergence' | 'mitigation' | 'review' | 'not-reproduced' | 'impact' | 'stage';
|
|
10
|
+
interface FxChainNode {
|
|
11
|
+
id: string;
|
|
12
|
+
/** Node title — rendered in the figure/mono face. */
|
|
13
|
+
label: string;
|
|
14
|
+
kind: FxChainNodeKind;
|
|
15
|
+
/** Caller-translated kind eyebrow; falls back to the raw kind key. */
|
|
16
|
+
kindLabel?: string;
|
|
17
|
+
/** Caller-translated muted subtitle. */
|
|
18
|
+
caption?: string;
|
|
19
|
+
/** true = verified badge, false = unverified badge, null/undefined = no badge. */
|
|
20
|
+
verified?: boolean | null;
|
|
21
|
+
/** Explicit column (0 = leftmost); omit to derive depth from the edges. */
|
|
22
|
+
column?: number;
|
|
23
|
+
/** Explicit row inside the column; omit to stack in declaration order. */
|
|
24
|
+
row?: number;
|
|
25
|
+
}
|
|
26
|
+
interface FxChainEdge {
|
|
27
|
+
source: string;
|
|
28
|
+
target: string;
|
|
29
|
+
}
|
|
30
|
+
/** Kind → severity token. Exported so callers can tint matching chips (the
|
|
31
|
+
stage list beside the canvas) from the same source of truth. */
|
|
32
|
+
declare const FX_CHAIN_KIND_TONE: Record<FxChainNodeKind, string>;
|
|
33
|
+
/**
|
|
34
|
+
* V2 exploit-chain canvas — the attack-path graph of design refs 04..07:
|
|
35
|
+
* kind-tinted node cards laid out left→right, curved edges, draggable nodes on
|
|
36
|
+
* a pannable/zoomable surface.
|
|
37
|
+
*
|
|
38
|
+
* Presentational: it takes a graph plus the currently selected node and emits
|
|
39
|
+
* clicks. Layout is derived from the edges (longest path from a source) unless
|
|
40
|
+
* a node pins its own column/row, so callers can hand over a plain chain.
|
|
41
|
+
*
|
|
42
|
+
* <fx-ui-flow-canvas [nodes]="chainNodes" [edges]="chainEdges"
|
|
43
|
+
* [activeId]="stageId()" (nodeClick)="selectStage($event)" />
|
|
44
|
+
*/
|
|
45
|
+
declare class FlowCanvasComponent {
|
|
46
|
+
readonly nodes: _angular_core.InputSignal<FxChainNode[]>;
|
|
47
|
+
readonly edges: _angular_core.InputSignal<FxChainEdge[]>;
|
|
48
|
+
/** Selected/current node: full opacity + accent border; the rest dim. */
|
|
49
|
+
readonly activeId: _angular_core.InputSignal<string | null>;
|
|
50
|
+
/** Explicit canvas height; omit to size it from the number of stacked rows. */
|
|
51
|
+
readonly height: _angular_core.InputSignal<string>;
|
|
52
|
+
/** Caller-translated hint shown when the graph is empty. */
|
|
53
|
+
readonly emptyText: _angular_core.InputSignal<string>;
|
|
54
|
+
readonly nodeClick: _angular_core.OutputEmitterRef<string>;
|
|
55
|
+
/** Column index per node: pinned value, else longest path from a source. */
|
|
56
|
+
private readonly columns;
|
|
57
|
+
/** ngx-vflow nodes: html-template cards positioned by the derived layout. */
|
|
58
|
+
readonly flowNodes: _angular_core.Signal<Node[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Edges stay identity-stable across selections: state lives in the template
|
|
61
|
+
* (read off `activeId`), so selecting a stage never re-creates them.
|
|
62
|
+
*/
|
|
63
|
+
readonly flowEdges: _angular_core.Signal<Edge<unknown>[]>;
|
|
64
|
+
/** Nodes one hop from the selection — they stay lit alongside it. */
|
|
65
|
+
private readonly relatedIds;
|
|
66
|
+
readonly isEmpty: _angular_core.Signal<boolean>;
|
|
67
|
+
/**
|
|
68
|
+
* A linear chain needs one row, the design's converging entries need three —
|
|
69
|
+
* sizing from the layout keeps the card from leaving a tall empty band.
|
|
70
|
+
*/
|
|
71
|
+
readonly resolvedHeight: _angular_core.Signal<string>;
|
|
72
|
+
kindTone(kind: FxChainNodeKind): string;
|
|
73
|
+
isActive(node: FxChainNode): boolean;
|
|
74
|
+
/** One hop from the selection: lit, but without the selected accent frame. */
|
|
75
|
+
isRelated(node: FxChainNode): boolean;
|
|
76
|
+
/** Nothing selected → every node reads at full strength. */
|
|
77
|
+
isDimmed(node: FxChainNode): boolean;
|
|
78
|
+
/** An edge touching the selection is part of the step being read. */
|
|
79
|
+
isEdgeActive(edge: Edge): boolean;
|
|
80
|
+
isEdgeDimmed(edge: Edge): boolean;
|
|
81
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlowCanvasComponent, never>;
|
|
82
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlowCanvasComponent, "fx-ui-flow-canvas", never, { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "edges": { "alias": "edges"; "required": false; "isSignal": true; }; "activeId": { "alias": "activeId"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; }, { "nodeClick": "nodeClick"; }, never, never, true, never>;
|
|
83
|
+
}
|
|
84
|
+
|
|
4
85
|
declare class FlowConnection {
|
|
5
86
|
readonly nodes: _angular_core.InputSignal<Node[]>;
|
|
6
87
|
edges: Edge[];
|
|
@@ -11,4 +92,5 @@ declare class FlowConnection {
|
|
|
11
92
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlowConnection, "fx-ui-flow-connection", never, { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "edges": { "alias": "edges"; "required": false; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; "isSignal": true; }; "view": { "alias": "view"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
12
93
|
}
|
|
13
94
|
|
|
14
|
-
export { FlowConnection };
|
|
95
|
+
export { FX_CHAIN_KIND_TONE, FlowCanvasComponent, FlowConnection };
|
|
96
|
+
export type { FxChainEdge, FxChainNode, FxChainNodeKind };
|