File size: 6,195 Bytes
fa9c65f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import { Panel } from './Panel';
import { getChinaActivityNowcastData } from '@/services/china-activity-nowcast';
import { unsafeRawHtml } from '@/utils/sanitize';
import type { ChinaActivityNowcastResponse } from '../../shared/china-activity-nowcast';
import { renderChinaActivityNowcastView } from './china-activity-nowcast-view';
const STYLE_ID = 'china-activity-nowcast-panel-styles';
function injectStyles(): void {
if (document.getElementById(STYLE_ID)) return;
const style = document.createElement('style');
style.id = STYLE_ID;
style.textContent = `
.china-nowcast-view { display: grid; gap: 12px; color: var(--text-primary); }
.china-nowcast-summary, .china-nowcast-official, .china-nowcast-method {
border: 1px solid var(--border-color); background: color-mix(in srgb, var(--panel-bg) 88%, transparent);
}
.china-nowcast-summary {
display: grid; grid-template-columns: minmax(0, 1fr) minmax(180px, .38fr);
gap: 14px; align-items: center; padding: 14px;
border-left: 3px solid var(--text-muted);
}
.china-nowcast-summary--agreement { border-left-color: var(--success-color, #45bd7d); }
.china-nowcast-summary--proxy_leading_divergence,
.china-nowcast-summary--official_leading_divergence { border-left-color: var(--warning-color, #e3a94f); }
.china-nowcast-summary--mixed_signals { border-left-color: #8f7bd6; }
.china-nowcast-summary--insufficient_data { border-left-color: var(--text-muted); }
.china-nowcast-eyebrow, .china-nowcast-family {
display: block; color: var(--text-muted); font-size: 10px; font-weight: 700;
letter-spacing: .11em; text-transform: uppercase;
}
.china-nowcast-summary h3, .china-nowcast-official h4,
.china-nowcast-contribution h4, .china-nowcast-method h4 { margin: 4px 0; }
.china-nowcast-summary p, .china-nowcast-official p,
.china-nowcast-contribution p, .china-nowcast-method p {
margin: 5px 0; color: var(--text-secondary); line-height: 1.45;
}
.china-nowcast-confidence { display: grid; gap: 3px; padding: 10px; background: var(--surface-hover); }
.china-nowcast-confidence > span {
width: max-content; padding: 2px 7px; border: 1px solid currentColor;
color: var(--text-secondary); font-size: 10px; text-transform: uppercase;
}
.china-nowcast-confidence small { color: var(--text-muted); line-height: 1.35; }
.china-nowcast-official { padding: 12px 14px; }
.china-nowcast-official dl, .china-nowcast-contribution dl { margin: 8px 0 0; }
.china-nowcast-official dl { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.china-nowcast-official dl div, .china-nowcast-contribution dl div { min-width: 0; }
.china-nowcast-official dt, .china-nowcast-contribution dt {
color: var(--text-muted); font-size: 10px; text-transform: uppercase;
}
.china-nowcast-official dd, .china-nowcast-contribution dd {
margin: 2px 0 0; overflow-wrap: anywhere; color: var(--text-secondary);
}
.china-nowcast-contributions {
display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
}
.china-nowcast-contribution {
min-width: 0; padding: 11px; border: 1px solid var(--border-color);
background: var(--surface-bg, var(--panel-bg));
}
.china-nowcast-contribution--strengthening { border-top: 2px solid var(--success-color, #45bd7d); }
.china-nowcast-contribution--weakening { border-top: 2px solid var(--danger-color, #df6969); }
.china-nowcast-contribution--unchanged { border-top: 2px solid #8f7bd6; }
.china-nowcast-contribution--excluded { border-top: 2px solid var(--text-muted); opacity: .86; }
.china-nowcast-contribution__heading {
display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: start;
}
.china-nowcast-contribution__state {
max-width: 190px; color: var(--text-secondary); font-size: 11px; text-align: right;
}
.china-nowcast-contribution dl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px 12px; }
.china-nowcast-contribution a { color: var(--accent-color); }
.china-nowcast-method summary {
padding: 11px 13px; cursor: pointer; font-weight: 650; color: var(--text-secondary);
}
.china-nowcast-method__grid {
display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px; padding: 0 13px 13px;
}
.china-nowcast-method ul { margin: 7px 0 0; padding-left: 18px; color: var(--text-secondary); }
.china-nowcast-method li { margin: 4px 0; line-height: 1.4; }
.china-nowcast-method li span { display: block; color: var(--text-muted); font-size: 11px; }
@media (max-width: 720px) {
.china-nowcast-summary, .china-nowcast-contributions,
.china-nowcast-method__grid { grid-template-columns: minmax(0, 1fr); }
.china-nowcast-contribution__heading { grid-template-columns: minmax(0, 1fr); }
.china-nowcast-contribution__state { max-width: none; text-align: left; }
}
`;
document.head.appendChild(style);
}
export class ChinaActivityNowcastPanel extends Panel {
private response: ChinaActivityNowcastResponse | null = null;
constructor() {
super({
id: 'china-activity-nowcast',
title: 'China Activity Nowcast',
className: 'panel-wide',
defaultRowSpan: 2,
infoTooltip: 'A deterministic directional comparison of revision-aware official activity and reviewed proxy families. Missing and stale inputs are excluded; this is not a replacement GDP estimate.',
});
injectStyles();
}
public async fetchData(): Promise<boolean> {
this.showLoading();
const response = await getChinaActivityNowcastData();
this.setData(response);
return response.state !== 'insufficient_data';
}
public setData(response: ChinaActivityNowcastResponse): void {
this.response = response;
this.render();
}
private render(): void {
if (this.response === null) return;
this.setSafeContent(unsafeRawHtml(
renderChinaActivityNowcastView(this.response),
'China activity nowcast renderer escapes every dynamic value before constructing markup',
));
}
}
|