@opendata-ai/openchart-core 7.1.4 → 7.2.1

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/index.d.ts CHANGED
@@ -334,6 +334,8 @@ interface AxisConfig {
334
334
  labelPadding?: number;
335
335
  /** Color override for axis tick labels and title. Useful in dual-axis charts to match axis color to its series. */
336
336
  labelColor?: string;
337
+ /** Literal string appended to every formatted tick label. e.g. "B" gives "$4.5B" when format is "$,.1~f". */
338
+ labelSuffix?: string;
337
339
  /** Secondary data field to display alongside each tick label. Renders in lighter weight/color. Only effective on categorical y-axis labels (horizontal bar charts). */
338
340
  labelField?: string;
339
341
  /**
@@ -847,6 +849,19 @@ interface ThemeConfig {
847
849
  family?: string;
848
850
  /** Monospace font family (for tabular numbers). */
849
851
  mono?: string;
852
+ /** Font size overrides in pixels. Partial — only specified keys are overridden. */
853
+ sizes?: {
854
+ /** Chart title. Default: 26. */
855
+ title?: number;
856
+ /** Subtitle below the title. Default: 14. */
857
+ subtitle?: number;
858
+ /** Body text (tooltips, legend labels). Default: 13. */
859
+ body?: number;
860
+ /** Small text (source line, footer). Default: 11. */
861
+ small?: number;
862
+ /** Axis tick labels. Default: 11. */
863
+ axisTick?: number;
864
+ };
850
865
  };
851
866
  /** Spacing overrides in pixels. */
852
867
  spacing?: {
@@ -854,6 +869,10 @@ interface ThemeConfig {
854
869
  padding?: number;
855
870
  /** Gap between chrome elements (title to subtitle, etc.). */
856
871
  chromeGap?: number;
872
+ /** Height reserved below chart area for x-axis tick labels. Increase when large axisTick font sizes cause label clipping. */
873
+ xAxisHeight?: number;
874
+ /** Gap in pixels between the x-axis line and tick label text. Increase when larger axisTick fonts sit too close to the axis line. */
875
+ xAxisLabelPadding?: number;
857
876
  };
858
877
  /** Border radius for chart container and tooltips. */
859
878
  borderRadius?: number;
@@ -894,10 +913,14 @@ interface LabelConfig {
894
913
  format?: string;
895
914
  /** Literal string prepended to each formatted label value (e.g. "-" or "$"). */
896
915
  prefix?: string;
916
+ /** Literal string appended to each formatted label value (e.g. "%" or "x"). */
917
+ suffix?: string;
897
918
  /** Fixed CSS color for all labels. Overrides the default fill-derived color. */
898
919
  color?: string;
899
920
  /** Per-series pixel offsets for fine-tuning label positions, keyed by series name. */
900
921
  offsets?: Record<string, AnnotationOffset>;
922
+ /** Font size in pixels for bar/column value labels. */
923
+ fontSize?: number;
901
924
  }
902
925
  /** Shorthand: `false` disables all labels, `true` uses defaults, or pass a full config object. */
903
926
  type LabelSpec = boolean | LabelConfig;
@@ -2220,6 +2243,10 @@ interface ThemeSpacing {
2220
2243
  chartToFooter: number;
2221
2244
  /** Internal padding within the chart area (axes margins). */
2222
2245
  axisMargin: number;
2246
+ /** Height reserved below the chart area for x-axis tick labels (and optional axis title). */
2247
+ xAxisHeight: number;
2248
+ /** Gap in pixels between the x-axis line and the top of non-rotated tick label text. */
2249
+ xAxisLabelPadding: number;
2223
2250
  }
2224
2251
  /** Default style configuration for a chrome text element. */
2225
2252
  interface ChromeDefaults {
@@ -3653,8 +3680,11 @@ declare function findAccessibleColor(baseColor: string, bg: string, targetRatio?
3653
3680
  * -> sRGB pipeline. Documented OKLCH source values are the contract; if
3654
3681
  * the conversion math changes, regenerate from the source rather than
3655
3682
  * editing hex literals directly.
3683
+ *
3684
+ * Tuned at L≈0.65, C≈0.20 (vs prior L≈0.70, C≈0.15) for more vivid,
3685
+ * saturated color on dark backgrounds where the lighter pastels read soft.
3656
3686
  */
3657
- declare const CATEGORICAL_PALETTE: readonly ["#06b6d4", "#eb7289", "#3bb974", "#ad87ed", "#e69c3a", "#4ba3f7", "#eb8656", "#8494fa", "#00b9c3"];
3687
+ declare const CATEGORICAL_PALETTE: readonly ["#06b6d4", "#ee4a73", "#00b054", "#a46bf5", "#e07d00", "#0091ff", "#f36000", "#6f7dff", "#00afbf"];
3658
3688
  type CategoricalPalette = typeof CATEGORICAL_PALETTE;
3659
3689
  /** Sequential palette definition: an array of color stops from light to dark. */
3660
3690
  interface SequentialPalette {
package/dist/index.js CHANGED
@@ -726,22 +726,22 @@ var ACHROMATIC_RAMP = {
726
726
  var CATEGORICAL_PALETTE = [
727
727
  "#06b6d4",
728
728
  // cyan, primary accent (sRGB literal, ~205°)
729
- "#eb7289",
730
- // rose — oklch(70% 0.15 10)
731
- "#3bb974",
732
- // emerald — oklch(70% 0.15 155)
733
- "#ad87ed",
734
- // violet — oklch(70% 0.15 300)
735
- "#e69c3a",
736
- // amber — oklch(75% 0.14 70)
737
- "#4ba3f7",
738
- // sky — oklch(70% 0.15 250)
739
- "#eb8656",
740
- // orange — oklch(72% 0.14 45)
741
- "#8494fa",
742
- // indigo — oklch(70% 0.15 275)
743
- "#00b9c3"
744
- // teal — oklch(70% 0.15 200)
729
+ "#ee4a73",
730
+ // rose — oklch(65% 0.20 10)
731
+ "#00b054",
732
+ // emerald — oklch(65% 0.20 155)
733
+ "#a46bf5",
734
+ // violet — oklch(65% 0.20 300)
735
+ "#e07d00",
736
+ // amber — oklch(68% 0.19 70)
737
+ "#0091ff",
738
+ // sky — oklch(65% 0.20 250)
739
+ "#f36000",
740
+ // orange — oklch(67% 0.20 45)
741
+ "#6f7dff",
742
+ // indigo — oklch(65% 0.20 275)
743
+ "#00afbf"
744
+ // teal — oklch(65% 0.20 200)
745
745
  ];
746
746
  var SEQUENTIAL_BLUE = {
747
747
  name: "blue",
@@ -853,7 +853,9 @@ var DEFAULT_THEME = {
853
853
  chromeGap: 4,
854
854
  chromeToChart: 8,
855
855
  chartToFooter: 8,
856
- axisMargin: 6
856
+ axisMargin: 6,
857
+ xAxisHeight: 26,
858
+ xAxisLabelPadding: 14
857
859
  },
858
860
  borderRadius: 2,
859
861
  chrome: {
@@ -1048,12 +1050,16 @@ function themeConfigToPartial(config) {
1048
1050
  const fonts = {};
1049
1051
  if (config.fonts.family) fonts.family = config.fonts.family;
1050
1052
  if (config.fonts.mono) fonts.mono = config.fonts.mono;
1053
+ if (config.fonts.sizes) fonts.sizes = config.fonts.sizes;
1051
1054
  partial.fonts = fonts;
1052
1055
  }
1053
1056
  if (config.spacing) {
1054
1057
  const spacing = {};
1055
1058
  if (config.spacing.padding !== void 0) spacing.padding = config.spacing.padding;
1056
1059
  if (config.spacing.chromeGap !== void 0) spacing.chromeGap = config.spacing.chromeGap;
1060
+ if (config.spacing.xAxisHeight !== void 0) spacing.xAxisHeight = config.spacing.xAxisHeight;
1061
+ if (config.spacing.xAxisLabelPadding !== void 0)
1062
+ spacing.xAxisLabelPadding = config.spacing.xAxisLabelPadding;
1057
1063
  partial.spacing = spacing;
1058
1064
  }
1059
1065
  if (config.borderRadius !== void 0) {
@@ -1123,6 +1129,26 @@ function adjustOpacity(hex2, opacity) {
1123
1129
  }
1124
1130
  function resolveTheme(userTheme, base = DEFAULT_THEME) {
1125
1131
  let merged = userTheme ? deepMerge(base, themeConfigToPartial(userTheme)) : { ...base };
1132
+ if (userTheme?.fonts?.sizes) {
1133
+ const s = userTheme.fonts.sizes;
1134
+ merged = {
1135
+ ...merged,
1136
+ chrome: {
1137
+ ...merged.chrome,
1138
+ ...s.title !== void 0 && {
1139
+ title: { ...merged.chrome.title, fontSize: s.title }
1140
+ },
1141
+ ...s.subtitle !== void 0 && {
1142
+ subtitle: { ...merged.chrome.subtitle, fontSize: s.subtitle }
1143
+ },
1144
+ ...s.small !== void 0 && {
1145
+ source: { ...merged.chrome.source, fontSize: s.small },
1146
+ byline: { ...merged.chrome.byline, fontSize: s.small },
1147
+ footer: { ...merged.chrome.footer, fontSize: s.small }
1148
+ }
1149
+ }
1150
+ };
1151
+ }
1126
1152
  const dark = isDarkBackground(merged.colors.background);
1127
1153
  if (dark) {
1128
1154
  merged = adaptChromeForDarkBg(merged, merged.colors.text);