@yuneta/gobj-ui 7.26.39 → 7.26.40

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/README.md CHANGED
@@ -3394,6 +3394,22 @@ the middle, and **a toolbar left with a single group is centred**. An unknown
3394
3394
  name is reported, not silently dropped: a typo would otherwise remove the save
3395
3395
  button with no trace of why.
3396
3396
 
3397
+ ### Charts — the ink of the axes, on both schemes
3398
+
3399
+ uPlot is built for a white page: its axis labels are black, its grid 7% black.
3400
+ `C_YUI_UPLOT` gives its axes the ink of the theme -- both of them: uPlot always
3401
+ draws an X and a Y axis, and until 7.26.40 the Y axis kept uPlot's black, which
3402
+ no one could read on the dark scheme. A uPlot built by the app itself takes the
3403
+ same axes from `yui_uplot_axes()`, and redraws on a change of the theme
3404
+ (`yui_watch_theme(gobj)` sends `EV_THEME`; its action calls `chart.redraw()`):
3405
+
3406
+ ```js
3407
+ import {yui_uplot_axes} from "@yuneta/gobj-ui/src/yui_uplot_ink.js";
3408
+
3409
+ new uPlot({width: 600, height: 300, series: [{}, {label: "temperature"}],
3410
+ axes: yui_uplot_axes([{}])}, data, $el);
3411
+ ```
3412
+
3397
3413
  ### `C_YUI_FORM` — what closing it asks about
3398
3414
 
3399
3415
  `changes` says the form is not what is stored: the reader changed it, or the
@@ -13396,41 +13396,58 @@ function register_c_yui_map() {
13396
13396
  return create_gclass$16(GCLASS_NAME$16);
13397
13397
  }
13398
13398
  //#endregion
13399
- //#region src/c_yui_uplot.js
13399
+ //#region src/yui_uplot_ink.js
13400
13400
  /***********************************************************************
13401
- * c_yui_uplot.js
13401
+ * yui_uplot_ink.js
13402
13402
  *
13403
- * Graphics, Charts with uPlot
13403
+ * The ink of a uPlot chart, on both schemes, and its palette.
13404
13404
  *
13405
- * Copyright (c) 2025-2026, ArtGins.
13405
+ * uPlot is built for a white page: its axis labels are `#000`
13406
+ * and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
13407
+ * 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
13408
+ * not there. The inks here are handed to uPlot as FUNCTIONS: it
13409
+ * calls them when it draws, so the value can never be stale --
13410
+ * what goes stale is the canvas, and a change of the theme has to
13411
+ * ask for a redraw (yui_watch_theme() turns it into an event).
13412
+ *
13413
+ * uPlot ALWAYS draws a Y axis: its setDefaults() makes axes[1]
13414
+ * whether it was given or not, with its own black. So the axes are
13415
+ * padded to two before they are inked. C_YUI_UPLOT's default is
13416
+ * `[{}]`, the X axis alone, and until 7.26.40 every chart of the
13417
+ * library had a Y axis whose values could not be read in the dark.
13418
+ *
13419
+ * C_YUI_UPLOT uses it, and so can an app that builds a uPlot of its
13420
+ * own:
13421
+ *
13422
+ * import {yui_uplot_axes} from "@yuneta/gobj-ui/src/yui_uplot_ink.js";
13423
+ *
13424
+ * const chart = new uPlot({
13425
+ * width: 600, height: 300,
13426
+ * series: [{}, {label: "temperature"}],
13427
+ * axes: yui_uplot_axes([{}]), // X and Y, with the ink of the theme
13428
+ * }, data, $el);
13429
+ *
13430
+ * The palette is six colours that clear 3:1 on BOTH grounds
13431
+ * (worst 3.39 on white, 3.71 on near-black), ordered so the first
13432
+ * two are the pair that survives colour blindness -- blue and
13433
+ * orange, never red and green as the opening pair.
13434
+ *
13435
+ * Copyright (c) 2026, ArtGins.
13406
13436
  * All Rights Reserved.
13407
13437
  ***********************************************************************/
13408
- /***************************************************************
13409
- * The ink of a chart, and its palette.
13410
- *
13411
- * uPlot is built for a white page: its axis labels are `#000`
13412
- * and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
13413
- * 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
13414
- * not there. And the series were CSS colour names: `blue` is
13415
- * 2.11:1 on the dark ground, `orange` 1.97 on the light one, so
13416
- * whichever scheme you were in, one of the lines was a rumour.
13417
- *
13418
- * These are given to uPlot as FUNCTIONS: it calls them when it
13419
- * draws, so the value can never be stale -- what goes stale is
13420
- * the canvas, and that is what EV_THEME redraws.
13421
- *
13422
- * The palette is six colours that clear 3:1 on BOTH grounds
13423
- * (worst 3.39 on white, 3.71 on near-black), ordered so the
13424
- * first two are the pair that survives colour blindness -- blue
13425
- * and orange, never red and green as the opening pair.
13426
- ***************************************************************/
13427
- function axis_ink() {
13438
+ /************************************************************
13439
+ * The ink of the labels of an axis.
13440
+ ************************************************************/
13441
+ function yui_uplot_axis_ink() {
13428
13442
  return yui_is_dark() ? "#c7cdd8" : "#2e333d";
13429
13443
  }
13430
- function grid_ink() {
13444
+ /************************************************************
13445
+ * The ink of the grid and of the ticks.
13446
+ ************************************************************/
13447
+ function yui_uplot_grid_ink() {
13431
13448
  return yui_is_dark() ? "rgba(199,205,216,0.16)" : "rgba(46,51,61,0.12)";
13432
13449
  }
13433
- var CHART_PALETTE = [
13450
+ var YUI_UPLOT_PALETTE = [
13434
13451
  {
13435
13452
  stroke: "#2f6fd0",
13436
13453
  fill: "rgba(47,111,208,0.10)"
@@ -13456,15 +13473,33 @@ var CHART_PALETTE = [
13456
13473
  fill: "rgba(209,52,75,0.10)"
13457
13474
  }
13458
13475
  ];
13459
- function themed_axes(axes) {
13460
- return (Array.isArray(axes) ? axes : [axes || {}]).map((ax) => {
13476
+ /************************************************************
13477
+ * The axes the host asked for -- at least the X and the Y,
13478
+ * the two uPlot always draws -- with the ink it did not ask
13479
+ * about. A stroke, a grid or a ticks the host gave is kept.
13480
+ * Answers new objects: the host's are not touched.
13481
+ ************************************************************/
13482
+ function yui_uplot_axes(axes) {
13483
+ let list = Array.isArray(axes) ? axes.slice() : [axes || {}];
13484
+ while (list.length < 2) list.push({});
13485
+ return list.map((ax) => {
13461
13486
  let a = Object.assign({}, ax || {});
13462
- if (a.stroke === void 0) a.stroke = axis_ink;
13463
- a.grid = Object.assign({ stroke: grid_ink }, a.grid || {});
13464
- a.ticks = Object.assign({ stroke: grid_ink }, a.ticks || {});
13487
+ if (a.stroke === void 0) a.stroke = yui_uplot_axis_ink;
13488
+ a.grid = Object.assign({ stroke: yui_uplot_grid_ink }, a.grid || {});
13489
+ a.ticks = Object.assign({ stroke: yui_uplot_grid_ink }, a.ticks || {});
13465
13490
  return a;
13466
13491
  });
13467
13492
  }
13493
+ //#endregion
13494
+ //#region src/c_yui_uplot.js
13495
+ /***********************************************************************
13496
+ * c_yui_uplot.js
13497
+ *
13498
+ * Graphics, Charts with uPlot
13499
+ *
13500
+ * Copyright (c) 2025-2026, ArtGins.
13501
+ * All Rights Reserved.
13502
+ ***********************************************************************/
13468
13503
  /***************************************************************
13469
13504
  * Constants
13470
13505
  ***************************************************************/
@@ -13482,7 +13517,7 @@ var attrs_table$15 = [
13482
13517
  (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "axes", 0, [{}], "Chart axes"),
13483
13518
  (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "scales", 0, {}, "Chart scales"),
13484
13519
  (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "data", 0, [[]], "Chart data"),
13485
- (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "colors", 0, CHART_PALETTE, "Series colours, in order. The default palette clears 3:1 on both schemes and opens with the colour-blind-safe pair (blue, orange)"),
13520
+ (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "colors", 0, YUI_UPLOT_PALETTE, "Series colours, in order. The default palette clears 3:1 on both schemes and opens with the colour-blind-safe pair (blue, orange)"),
13486
13521
  (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$container", 0, null, "HTML container for the chart"),
13487
13522
  (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "own_container", 0, false, "If true, container is gobj-managed"),
13488
13523
  (0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "uplot", 0, null, "uPlot instance"),
@@ -13549,7 +13584,7 @@ function build_ui$14(gobj) {
13549
13584
  width: (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "width"),
13550
13585
  height: (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "height"),
13551
13586
  series: (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "series"),
13552
- axes: themed_axes((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "axes")),
13587
+ axes: yui_uplot_axes((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "axes")),
13553
13588
  scales: (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "scales")
13554
13589
  };
13555
13590
  let uplot$2 = new uplot.default(uPlot_options, (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "data"), $container);
@@ -13650,7 +13685,7 @@ function ac_add_serie(gobj, event, kw, src) {
13650
13685
  }
13651
13686
  }
13652
13687
  let colors = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "colors");
13653
- if (!Array.isArray(colors) || !colors.length) colors = CHART_PALETTE;
13688
+ if (!Array.isArray(colors) || !colors.length) colors = YUI_UPLOT_PALETTE;
13654
13689
  let color = colors[Math.max(0, idx - 1) % colors.length];
13655
13690
  if (kw.stroke === void 0) kw.stroke = color.stroke;
13656
13691
  if (kw.fill === void 0) kw.fill = color.fill;
@@ -13391,41 +13391,58 @@ function register_c_yui_map() {
13391
13391
  return create_gclass$16(GCLASS_NAME$16);
13392
13392
  }
13393
13393
  //#endregion
13394
- //#region src/c_yui_uplot.js
13394
+ //#region src/yui_uplot_ink.js
13395
13395
  /***********************************************************************
13396
- * c_yui_uplot.js
13396
+ * yui_uplot_ink.js
13397
13397
  *
13398
- * Graphics, Charts with uPlot
13398
+ * The ink of a uPlot chart, on both schemes, and its palette.
13399
13399
  *
13400
- * Copyright (c) 2025-2026, ArtGins.
13400
+ * uPlot is built for a white page: its axis labels are `#000`
13401
+ * and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
13402
+ * 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
13403
+ * not there. The inks here are handed to uPlot as FUNCTIONS: it
13404
+ * calls them when it draws, so the value can never be stale --
13405
+ * what goes stale is the canvas, and a change of the theme has to
13406
+ * ask for a redraw (yui_watch_theme() turns it into an event).
13407
+ *
13408
+ * uPlot ALWAYS draws a Y axis: its setDefaults() makes axes[1]
13409
+ * whether it was given or not, with its own black. So the axes are
13410
+ * padded to two before they are inked. C_YUI_UPLOT's default is
13411
+ * `[{}]`, the X axis alone, and until 7.26.40 every chart of the
13412
+ * library had a Y axis whose values could not be read in the dark.
13413
+ *
13414
+ * C_YUI_UPLOT uses it, and so can an app that builds a uPlot of its
13415
+ * own:
13416
+ *
13417
+ * import {yui_uplot_axes} from "@yuneta/gobj-ui/src/yui_uplot_ink.js";
13418
+ *
13419
+ * const chart = new uPlot({
13420
+ * width: 600, height: 300,
13421
+ * series: [{}, {label: "temperature"}],
13422
+ * axes: yui_uplot_axes([{}]), // X and Y, with the ink of the theme
13423
+ * }, data, $el);
13424
+ *
13425
+ * The palette is six colours that clear 3:1 on BOTH grounds
13426
+ * (worst 3.39 on white, 3.71 on near-black), ordered so the first
13427
+ * two are the pair that survives colour blindness -- blue and
13428
+ * orange, never red and green as the opening pair.
13429
+ *
13430
+ * Copyright (c) 2026, ArtGins.
13401
13431
  * All Rights Reserved.
13402
13432
  ***********************************************************************/
13403
- /***************************************************************
13404
- * The ink of a chart, and its palette.
13405
- *
13406
- * uPlot is built for a white page: its axis labels are `#000`
13407
- * and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
13408
- * 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
13409
- * not there. And the series were CSS colour names: `blue` is
13410
- * 2.11:1 on the dark ground, `orange` 1.97 on the light one, so
13411
- * whichever scheme you were in, one of the lines was a rumour.
13412
- *
13413
- * These are given to uPlot as FUNCTIONS: it calls them when it
13414
- * draws, so the value can never be stale -- what goes stale is
13415
- * the canvas, and that is what EV_THEME redraws.
13416
- *
13417
- * The palette is six colours that clear 3:1 on BOTH grounds
13418
- * (worst 3.39 on white, 3.71 on near-black), ordered so the
13419
- * first two are the pair that survives colour blindness -- blue
13420
- * and orange, never red and green as the opening pair.
13421
- ***************************************************************/
13422
- function axis_ink() {
13433
+ /************************************************************
13434
+ * The ink of the labels of an axis.
13435
+ ************************************************************/
13436
+ function yui_uplot_axis_ink() {
13423
13437
  return yui_is_dark() ? "#c7cdd8" : "#2e333d";
13424
13438
  }
13425
- function grid_ink() {
13439
+ /************************************************************
13440
+ * The ink of the grid and of the ticks.
13441
+ ************************************************************/
13442
+ function yui_uplot_grid_ink() {
13426
13443
  return yui_is_dark() ? "rgba(199,205,216,0.16)" : "rgba(46,51,61,0.12)";
13427
13444
  }
13428
- var CHART_PALETTE = [
13445
+ var YUI_UPLOT_PALETTE = [
13429
13446
  {
13430
13447
  stroke: "#2f6fd0",
13431
13448
  fill: "rgba(47,111,208,0.10)"
@@ -13451,15 +13468,33 @@ var CHART_PALETTE = [
13451
13468
  fill: "rgba(209,52,75,0.10)"
13452
13469
  }
13453
13470
  ];
13454
- function themed_axes(axes) {
13455
- return (Array.isArray(axes) ? axes : [axes || {}]).map((ax) => {
13471
+ /************************************************************
13472
+ * The axes the host asked for -- at least the X and the Y,
13473
+ * the two uPlot always draws -- with the ink it did not ask
13474
+ * about. A stroke, a grid or a ticks the host gave is kept.
13475
+ * Answers new objects: the host's are not touched.
13476
+ ************************************************************/
13477
+ function yui_uplot_axes(axes) {
13478
+ let list = Array.isArray(axes) ? axes.slice() : [axes || {}];
13479
+ while (list.length < 2) list.push({});
13480
+ return list.map((ax) => {
13456
13481
  let a = Object.assign({}, ax || {});
13457
- if (a.stroke === void 0) a.stroke = axis_ink;
13458
- a.grid = Object.assign({ stroke: grid_ink }, a.grid || {});
13459
- a.ticks = Object.assign({ stroke: grid_ink }, a.ticks || {});
13482
+ if (a.stroke === void 0) a.stroke = yui_uplot_axis_ink;
13483
+ a.grid = Object.assign({ stroke: yui_uplot_grid_ink }, a.grid || {});
13484
+ a.ticks = Object.assign({ stroke: yui_uplot_grid_ink }, a.ticks || {});
13460
13485
  return a;
13461
13486
  });
13462
13487
  }
13488
+ //#endregion
13489
+ //#region src/c_yui_uplot.js
13490
+ /***********************************************************************
13491
+ * c_yui_uplot.js
13492
+ *
13493
+ * Graphics, Charts with uPlot
13494
+ *
13495
+ * Copyright (c) 2025-2026, ArtGins.
13496
+ * All Rights Reserved.
13497
+ ***********************************************************************/
13463
13498
  /***************************************************************
13464
13499
  * Constants
13465
13500
  ***************************************************************/
@@ -13477,7 +13512,7 @@ var attrs_table$15 = [
13477
13512
  SDATA(data_type_t.DTP_JSON, "axes", 0, [{}], "Chart axes"),
13478
13513
  SDATA(data_type_t.DTP_JSON, "scales", 0, {}, "Chart scales"),
13479
13514
  SDATA(data_type_t.DTP_JSON, "data", 0, [[]], "Chart data"),
13480
- SDATA(data_type_t.DTP_JSON, "colors", 0, CHART_PALETTE, "Series colours, in order. The default palette clears 3:1 on both schemes and opens with the colour-blind-safe pair (blue, orange)"),
13515
+ SDATA(data_type_t.DTP_JSON, "colors", 0, YUI_UPLOT_PALETTE, "Series colours, in order. The default palette clears 3:1 on both schemes and opens with the colour-blind-safe pair (blue, orange)"),
13481
13516
  SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "HTML container for the chart"),
13482
13517
  SDATA(data_type_t.DTP_BOOLEAN, "own_container", 0, false, "If true, container is gobj-managed"),
13483
13518
  SDATA(data_type_t.DTP_POINTER, "uplot", 0, null, "uPlot instance"),
@@ -13544,7 +13579,7 @@ function build_ui$14(gobj) {
13544
13579
  width: gobj_read_attr(gobj, "width"),
13545
13580
  height: gobj_read_attr(gobj, "height"),
13546
13581
  series: gobj_read_attr(gobj, "series"),
13547
- axes: themed_axes(gobj_read_attr(gobj, "axes")),
13582
+ axes: yui_uplot_axes(gobj_read_attr(gobj, "axes")),
13548
13583
  scales: gobj_read_attr(gobj, "scales")
13549
13584
  };
13550
13585
  let uplot = new uPlot(uPlot_options, gobj_read_attr(gobj, "data"), $container);
@@ -13645,7 +13680,7 @@ function ac_add_serie(gobj, event, kw, src) {
13645
13680
  }
13646
13681
  }
13647
13682
  let colors = gobj_read_attr(gobj, "colors");
13648
- if (!Array.isArray(colors) || !colors.length) colors = CHART_PALETTE;
13683
+ if (!Array.isArray(colors) || !colors.length) colors = YUI_UPLOT_PALETTE;
13649
13684
  let color = colors[Math.max(0, idx - 1) % colors.length];
13650
13685
  if (kw.stroke === void 0) kw.stroke = color.stroke;
13651
13686
  if (kw.fill === void 0) kw.fill = color.fill;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.26.39",
3
+ "version": "7.26.40",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -30,62 +30,12 @@ import {
30
30
  import uPlot from "uplot";
31
31
  import "uplot/dist/uPlot.min.css";
32
32
 
33
- import {yui_is_dark, yui_watch_theme} from "./yui_theme.js";
33
+ import {yui_watch_theme} from "./yui_theme.js";
34
+ /* The ink of the axes -- the X and the Y -- and the palette of the
35
+ * series, on both schemes: see yui_uplot_ink.js. */
36
+ import {yui_uplot_axes, YUI_UPLOT_PALETTE} from "./yui_uplot_ink.js";
34
37
 
35
38
 
36
- /***************************************************************
37
- * The ink of a chart, and its palette.
38
- *
39
- * uPlot is built for a white page: its axis labels are `#000`
40
- * and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
41
- * 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
42
- * not there. And the series were CSS colour names: `blue` is
43
- * 2.11:1 on the dark ground, `orange` 1.97 on the light one, so
44
- * whichever scheme you were in, one of the lines was a rumour.
45
- *
46
- * These are given to uPlot as FUNCTIONS: it calls them when it
47
- * draws, so the value can never be stale -- what goes stale is
48
- * the canvas, and that is what EV_THEME redraws.
49
- *
50
- * The palette is six colours that clear 3:1 on BOTH grounds
51
- * (worst 3.39 on white, 3.71 on near-black), ordered so the
52
- * first two are the pair that survives colour blindness -- blue
53
- * and orange, never red and green as the opening pair.
54
- ***************************************************************/
55
- function axis_ink()
56
- {
57
- return yui_is_dark()? "#c7cdd8" : "#2e333d";
58
- }
59
-
60
- function grid_ink()
61
- {
62
- return yui_is_dark()? "rgba(199,205,216,0.16)" : "rgba(46,51,61,0.12)";
63
- }
64
-
65
- const CHART_PALETTE = [
66
- {stroke: "#2f6fd0", fill: "rgba(47,111,208,0.10)"}, /* 4.88 / 3.71 */
67
- {stroke: "#b8620a", fill: "rgba(184,98,10,0.10)"}, /* 4.38 / 4.13 */
68
- {stroke: "#2f8f4e", fill: "rgba(47,143,78,0.10)"}, /* 4.07 / 4.45 */
69
- {stroke: "#8b5cf6", fill: "rgba(139,92,246,0.10)"}, /* 4.23 / 4.28 */
70
- {stroke: "#0e9aa7", fill: "rgba(14,154,167,0.10)"}, /* 3.39 / 5.35 */
71
- {stroke: "#d1344b", fill: "rgba(209,52,75,0.10)"}, /* 4.88 / 3.71 */
72
- ];
73
-
74
- /* The axes the host asked for, with the ink it did not ask about. */
75
- function themed_axes(axes)
76
- {
77
- let list = Array.isArray(axes)? axes : [axes || {}];
78
- return list.map((ax) => {
79
- let a = Object.assign({}, ax || {});
80
- if(a.stroke === undefined) {
81
- a.stroke = axis_ink;
82
- }
83
- a.grid = Object.assign({stroke: grid_ink}, a.grid || {});
84
- a.ticks = Object.assign({stroke: grid_ink}, a.ticks || {});
85
- return a;
86
- });
87
- }
88
-
89
39
  /***************************************************************
90
40
  * Constants
91
41
  ***************************************************************/
@@ -104,7 +54,7 @@ SDATA(data_type_t.DTP_JSON, "series", 0, [{}], "Data series"),
104
54
  SDATA(data_type_t.DTP_JSON, "axes", 0, [{}], "Chart axes"),
105
55
  SDATA(data_type_t.DTP_JSON, "scales", 0, {}, "Chart scales"),
106
56
  SDATA(data_type_t.DTP_JSON, "data", 0, [[]], "Chart data"),
107
- SDATA(data_type_t.DTP_JSON, "colors", 0, CHART_PALETTE,
57
+ SDATA(data_type_t.DTP_JSON, "colors", 0, YUI_UPLOT_PALETTE,
108
58
  "Series colours, in order. The default palette clears 3:1 on both schemes and opens with the colour-blind-safe pair (blue, orange)"),
109
59
  SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "HTML container for the chart"),
110
60
  SDATA(data_type_t.DTP_BOOLEAN, "own_container", 0, false, "If true, container is gobj-managed"),
@@ -138,7 +88,7 @@ function mt_create(gobj)
138
88
  build_ui(gobj);
139
89
 
140
90
  /* A canvas does not restyle itself: the ink is read when uPlot
141
- * DRAWS (see axis_ink), so a theme change only has to reach the
91
+ * DRAWS (yui_uplot_ink.js), so a theme change only has to reach the
142
92
  * machine and ask for a redraw. Same wiring as the graphs. */
143
93
  gobj.priv.theme_observer = yui_watch_theme(gobj);
144
94
 
@@ -220,7 +170,7 @@ function build_ui(gobj)
220
170
  width: gobj_read_attr(gobj, "width"),
221
171
  height: gobj_read_attr(gobj, "height"),
222
172
  series: gobj_read_attr(gobj, "series"),
223
- axes: themed_axes(gobj_read_attr(gobj, "axes")),
173
+ axes: yui_uplot_axes(gobj_read_attr(gobj, "axes")),
224
174
  scales: gobj_read_attr(gobj, "scales"),
225
175
  };
226
176
  let uplot = new uPlot(
@@ -444,7 +394,7 @@ function ac_add_serie(gobj, event, kw, src)
444
394
  }
445
395
  let colors = gobj_read_attr(gobj, "colors");
446
396
  if(!Array.isArray(colors) || !colors.length) {
447
- colors = CHART_PALETTE;
397
+ colors = YUI_UPLOT_PALETTE;
448
398
  }
449
399
  /* `idx` counts uPlot's series, and series[0] is the X AXIS -- so
450
400
  * the first line drawn was taking colours[1] and the palette's
@@ -0,0 +1,105 @@
1
+ /***********************************************************************
2
+ * uplot_ink.test.js
3
+ *
4
+ * The axes of a chart carry the ink of the theme -- the Y axis
5
+ * too. uPlot always draws one (its setDefaults() makes axes[1]
6
+ * whether it was given or not, with its own black), and
7
+ * C_YUI_UPLOT inked only the axes it was handed: by default one,
8
+ * the X. In the dark scheme the values of every Y axis of the
9
+ * library were black on near-black (a user's report, the cards of
10
+ * estadodelaire).
11
+ *
12
+ * Copyright (c) 2026, ArtGins.
13
+ * All Rights Reserved.
14
+ ***********************************************************************/
15
+ import {describe, test, expect, beforeAll, beforeEach, afterEach, vi} from "vitest";
16
+ import {install_dom_double} from "../test/dom_double.js";
17
+
18
+ install_dom_double();
19
+
20
+ /* What C_YUI_UPLOT hands to uPlot, kept by the stand-in. */
21
+ let given = null;
22
+ vi.mock("uplot", () => ({
23
+ default: class {
24
+ constructor(opts) {
25
+ given = opts;
26
+ this.series = [{}];
27
+ }
28
+ setSize() {}
29
+ addSeries() {}
30
+ redraw() {}
31
+ destroy() {}
32
+ }
33
+ }));
34
+
35
+ const {
36
+ gobj_start_up, gobj_create_yuno, gobj_create_pure_child, gclass_create,
37
+ set_log_callback, SDATA_END,
38
+ } = await import("@yuneta/gobj-js");
39
+ const {register_c_yui_uplot} = await import("./c_yui_uplot.js");
40
+ const {
41
+ yui_uplot_axes, yui_uplot_axis_ink, yui_uplot_grid_ink,
42
+ } = await import("./yui_uplot_ink.js");
43
+
44
+ const logged = [];
45
+ let yuno = null;
46
+
47
+ beforeAll(() => {
48
+ gobj_start_up(null, null, null, null, null, null, null);
49
+ set_log_callback((level, msg) => {
50
+ logged.push({level: String(level), msg: String(msg)});
51
+ });
52
+ gclass_create("C_TEST_INK_HOST", [], [["ST_IDLE", []]], {}, 0, [SDATA_END()], {}, 0, 0, 0, 0);
53
+ register_c_yui_uplot();
54
+ yuno = gobj_create_yuno("ink_yuno", "C_TEST_INK_HOST", {});
55
+ });
56
+
57
+ beforeEach(() => {
58
+ logged.length = 0;
59
+ given = null;
60
+ });
61
+
62
+ afterEach(() => {
63
+ document.documentElement.removeAttribute("data-theme");
64
+ });
65
+
66
+ describe("yui_uplot_axes()", () => {
67
+ test("gives the X and the Y axes, the two uPlot draws", () => {
68
+ expect(yui_uplot_axes([{}]).length).toBe(2);
69
+ expect(yui_uplot_axes(undefined).length).toBe(2);
70
+ expect(yui_uplot_axes([]).length).toBe(2);
71
+ expect(yui_uplot_axes([{}, {}, {scale: "%"}]).length).toBe(3);
72
+ });
73
+
74
+ test("inks each one with the theme, read when uPlot draws", () => {
75
+ const axes = yui_uplot_axes([{}]);
76
+ for(const a of axes) {
77
+ expect(a.stroke).toBe(yui_uplot_axis_ink);
78
+ expect(a.grid.stroke).toBe(yui_uplot_grid_ink);
79
+ expect(a.ticks.stroke).toBe(yui_uplot_grid_ink);
80
+ }
81
+ document.documentElement.setAttribute("data-theme", "light");
82
+ expect(axes[1].stroke()).toBe("#2e333d");
83
+ document.documentElement.setAttribute("data-theme", "dark");
84
+ expect(axes[1].stroke()).toBe("#c7cdd8");
85
+ });
86
+
87
+ test("keeps what the host gave, and does not touch its objects", () => {
88
+ const mine = [{stroke: "red", grid: {show: false}}];
89
+ const axes = yui_uplot_axes(mine);
90
+ expect(axes[0].stroke).toBe("red");
91
+ expect(axes[0].grid).toEqual({stroke: yui_uplot_grid_ink, show: false});
92
+ expect(mine).toEqual([{stroke: "red", grid: {show: false}}]);
93
+ });
94
+ });
95
+
96
+ describe("C_YUI_UPLOT", () => {
97
+ test("hands uPlot a Y axis with the ink of the theme", () => {
98
+ gobj_create_pure_child("ink_chart", "C_YUI_UPLOT", {}, yuno);
99
+ expect(given).toBeTruthy();
100
+ expect(given.axes.length).toBe(2);
101
+ expect(given.axes[1].stroke).toBe(yui_uplot_axis_ink);
102
+ expect(given.axes[1].grid.stroke).toBe(yui_uplot_grid_ink);
103
+ expect(logged.filter((l) => /error/i.test(l.level))).toEqual([]);
104
+ });
105
+ });
@@ -0,0 +1,94 @@
1
+ /***********************************************************************
2
+ * yui_uplot_ink.js
3
+ *
4
+ * The ink of a uPlot chart, on both schemes, and its palette.
5
+ *
6
+ * uPlot is built for a white page: its axis labels are `#000`
7
+ * and its grid `rgba(0,0,0,0.07)`, which on the dark scheme are
8
+ * 1.16:1 and 1.04 -- an axis nobody can read and a grid that is
9
+ * not there. The inks here are handed to uPlot as FUNCTIONS: it
10
+ * calls them when it draws, so the value can never be stale --
11
+ * what goes stale is the canvas, and a change of the theme has to
12
+ * ask for a redraw (yui_watch_theme() turns it into an event).
13
+ *
14
+ * uPlot ALWAYS draws a Y axis: its setDefaults() makes axes[1]
15
+ * whether it was given or not, with its own black. So the axes are
16
+ * padded to two before they are inked. C_YUI_UPLOT's default is
17
+ * `[{}]`, the X axis alone, and until 7.26.40 every chart of the
18
+ * library had a Y axis whose values could not be read in the dark.
19
+ *
20
+ * C_YUI_UPLOT uses it, and so can an app that builds a uPlot of its
21
+ * own:
22
+ *
23
+ * import {yui_uplot_axes} from "@yuneta/gobj-ui/src/yui_uplot_ink.js";
24
+ *
25
+ * const chart = new uPlot({
26
+ * width: 600, height: 300,
27
+ * series: [{}, {label: "temperature"}],
28
+ * axes: yui_uplot_axes([{}]), // X and Y, with the ink of the theme
29
+ * }, data, $el);
30
+ *
31
+ * The palette is six colours that clear 3:1 on BOTH grounds
32
+ * (worst 3.39 on white, 3.71 on near-black), ordered so the first
33
+ * two are the pair that survives colour blindness -- blue and
34
+ * orange, never red and green as the opening pair.
35
+ *
36
+ * Copyright (c) 2026, ArtGins.
37
+ * All Rights Reserved.
38
+ ***********************************************************************/
39
+ import {yui_is_dark} from "./yui_theme.js";
40
+
41
+ /************************************************************
42
+ * The ink of the labels of an axis.
43
+ ************************************************************/
44
+ function yui_uplot_axis_ink()
45
+ {
46
+ return yui_is_dark()? "#c7cdd8" : "#2e333d";
47
+ }
48
+
49
+ /************************************************************
50
+ * The ink of the grid and of the ticks.
51
+ ************************************************************/
52
+ function yui_uplot_grid_ink()
53
+ {
54
+ return yui_is_dark()? "rgba(199,205,216,0.16)" : "rgba(46,51,61,0.12)";
55
+ }
56
+
57
+ const YUI_UPLOT_PALETTE = [
58
+ {stroke: "#2f6fd0", fill: "rgba(47,111,208,0.10)"}, /* 4.88 / 3.71 */
59
+ {stroke: "#b8620a", fill: "rgba(184,98,10,0.10)"}, /* 4.38 / 4.13 */
60
+ {stroke: "#2f8f4e", fill: "rgba(47,143,78,0.10)"}, /* 4.07 / 4.45 */
61
+ {stroke: "#8b5cf6", fill: "rgba(139,92,246,0.10)"}, /* 4.23 / 4.28 */
62
+ {stroke: "#0e9aa7", fill: "rgba(14,154,167,0.10)"}, /* 3.39 / 5.35 */
63
+ {stroke: "#d1344b", fill: "rgba(209,52,75,0.10)"}, /* 4.88 / 3.71 */
64
+ ];
65
+
66
+ /************************************************************
67
+ * The axes the host asked for -- at least the X and the Y,
68
+ * the two uPlot always draws -- with the ink it did not ask
69
+ * about. A stroke, a grid or a ticks the host gave is kept.
70
+ * Answers new objects: the host's are not touched.
71
+ ************************************************************/
72
+ function yui_uplot_axes(axes)
73
+ {
74
+ let list = Array.isArray(axes)? axes.slice() : [axes || {}];
75
+ while(list.length < 2) {
76
+ list.push({});
77
+ }
78
+ return list.map((ax) => {
79
+ let a = Object.assign({}, ax || {});
80
+ if(a.stroke === undefined) {
81
+ a.stroke = yui_uplot_axis_ink;
82
+ }
83
+ a.grid = Object.assign({stroke: yui_uplot_grid_ink}, a.grid || {});
84
+ a.ticks = Object.assign({stroke: yui_uplot_grid_ink}, a.ticks || {});
85
+ return a;
86
+ });
87
+ }
88
+
89
+ export {
90
+ yui_uplot_axes,
91
+ yui_uplot_axis_ink,
92
+ yui_uplot_grid_ink,
93
+ YUI_UPLOT_PALETTE,
94
+ };