mviz 1.6.3 → 1.6.4
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/dist/core/export.js +7 -2
- package/dist/core/themes.js +10 -5
- package/dist/layout/parser.js +10 -1
- package/dist/layout/templates.js +23 -19
- package/package.json +2 -2
package/dist/core/export.js
CHANGED
|
@@ -37,7 +37,7 @@ export function generateExportCss() {
|
|
|
37
37
|
box-shadow: 0 2px 8px rgba(0,0,0,0.18);
|
|
38
38
|
padding: 4px 0;
|
|
39
39
|
min-width: 200px;
|
|
40
|
-
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
40
|
+
font-family: var(--font-family, 'Helvetica Neue', Helvetica, Arial, sans-serif);
|
|
41
41
|
font-size: 12px;
|
|
42
42
|
color: ${COLORS.TEXT_DARK};
|
|
43
43
|
}
|
|
@@ -136,9 +136,14 @@ export function generateExportJs() {
|
|
|
136
136
|
return { div: tmpDiv, chart: tmpChart };
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
function getThemeFont() {
|
|
140
|
+
var fontFamily = getComputedStyle(document.body).fontFamily;
|
|
141
|
+
return fontFamily || '"Helvetica Neue", Helvetica, Arial, sans-serif';
|
|
142
|
+
}
|
|
143
|
+
|
|
139
144
|
function drawTitle(ctx, title, pixelRatio) {
|
|
140
145
|
ctx.fillStyle = isDarkTheme() ? CFG.TEXT_DARK : CFG.TEXT_LIGHT;
|
|
141
|
-
ctx.font = 'bold ' + Math.round(CFG.TITLE_FONT_SIZE * pixelRatio) + 'px
|
|
146
|
+
ctx.font = 'bold ' + Math.round(CFG.TITLE_FONT_SIZE * pixelRatio) + 'px ' + getThemeFont();
|
|
142
147
|
ctx.textAlign = 'left';
|
|
143
148
|
ctx.textBaseline = 'top';
|
|
144
149
|
ctx.fillText(
|
package/dist/core/themes.js
CHANGED
|
@@ -193,11 +193,15 @@ export function getPalette(theme = 'light') {
|
|
|
193
193
|
* Custom theme can specify which base theme to extend.
|
|
194
194
|
*/
|
|
195
195
|
export function getThemeColorsWithCustom(theme = 'light', custom) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
196
|
+
// Only apply custom color overrides when the requested theme matches
|
|
197
|
+
// the theme the custom colors were designed for (custom.extends).
|
|
198
|
+
// For the opposite theme, use standard defaults so dark mode isn't
|
|
199
|
+
// broken by light-mode custom colors (and vice versa).
|
|
200
|
+
const customExtends = custom?.extends ?? 'light';
|
|
201
|
+
if (!custom?.colors || theme !== customExtends) {
|
|
202
|
+
return getThemeColors(theme);
|
|
200
203
|
}
|
|
204
|
+
const baseColors = getThemeColors(customExtends);
|
|
201
205
|
return { ...baseColors, ...custom.colors };
|
|
202
206
|
}
|
|
203
207
|
/**
|
|
@@ -249,10 +253,11 @@ export function getTooltipConfig(theme = 'light') {
|
|
|
249
253
|
export function getBaseOption(spec) {
|
|
250
254
|
const theme = spec.theme ?? 'light';
|
|
251
255
|
const colors = getThemeColors(theme);
|
|
256
|
+
const fonts = getFontsWithCustom(spec.customTheme);
|
|
252
257
|
return {
|
|
253
258
|
backgroundColor: 'transparent',
|
|
254
259
|
textStyle: {
|
|
255
|
-
fontFamily:
|
|
260
|
+
fontFamily: fonts.family,
|
|
256
261
|
color: colors.text,
|
|
257
262
|
},
|
|
258
263
|
title: spec.title
|
package/dist/layout/parser.js
CHANGED
|
@@ -12,7 +12,7 @@ import { getOptionsBuilder } from '../charts/index.js';
|
|
|
12
12
|
import { serializeOption } from '../core/serializer.js';
|
|
13
13
|
import { formatNumber, inferFormat, resolveCurrency } from '../core/formatting.js';
|
|
14
14
|
import { lintSpec } from '../core/linter.js';
|
|
15
|
-
import { COLORS, GRID_TOTAL_COLUMNS, DEFAULT_SIZES, autoSizeChart, getHeatmapColors, getThemeColors, getThemeColorsWithCustom, ALERT_ICONS, } from '../core/themes.js';
|
|
15
|
+
import { COLORS, GRID_TOTAL_COLUMNS, DEFAULT_SIZES, autoSizeChart, getHeatmapColors, getThemeColors, getThemeColorsWithCustom, getFontsWithCustom, ALERT_ICONS, } from '../core/themes.js';
|
|
16
16
|
import { renderMermaid, renderMermaidAscii } from 'beautiful-mermaid';
|
|
17
17
|
import { formatCell, computeHeatmapRanges, computeDumbbellRanges, } from '../components/table.js';
|
|
18
18
|
// Height per row unit (compact for print) - must match Python's ROW_HEIGHT_PX
|
|
@@ -139,16 +139,25 @@ function renderEchartsComponent(compType, spec, chartId, colSpan, itemHeight, an
|
|
|
139
139
|
}
|
|
140
140
|
const chartHeight = itemHeight - (title ? 24 : 0);
|
|
141
141
|
// Note: Time series validation is handled by the linter when specs are parsed
|
|
142
|
+
// Resolve custom font for ECharts textStyle injection
|
|
143
|
+
const fontFamily = getFontsWithCustom(customTheme).family;
|
|
144
|
+
function applyFont(option) {
|
|
145
|
+
option.textStyle = { ...(option.textStyle ?? {}), fontFamily };
|
|
146
|
+
}
|
|
142
147
|
// Generate light theme options
|
|
143
148
|
const specLight = { ...spec, theme: 'light', height: chartHeight, customTheme };
|
|
144
149
|
const optionLight = builder(specLight);
|
|
145
150
|
if (!optionLight) {
|
|
146
151
|
return { html: null, script: null };
|
|
147
152
|
}
|
|
153
|
+
applyFont(optionLight);
|
|
148
154
|
const optionJsonLight = serializeOption(optionLight);
|
|
149
155
|
// Generate dark theme options
|
|
150
156
|
const specDark = { ...spec, theme: 'dark', height: chartHeight, customTheme };
|
|
151
157
|
const optionDark = builder(specDark);
|
|
158
|
+
if (optionDark) {
|
|
159
|
+
applyFont(optionDark);
|
|
160
|
+
}
|
|
152
161
|
const optionJsonDark = optionDark ? serializeOption(optionDark) : null;
|
|
153
162
|
const anchorAttr = anchorId ? ` id="${anchorId}"` : '';
|
|
154
163
|
const html = `
|
package/dist/layout/templates.js
CHANGED
|
@@ -103,7 +103,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
103
103
|
margin-bottom: 8px;
|
|
104
104
|
}
|
|
105
105
|
.page-title {
|
|
106
|
-
font-family:
|
|
106
|
+
font-family: var(--font-family);
|
|
107
107
|
font-size: 18px;
|
|
108
108
|
font-weight: 900;
|
|
109
109
|
margin-bottom: 12px;
|
|
@@ -119,7 +119,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
119
119
|
border-top: 1px solid var(--grid);
|
|
120
120
|
}
|
|
121
121
|
.section-title {
|
|
122
|
-
font-family:
|
|
122
|
+
font-family: var(--font-family);
|
|
123
123
|
font-size: 14px;
|
|
124
124
|
font-weight: 900;
|
|
125
125
|
letter-spacing: 0.05em;
|
|
@@ -128,7 +128,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
128
128
|
margin-bottom: 16px;
|
|
129
129
|
}
|
|
130
130
|
.chart-title {
|
|
131
|
-
font-family:
|
|
131
|
+
font-family: var(--font-family); font-weight: 700;
|
|
132
132
|
font-size: 10px;
|
|
133
133
|
font-weight: bold;
|
|
134
134
|
color: var(--text);
|
|
@@ -157,6 +157,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
157
157
|
.grid-item { break-inside: avoid; page-break-inside: avoid; }
|
|
158
158
|
.dashboard-section { break-inside: avoid; page-break-inside: avoid; }
|
|
159
159
|
.dashboard-section.page-break { page-break-before: always; }
|
|
160
|
+
.section-title { break-after: avoid; page-break-after: avoid; }
|
|
160
161
|
.data-table { break-inside: avoid; page-break-inside: avoid; }
|
|
161
162
|
.theme-toggle { display: none; }
|
|
162
163
|
.title-row { break-after: avoid; page-break-after: avoid; }
|
|
@@ -172,7 +173,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
172
173
|
transition: background 0.3s;
|
|
173
174
|
}
|
|
174
175
|
.big-value {
|
|
175
|
-
font-family:
|
|
176
|
+
font-family: var(--font-family); font-weight: 700;
|
|
176
177
|
font-size: 28px;
|
|
177
178
|
font-weight: bold;
|
|
178
179
|
color: var(--text);
|
|
@@ -187,7 +188,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
187
188
|
font-size: 16px;
|
|
188
189
|
}
|
|
189
190
|
.delta .value {
|
|
190
|
-
font-family:
|
|
191
|
+
font-family: var(--font-family);
|
|
191
192
|
font-size: 16px;
|
|
192
193
|
font-weight: bold;
|
|
193
194
|
}
|
|
@@ -244,7 +245,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
244
245
|
width: 100%; border-collapse: collapse; font-size: 11px;
|
|
245
246
|
}
|
|
246
247
|
.data-table th {
|
|
247
|
-
font-family:
|
|
248
|
+
font-family: var(--font-family); font-size: 9px; font-weight: bold;
|
|
248
249
|
color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em;
|
|
249
250
|
padding: 6px 8px; border-bottom: 1px solid var(--text); text-align: left;
|
|
250
251
|
}
|
|
@@ -290,7 +291,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
290
291
|
margin-bottom: 4px;
|
|
291
292
|
}
|
|
292
293
|
.inline-header-text {
|
|
293
|
-
font-family:
|
|
294
|
+
font-family: var(--font-family);
|
|
294
295
|
font-size: 11px;
|
|
295
296
|
font-weight: 700;
|
|
296
297
|
color: var(--text);
|
|
@@ -319,7 +320,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
319
320
|
.pct-bar-value {
|
|
320
321
|
font-size: 11px;
|
|
321
322
|
color: var(--text);
|
|
322
|
-
font-family:
|
|
323
|
+
font-family: var(--font-family);
|
|
323
324
|
font-weight: 700;
|
|
324
325
|
min-width: 32px;
|
|
325
326
|
flex-shrink: 0;
|
|
@@ -340,7 +341,7 @@ export function generateDashboardCss(customTheme, orientation = 'portrait') {
|
|
|
340
341
|
padding: 4px 8px;
|
|
341
342
|
border-radius: 4px;
|
|
342
343
|
font-size: 11px;
|
|
343
|
-
font-family:
|
|
344
|
+
font-family: var(--font-family);
|
|
344
345
|
white-space: nowrap;
|
|
345
346
|
opacity: 0;
|
|
346
347
|
visibility: hidden;
|
|
@@ -447,6 +448,8 @@ export function generateTestHarnessCss() {
|
|
|
447
448
|
--grid: ${colorsLight.border};
|
|
448
449
|
--red: ${colorsLight.accent};
|
|
449
450
|
--link: ${linkColor};
|
|
451
|
+
--font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
452
|
+
--font-mono: 'Consolas', 'Monaco', monospace;
|
|
450
453
|
}
|
|
451
454
|
body.theme-dark {
|
|
452
455
|
--bg: ${colorsDark.background};
|
|
@@ -459,7 +462,7 @@ export function generateTestHarnessCss() {
|
|
|
459
462
|
}
|
|
460
463
|
|
|
461
464
|
body {
|
|
462
|
-
font-family:
|
|
465
|
+
font-family: var(--font-family);
|
|
463
466
|
background: var(--bg);
|
|
464
467
|
color: var(--text);
|
|
465
468
|
transition: background-color 0.3s, color 0.3s;
|
|
@@ -604,7 +607,7 @@ export function generateTestHarnessCss() {
|
|
|
604
607
|
margin-bottom: 40px;
|
|
605
608
|
}
|
|
606
609
|
.section-title {
|
|
607
|
-
font-family:
|
|
610
|
+
font-family: var(--font-family);
|
|
608
611
|
font-size: 14px;
|
|
609
612
|
font-weight: 900;
|
|
610
613
|
letter-spacing: 0.05em;
|
|
@@ -634,7 +637,7 @@ export function generateTestHarnessCss() {
|
|
|
634
637
|
margin-bottom: 8px;
|
|
635
638
|
}
|
|
636
639
|
.page-title {
|
|
637
|
-
font-family:
|
|
640
|
+
font-family: var(--font-family);
|
|
638
641
|
font-size: 18px;
|
|
639
642
|
font-weight: 900;
|
|
640
643
|
margin-bottom: 12px;
|
|
@@ -650,7 +653,7 @@ export function generateTestHarnessCss() {
|
|
|
650
653
|
border-top: 1px solid var(--grid);
|
|
651
654
|
}
|
|
652
655
|
.chart-title {
|
|
653
|
-
font-family:
|
|
656
|
+
font-family: var(--font-family); font-weight: 700;
|
|
654
657
|
font-size: 10px;
|
|
655
658
|
font-weight: bold;
|
|
656
659
|
color: var(--text);
|
|
@@ -688,7 +691,7 @@ export function generateTestHarnessCss() {
|
|
|
688
691
|
|
|
689
692
|
/* Component styles */
|
|
690
693
|
.big-value {
|
|
691
|
-
font-family:
|
|
694
|
+
font-family: var(--font-family); font-weight: 700;
|
|
692
695
|
font-size: 28px;
|
|
693
696
|
font-weight: bold;
|
|
694
697
|
color: var(--text);
|
|
@@ -703,7 +706,7 @@ export function generateTestHarnessCss() {
|
|
|
703
706
|
font-size: 16px;
|
|
704
707
|
}
|
|
705
708
|
.delta .value {
|
|
706
|
-
font-family:
|
|
709
|
+
font-family: var(--font-family);
|
|
707
710
|
font-size: 16px;
|
|
708
711
|
font-weight: bold;
|
|
709
712
|
}
|
|
@@ -757,7 +760,7 @@ export function generateTestHarnessCss() {
|
|
|
757
760
|
width: 100%; border-collapse: collapse; font-size: 11px;
|
|
758
761
|
}
|
|
759
762
|
.data-table th {
|
|
760
|
-
font-family:
|
|
763
|
+
font-family: var(--font-family); font-size: 9px; font-weight: bold;
|
|
761
764
|
color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em;
|
|
762
765
|
padding: 6px 8px; border-bottom: 1px solid var(--text); text-align: left;
|
|
763
766
|
}
|
|
@@ -784,7 +787,7 @@ export function generateTestHarnessCss() {
|
|
|
784
787
|
margin-bottom: 4px;
|
|
785
788
|
}
|
|
786
789
|
.inline-header-text {
|
|
787
|
-
font-family:
|
|
790
|
+
font-family: var(--font-family);
|
|
788
791
|
font-size: 11px;
|
|
789
792
|
font-weight: 700;
|
|
790
793
|
color: var(--text);
|
|
@@ -814,7 +817,7 @@ export function generateTestHarnessCss() {
|
|
|
814
817
|
.pct-bar-value {
|
|
815
818
|
font-size: 11px;
|
|
816
819
|
color: var(--text);
|
|
817
|
-
font-family:
|
|
820
|
+
font-family: var(--font-family);
|
|
818
821
|
font-weight: 700;
|
|
819
822
|
min-width: 32px;
|
|
820
823
|
flex-shrink: 0;
|
|
@@ -836,7 +839,7 @@ export function generateTestHarnessCss() {
|
|
|
836
839
|
padding: 4px 8px;
|
|
837
840
|
border-radius: 4px;
|
|
838
841
|
font-size: 11px;
|
|
839
|
-
font-family:
|
|
842
|
+
font-family: var(--font-family);
|
|
840
843
|
white-space: nowrap;
|
|
841
844
|
opacity: 0;
|
|
842
845
|
visibility: hidden;
|
|
@@ -880,6 +883,7 @@ export function generateTestHarnessCss() {
|
|
|
880
883
|
.grid-item { break-inside: avoid; page-break-inside: avoid; }
|
|
881
884
|
.dashboard-section { break-inside: avoid; page-break-inside: avoid; }
|
|
882
885
|
.dashboard-section.page-break { page-break-before: always; }
|
|
886
|
+
.section-title { break-after: avoid; page-break-after: avoid; }
|
|
883
887
|
.data-table { break-inside: avoid; page-break-inside: avoid; }
|
|
884
888
|
header { display: none; }
|
|
885
889
|
.annotation-bar { display: none; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mviz",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.4",
|
|
4
4
|
"description": "A chart & report builder designed for use by AI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -83,6 +83,6 @@
|
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"ajv": "^8.17.1",
|
|
85
85
|
"ajv-formats": "^3.0.1",
|
|
86
|
-
"beautiful-mermaid": "^
|
|
86
|
+
"beautiful-mermaid": "^1.1.3"
|
|
87
87
|
}
|
|
88
88
|
}
|