@opendata-ai/openchart-vanilla 8.6.4 → 8.8.0
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/{chunk-RYVV3YIG.js → chunk-DFKLAB67.js} +3 -3
- package/dist/chunk-DFKLAB67.js.map +1 -0
- package/dist/{chunk-CPULCRVF.js → chunk-EZQDCLZN.js} +2 -2
- package/dist/{chunk-6B5OBGIO.js → chunk-I73B3DJI.js} +2 -2
- package/dist/chunk-I73B3DJI.js.map +1 -0
- package/dist/{chunk-W3WPGHYV.js → chunk-QBTRAQAX.js} +795 -124
- package/dist/chunk-QBTRAQAX.js.map +1 -0
- package/dist/{chunk-5RX6ZQGZ.js → chunk-SDJHUELU.js} +1 -2
- package/dist/chunk-SDJHUELU.js.map +1 -0
- package/dist/{chunk-MDK6AILK.js → chunk-SXTHPXG6.js} +2 -2
- package/dist/{chunk-MDK6AILK.js.map → chunk-SXTHPXG6.js.map} +1 -1
- package/dist/export-gif.d.ts +1 -1
- package/dist/export-gif.js +3 -3
- package/dist/index.d.ts +15 -2
- package/dist/index.js +6 -6
- package/dist/{mount-Bs8nFSf1.d.ts → mount-WiY9BIr9.d.ts} +1 -1
- package/dist/static.js +3 -3
- package/dist/story/index.d.ts +2 -2
- package/dist/story/index.js +4 -4
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-5RX6ZQGZ.js.map +0 -1
- package/dist/chunk-6B5OBGIO.js.map +0 -1
- package/dist/chunk-RYVV3YIG.js.map +0 -1
- package/dist/chunk-W3WPGHYV.js.map +0 -1
- /package/dist/{chunk-CPULCRVF.js.map → chunk-EZQDCLZN.js.map} +0 -0
|
@@ -81,7 +81,6 @@ function buildThemeStyleBlock(theme) {
|
|
|
81
81
|
`.oc-subtitle { font-size: var(--oc-subtitle-size); font-weight: var(--oc-subtitle-weight); fill: var(--oc-text-muted); }`,
|
|
82
82
|
`.oc-source, .oc-byline, .oc-footer { font-size: var(--oc-source-size); font-weight: var(--oc-source-weight); fill: var(--oc-text-muted); }`,
|
|
83
83
|
`.oc-brand { font-size: 11px; font-weight: 500; letter-spacing: 0.02em; fill: var(--oc-text-faint); }`,
|
|
84
|
-
`.oc-brand-dot { fill: var(--oc-accent); }`,
|
|
85
84
|
`.oc-eyebrow-dot { fill: var(--oc-accent); }`,
|
|
86
85
|
`.oc-metrics { font-family: var(--oc-font-family); }`,
|
|
87
86
|
`.oc-metric-label { font-size: 11px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; fill: var(--oc-text-muted); }`,
|
|
@@ -124,4 +123,4 @@ export {
|
|
|
124
123
|
buildThemeStyleBlock,
|
|
125
124
|
injectThemeStyleBlock
|
|
126
125
|
};
|
|
127
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-SDJHUELU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/renderers/svg-dom.ts","../src/theme-style-block.ts"],"sourcesContent":["/**\n * Shared SVG DOM helpers used across the per-concern renderers.\n *\n * Pure, stateless utilities. No layout/theme knowledge.\n */\n\nimport type { TextStyle } from '@opendata-ai/openchart-core';\n\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const XLINK_NS = 'http://www.w3.org/1999/xlink';\n\nexport function createSVGElement(tag: string): SVGElement {\n return document.createElementNS(SVG_NS, tag);\n}\n\nexport function setAttrs(el: SVGElement, attrs: Record<string, string | number>): void {\n for (const [key, value] of Object.entries(attrs)) {\n el.setAttribute(key, String(value));\n }\n}\n\n/**\n * Cut a knockout halo behind text so it stays legible where it crosses\n * gridlines, marks, or a neighbouring series: a surface-colored stroke painted\n * under the glyphs.\n *\n * Presentation attributes, not inline styles, so a stylesheet can still\n * override the halo. The width scales with the font size -- a fixed width rings\n * small glyphs and disappears behind large ones.\n */\nexport function applyKnockoutHalo(el: SVGElement, color: string, fontSize: number): void {\n setAttrs(el, {\n stroke: color,\n 'stroke-width': Math.round(fontSize * 0.3),\n 'stroke-linejoin': 'round',\n 'paint-order': 'stroke',\n });\n}\n\nexport function applyTextStyle(el: SVGElement, style: TextStyle): void {\n // Use inline styles so engine-computed values take priority over CSS class\n // defaults (e.g. .oc-title { font-size: var(--oc-title-size) } would otherwise\n // override the responsive scaling applied by the chrome layout).\n const inline = (el as SVGElement & ElementCSSInlineStyle).style;\n inline.setProperty('fill', style.fill);\n inline.setProperty('font-size', `${style.fontSize}px`);\n inline.setProperty('font-weight', String(style.fontWeight));\n inline.setProperty('font-family', style.fontFamily);\n if (style.textAnchor) {\n el.setAttribute('text-anchor', style.textAnchor);\n }\n if (style.dominantBaseline) {\n el.setAttribute('dominant-baseline', style.dominantBaseline);\n }\n if (style.fontVariant) {\n el.setAttribute('font-variant', style.fontVariant);\n }\n}\n","/**\n * Theme `<style>` block for self-contained SVG export.\n *\n * Charts render most fills as inline SVG attributes, but a handful of chrome\n * elements (metric cells, the eyebrow dot, legend text, endpoint labels)\n * take their fill from CSS classes in `chrome.css` via `--oc-*` variables. That\n * works on-screen because the live SVG inherits the page stylesheet — but a\n * serialized/rasterized export (PNG/JPG/GIF) is detached from the page, so those\n * class-based fills vanish. This module builds a `<style>` block that resolves\n * every such rule against a concrete `ResolvedTheme`, so injecting it into an\n * export clone makes the SVG fully self-contained.\n *\n * Both the headless renderer (`static.ts`) and the browser export path use this,\n * so class-based styling round-trips identically no matter which path produced\n * the SVG. Browser-safe (no Node imports) so the browser exporters can import it.\n */\n\nimport type { ResolvedTheme } from '@opendata-ai/openchart-core';\nimport { adaptForLightLineStroke, cssTokenDefault } from '@opendata-ai/openchart-core';\nimport { SVG_NS } from './renderers/svg-dom';\n\n/**\n * Build the theme `<style>` block CSS text for a resolved theme. Sets the\n * `--oc-*` custom properties on `svg.oc-chart` and defines every class-based\n * chrome rule against them.\n */\nexport function buildThemeStyleBlock(theme: ResolvedTheme): string {\n const accent = theme.colors.categorical[0] ?? cssTokenDefault('--oc-accent', 'light');\n const bg = theme.colors.neutral.surface;\n\n const props = [\n `--oc-font-family: ${theme.fonts.family}`,\n `--oc-font-mono: ${theme.fonts.mono}`,\n `--oc-title-size: ${theme.chrome.title.fontSize}px`,\n `--oc-title-weight: ${theme.chrome.title.fontWeight}`,\n `--oc-title-tracking: ${cssTokenDefault('--oc-title-tracking', 'light')}`,\n `--oc-subtitle-size: ${theme.chrome.subtitle.fontSize}px`,\n `--oc-subtitle-weight: ${theme.chrome.subtitle.fontWeight}`,\n `--oc-source-size: ${theme.chrome.source.fontSize}px`,\n `--oc-source-weight: ${theme.chrome.source.fontWeight}`,\n `--oc-body-size: ${theme.fonts.sizes.body}px`,\n `--oc-eyebrow-size: ${theme.chrome.eyebrow.fontSize}px`,\n `--oc-eyebrow-weight: ${theme.chrome.eyebrow.fontWeight}`,\n `--oc-eyebrow-tracking: ${cssTokenDefault('--oc-eyebrow-tracking', 'light')}`,\n `--oc-bg: ${bg}`,\n `--oc-text: ${theme.colors.text}`,\n `--oc-text-muted: ${theme.colors.axis}`,\n `--oc-text-secondary: ${theme.colors.neutral.secondary}`,\n `--oc-text-faint: ${theme.colors.neutral.faint}`,\n `--oc-border: ${theme.colors.neutral.border}`,\n `--oc-gridline: ${theme.colors.gridline}`,\n // Hairline, not the tick-label ink.\n `--oc-axis: ${theme.colors.hairline}`,\n `--oc-border-radius: ${theme.borderRadius}px`,\n `--oc-accent: ${accent}`,\n `--oc-accent-strong: ${adaptForLightLineStroke(accent)}`,\n `--oc-positive: ${theme.colors.positive}`,\n `--oc-negative: ${theme.colors.negative}`,\n `--oc-legend-text: ${theme.isDark ? cssTokenDefault('--oc-legend-text', 'dark') : cssTokenDefault('--oc-legend-text', 'light')}`,\n `--oc-space-2: ${theme.spacing.chromeGap * 2}px`,\n `--oc-space-4: ${theme.spacing.padding}px`,\n ];\n\n const rules = [\n // Tabular figures everywhere in the chart's own text: axis ticks, value\n // labels and legend entries all line up column-wise.\n `svg.oc-chart { ${props.join('; ')}; font-variant-numeric: tabular-nums; }`,\n `.oc-chrome { font-family: var(--oc-font-family); }`,\n `.oc-eyebrow { font-size: var(--oc-eyebrow-size); font-weight: var(--oc-eyebrow-weight); letter-spacing: var(--oc-eyebrow-tracking); text-transform: uppercase; fill: var(--oc-accent); }`,\n `.oc-title { font-size: var(--oc-title-size); font-weight: var(--oc-title-weight); letter-spacing: var(--oc-title-tracking); fill: var(--oc-text); }`,\n `.oc-subtitle { font-size: var(--oc-subtitle-size); font-weight: var(--oc-subtitle-weight); fill: var(--oc-text-muted); }`,\n `.oc-source, .oc-byline, .oc-footer { font-size: var(--oc-source-size); font-weight: var(--oc-source-weight); fill: var(--oc-text-muted); }`,\n `.oc-brand { font-size: 11px; font-weight: 500; letter-spacing: 0.02em; fill: var(--oc-text-faint); }`,\n `.oc-eyebrow-dot { fill: var(--oc-accent); }`,\n `.oc-metrics { font-family: var(--oc-font-family); }`,\n `.oc-metric-label { font-size: 11px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; fill: var(--oc-text-muted); }`,\n `.oc-metric-value { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; fill: var(--oc-text); font-variant-numeric: tabular-nums; }`,\n `.oc-metric-delta-up { fill: var(--oc-positive); font-size: 12px; font-weight: 500; }`,\n `.oc-metric-delta-down { fill: var(--oc-negative); font-size: 12px; font-weight: 500; }`,\n `.oc-axis-tick-inline { font-size: 11px; font-weight: 400; fill: var(--oc-text-muted); }`,\n `.oc-endpoint-labels { font-family: var(--oc-font-family); }`,\n `.oc-endpoint-label { fill: var(--oc-endpoint-label-color, var(--oc-text)); }`,\n `.oc-endpoint-value { fill: var(--oc-endpoint-value-color, var(--oc-text-muted)); }`,\n `.oc-endpoint-leader { stroke: var(--oc-endpoint-leader-color, currentColor); }`,\n `.oc-annotation-subtitle { fill: var(--oc-annotation-subtitle-color, var(--oc-text-muted)); }`,\n `.oc-metric-secondary { fill: var(--oc-text-muted); font-size: 12px; font-weight: 400; }`,\n `.oc-legend { font-family: var(--oc-font-family); font-size: var(--oc-body-size); }`,\n `.oc-legend-entry { cursor: default; }`,\n `.oc-legend text { fill: var(--oc-legend-text); }`,\n ];\n\n return rules.join('\\n');\n}\n\n/**\n * Inject the theme style block into an SVG clone's `<defs>` so class-based fills\n * survive serialization. Idempotent-ish: adds one `<style data-oc-theme>` at the\n * front of `<defs>`; call once per clone before serializing. No-op if `theme` is\n * undefined (nothing to resolve against).\n */\nexport function injectThemeStyleBlock(svg: SVGElement, theme: ResolvedTheme | undefined): void {\n if (!theme) return;\n let defs = svg.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS(SVG_NS, 'defs');\n svg.insertBefore(defs, svg.firstChild);\n }\n const style = document.createElementNS(SVG_NS, 'style');\n style.setAttribute('data-oc-theme', '');\n style.textContent = buildThemeStyleBlock(theme);\n defs.insertBefore(style, defs.firstChild);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
applyTextStyle,
|
|
6
6
|
createSVGElement,
|
|
7
7
|
setAttrs
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SDJHUELU.js";
|
|
9
9
|
import {
|
|
10
10
|
resolvedSurface
|
|
11
11
|
} from "./chunk-NG7CVCI2.js";
|
|
@@ -2071,4 +2071,4 @@ export {
|
|
|
2071
2071
|
renderSingleMark,
|
|
2072
2072
|
renderChartSVG
|
|
2073
2073
|
};
|
|
2074
|
-
//# sourceMappingURL=chunk-
|
|
2074
|
+
//# sourceMappingURL=chunk-SXTHPXG6.js.map
|