cordova-plugin-ra-chart 1.0.3 → 1.0.5

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
@@ -82,6 +82,14 @@ Add the stylesheet to `angular.json`:
82
82
  ]
83
83
  ```
84
84
 
85
+ > **`ra-chart.css` must be global — never a component's `styleUrls`.** Angular's
86
+ > view encapsulation scopes those rules to `[_ngcontent-*]`, which never matches
87
+ > the legend, tooltip and zoom bar because the engine creates them at runtime.
88
+ > The classic symptom is a legend that reads `RevenueTarget` with no colour
89
+ > swatches. Since v1.0.3 the engine injects its own structural styles so this
90
+ > renders correctly regardless, and `ra-chart.css` is optional — it only supplies
91
+ > theming. Load it globally to theme; skip it entirely and charts still look right.
92
+
85
93
  The component lazy-loads `ra-chart.js` from `assets/ra-chart/ra-chart.js` on first use. To bundle it eagerly instead, add it to `angular.json` → `"scripts"`; the loader will detect `window.RaChart` and skip the fetch.
86
94
 
87
95
  To load it from somewhere else:
@@ -491,6 +499,54 @@ Force a mode per chart with a class:
491
499
 
492
500
  The default 8-colour palette is ordered so adjacent series stay distinguishable for colourblind viewers. If you pass your own `colors`, keep that in mind. Charts also carry non-colour cues — legends, direct labels, tooltips.
493
501
 
502
+ ### Changing the colours of every chart
503
+
504
+ Three ways, highest precedence first.
505
+
506
+ **Per chart** — `colors` wins over everything:
507
+
508
+ ```html
509
+ <ra-chart [colors]="['#534ab7', '#2196f3']" ...></ra-chart>
510
+ ```
511
+
512
+ **Globally in CSS** — the recommended way for Ionic. Set `--ra-chart-series-N`
513
+ from 1 upward; the engine reads until the first one you leave unset. Because it
514
+ is plain CSS, it is theme-scoped and switches automatically in dark mode:
515
+
516
+ ```css
517
+ /* src/global.scss — applies to every chart in the app */
518
+ .ra-chart {
519
+ --ra-chart-series-1: #534ab7;
520
+ --ra-chart-series-2: #2196f3;
521
+ --ra-chart-series-3: #f0334b;
522
+ --ra-chart-series-4: #eda100;
523
+ }
524
+
525
+ /* different steps for dark mode */
526
+ .ion-palette-dark .ra-chart {
527
+ --ra-chart-series-1: #9085e9;
528
+ --ra-chart-series-2: #3987e5;
529
+ --ra-chart-series-3: #e66767;
530
+ --ra-chart-series-4: #c98500;
531
+ }
532
+ ```
533
+
534
+ Scope it to recolour one section only — `.reports-page .ra-chart { … }`.
535
+
536
+ **Globally in JS** — one call before any chart is created, e.g. in `main.ts`:
537
+
538
+ ```ts
539
+ declare const RaChart: any;
540
+
541
+ RaChart.setPalette(['#534ab7', '#2196f3', '#f0334b', '#eda100']);
542
+ RaChart.setPalette(lightHexes, darkHexes); // separate dark steps
543
+ RaChart.resetPalette(); // back to the built-in palette
544
+ ```
545
+
546
+ Colours cycle when a chart has more series than you supply. Charts that already
547
+ exist keep their palette until they rebuild — call `replay()` on them, or set the
548
+ palette before creating any chart.
549
+
494
550
  ---
495
551
 
496
552
  ## Recipes
@@ -621,6 +677,8 @@ To silence the diagnostics in production: `RaChart.warnings = false;`
621
677
 
622
678
  **Labels are cut off** — increase `height`, or shorten category labels. Horizontal `bar` and `gantt` cap the label gutter at about a third of the width.
623
679
 
680
+ **Legend reads "RevenueTarget" with no colour swatches** — the legend HTML is unstyled, meaning `ra-chart.css` did not reach it. Almost always because it was added to a component's `styleUrls` instead of `angular.json` → `styles`; view encapsulation scopes it to `[_ngcontent-*]` and the runtime-created legend has no such attribute. Fixed by default in v1.0.3 (the engine injects its own structural CSS), so updating the engine resolves it. To theme, move `ra-chart.css` to the global styles array.
681
+
624
682
  **Tooltip is clipped inside `ion-card`** — the tooltip is absolutely positioned inside the chart element; give the card content enough padding, or set `sheetTooltip: true` to dock it.
625
683
 
626
684
  **No haptics on device** — install `@capacitor/haptics`, or rely on the `navigator.vibrate` fallback (Android only; iOS Safari does not support it).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cordova-plugin-ra-chart",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Dependency-free SVG chart engine for Cordova and Ionic — 21 chart types with touch gestures, pinch-to-zoom, haptics and dark-mode theming. No native code, no build step.",
5
5
  "main": "www/ra-chart.js",
6
6
  "types": "types/index.d.ts",
package/plugin.xml CHANGED
@@ -15,7 +15,7 @@
15
15
  -->
16
16
  <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
17
17
  id="cordova-plugin-ra-chart"
18
- version="1.0.2">
18
+ version="1.0.4">
19
19
 
20
20
  <name>raChart</name>
21
21
  <description>
package/types/index.d.ts CHANGED
@@ -200,6 +200,25 @@ export declare class RaChart {
200
200
  static paletteDark: string[];
201
201
  static types: RaChartType[];
202
202
  static create(host: HTMLElement | string, options?: RaChartOptions): RaChart;
203
+
204
+ /** Silence the "nothing to plot" console diagnostics. */
205
+ static warnings: boolean;
206
+
207
+ /**
208
+ * Recolour every chart created from now on. Pass one array to use it in
209
+ * both light and dark mode, or two for separate dark steps. Overridden per
210
+ * chart by `colors`, and by `--ra-chart-series-N` CSS variables.
211
+ */
212
+ static setPalette(light: string[], dark?: string[]): typeof RaChart;
213
+
214
+ /** Restore the built-in colourblind-safe palette. */
215
+ static resetPalette(): typeof RaChart;
216
+
217
+ /** Register `<ra-chart>` as a custom element (done automatically). */
218
+ static defineElement(tag?: string): boolean;
219
+
220
+ /** Inject the built-in structural stylesheet (done automatically). */
221
+ static injectStyles(): void;
203
222
  }
204
223
 
205
224
  export default RaChart;
package/www/ra-chart.css CHANGED
@@ -37,6 +37,20 @@ ra-chart {
37
37
 
38
38
  --ra-chart-radius: 12px;
39
39
 
40
+ /* ---- series palette ----
41
+ Uncomment and set these to recolour every chart. The engine reads
42
+ --ra-chart-series-1 upward and stops at the first one you leave unset,
43
+ so define as many as your busiest chart needs. Overridden per chart by
44
+ the `colors` option; overrides RaChart.setPalette().
45
+
46
+ --ra-chart-series-1: #534ab7;
47
+ --ra-chart-series-2: #2196f3;
48
+ --ra-chart-series-3: #f0334b;
49
+ --ra-chart-series-4: #eda100;
50
+ --ra-chart-series-5: #1baf7a;
51
+ --ra-chart-series-6: #eb6834;
52
+ */
53
+
40
54
  position: relative;
41
55
  display: block;
42
56
  width: 100%;
package/www/ra-chart.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * raChart Cordova v1.0.2 — mobile SVG chart engine
2
+ * raChart Cordova v1.0.4 — mobile SVG chart engine
3
3
  * RemoteApps UI Components
4
4
  *
5
5
  * Zero dependencies. No jQuery, no chart library, no build step.
@@ -20,14 +20,17 @@
20
20
  "use strict";
21
21
 
22
22
  var NS = "http://www.w3.org/2000/svg";
23
- var VERSION = "1.0.2";
23
+ var VERSION = "1.0.4";
24
24
 
25
25
  /* ============================================================
26
26
  Palettes — CVD-validated order, do not shuffle
27
27
  ============================================================ */
28
28
 
29
- var PALETTE_LIGHT = ["#2a78d6", "#008300", "#e87ba4", "#eda100", "#1baf7a", "#eb6834", "#4a3aa7", "#e34948"];
30
- var PALETTE_DARK = ["#3987e5", "#008300", "#d55181", "#c98500", "#199e70", "#d95926", "#9085e9", "#e66767"];
29
+ var DEFAULT_LIGHT = ["#2a78d6", "#008300", "#e87ba4", "#eda100", "#1baf7a", "#eb6834", "#4a3aa7", "#e34948"];
30
+ var DEFAULT_DARK = ["#3987e5", "#008300", "#d55181", "#c98500", "#199e70", "#d95926", "#9085e9", "#e66767"];
31
+ // live palettes — swapped by RaChart.setPalette()
32
+ var PALETTE_LIGHT = DEFAULT_LIGHT.slice();
33
+ var PALETTE_DARK = DEFAULT_DARK.slice();
31
34
  var SEQ_LIGHT = ["#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#184f95", "#0d366b"];
32
35
  var SEQ_DARK = ["#0d366b", "#184f95", "#256abf", "#3987e5", "#6da7ec", "#9ec5f4", "#cde2fb"];
33
36
 
@@ -351,6 +354,60 @@
351
354
  gauge: "gauge", heatmap: "heat"
352
355
  };
353
356
 
357
+ /* ============================================================
358
+ Base stylesheet
359
+
360
+ The SVG gets its colours from inline attributes, but the legend, tooltip
361
+ and zoom bar are real HTML and would collapse into unstyled inline text
362
+ without CSS — the classic "legend reads RevenueTarget" symptom. Angular
363
+ makes that easy to hit: ra-chart.css dropped into a component's styleUrls
364
+ is scoped to [_ngcontent-*], which never matches nodes the engine creates
365
+ at runtime.
366
+
367
+ So the structural rules ship in JS and are injected once, at the TOP of
368
+ <head>, leaving ra-chart.css (and any app CSS) free to override them.
369
+ Colours defer to the same custom properties, with fallbacks.
370
+ ============================================================ */
371
+
372
+ var BASE_STYLE_ID = "ra-chart-base-styles";
373
+ var BASE_CSS = [
374
+ 'ra-chart{display:block;position:relative;width:100%}',
375
+ '.ra-chart{position:relative;display:block;width:100%;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;-webkit-tap-highlight-color:transparent}',
376
+ '.ra-chart__stage{position:relative;width:100%;overflow:hidden}',
377
+ '.ra-chart__stage svg{display:block;width:100%;height:100%;overflow:visible;user-select:none;-webkit-user-select:none}',
378
+ '.ra-chart .ra-hit{cursor:pointer}',
379
+ '.ra-chart__legend{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:4px 14px;padding-top:10px;font-size:13px;font-weight:700;line-height:1.4;color:var(--ra-chart-body,#4b5563)}',
380
+ '.ra-chart__legend-item{display:inline-flex;align-items:center;gap:7px;padding:7px 2px;cursor:pointer;user-select:none;-webkit-user-select:none;transition:opacity .18s}',
381
+ '.ra-chart__legend-item.is-off{opacity:.38}',
382
+ '.ra-chart__legend-item.is-off .ra-chart__legend-label{text-decoration:line-through}',
383
+ '.ra-chart__legend-swatch{display:inline-block;width:11px;height:11px;border-radius:4px;flex:0 0 auto}',
384
+ '.ra-chart__legend-value{color:var(--ra-chart-muted,#9ca3af);font-weight:600}',
385
+ '.ra-chart__tip{position:absolute;z-index:5;pointer-events:none;max-width:88%;background:var(--ra-chart-tip-bg,#1f2937);color:var(--ra-chart-tip-text,#f9fafb);font-size:12px;font-weight:600;line-height:1.5;border-radius:10px;padding:8px 12px;box-shadow:0 6px 20px rgba(15,23,42,.28);opacity:0;transform:translate(-50%,-112%) scale(.96);transition:opacity .15s,transform .15s;white-space:nowrap}',
386
+ '.ra-chart__tip.is-on{opacity:1;transform:translate(-50%,-112%) scale(1)}',
387
+ '.ra-chart__tip--sheet{left:50%!important;top:auto!important;bottom:6px;transform:translate(-50%,8px);white-space:normal;text-align:center;padding:10px 16px;border-radius:12px;font-size:13px}',
388
+ '.ra-chart__tip--sheet.is-on{transform:translate(-50%,0)}',
389
+ '.ra-chart__tip-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}',
390
+ '.ra-chart__tip-cat{display:block;color:var(--ra-chart-tip-muted,#9ca3af);font-weight:500;margin-bottom:2px}',
391
+ '.ra-chart__tip-muted{color:var(--ra-chart-tip-muted,#9ca3af);font-weight:500}',
392
+ '.ra-chart__zoom{padding:6px 0 14px;touch-action:none}',
393
+ '.ra-chart__zoom-track{position:relative;height:8px;background:var(--ra-chart-zoom-track,#eceff3);border-radius:999px;margin:0 13px}',
394
+ '.ra-chart__zoom-sel{position:absolute;top:0;height:100%;background:var(--ra-chart-zoom-sel,#c7c2ee);border-radius:999px;cursor:grab}',
395
+ '.ra-chart__zoom-handle{position:absolute;top:50%;width:26px;height:26px;border-radius:50%;background:var(--ra-chart-zoom-handle,#fff);border:2px solid var(--ra-chart-zoom-handle-border,#534ab7);box-shadow:0 1px 5px rgba(15,23,42,.28);transform:translate(-50%,-50%);cursor:ew-resize;touch-action:none}',
396
+ '@media (pointer:fine){.ra-chart__zoom-handle{width:18px;height:18px}}'
397
+ ].join("");
398
+
399
+ function ensureBaseStyles() {
400
+ if (typeof document === "undefined") return;
401
+ if (document.getElementById(BASE_STYLE_ID)) return;
402
+ var head = document.head || document.getElementsByTagName("head")[0];
403
+ if (!head) return;
404
+ var st = document.createElement("style");
405
+ st.id = BASE_STYLE_ID;
406
+ st.appendChild(document.createTextNode(BASE_CSS));
407
+ // first in <head> so ra-chart.css and app styles win on equal specificity
408
+ head.insertBefore(st, head.firstChild);
409
+ }
410
+
354
411
  var UID = 0;
355
412
 
356
413
  /* ============================================================
@@ -362,6 +419,7 @@
362
419
  if (typeof host === "string") host = document.querySelector(host);
363
420
  if (!host) throw new Error("raChart: host element not found");
364
421
 
422
+ ensureBaseStyles();
365
423
  this.el = host;
366
424
  this.uid = ++UID;
367
425
  this.opts = merge(merge({}, DEFAULTS), options || {});
@@ -390,6 +448,16 @@
390
448
  }
391
449
  var dark = v("--ra-chart-scheme", "light").indexOf("dark") >= 0;
392
450
  this.dark = dark;
451
+
452
+ // Palette from CSS custom properties: --ra-chart-series-1 .. -N, read until
453
+ // the first gap. Lets a theme file recolour every chart (and switch palettes
454
+ // in dark mode) with no JavaScript.
455
+ var cssSeries = [];
456
+ for (var i = 1; i <= 16; i++) {
457
+ var c = v("--ra-chart-series-" + i, "");
458
+ if (!c) break;
459
+ cssSeries.push(c);
460
+ }
393
461
  this.theme = {
394
462
  dark: dark,
395
463
  surface: v("--ra-chart-surface", dark ? "#1a1a19" : "#ffffff"),
@@ -400,7 +468,9 @@
400
468
  baseline: v("--ra-chart-baseline", dark ? "#383835" : "#c3c2b7"),
401
469
  body: v("--ra-chart-body", dark ? "#c3c2b7" : "#4b5563")
402
470
  };
403
- this.palette = this.opts.colors || (dark ? PALETTE_DARK : PALETTE_LIGHT);
471
+ // precedence: per-chart colors > CSS variables > global palette
472
+ this.palette = this.opts.colors ||
473
+ (cssSeries.length ? cssSeries : (dark ? PALETTE_DARK : PALETTE_LIGHT));
404
474
  this.seq = dark ? SEQ_DARK : SEQ_LIGHT;
405
475
  };
406
476
 
@@ -2852,6 +2922,42 @@
2852
2922
  RaChart.defaults = DEFAULTS;
2853
2923
  RaChart.palette = PALETTE_LIGHT;
2854
2924
  RaChart.paletteDark = PALETTE_DARK;
2925
+
2926
+ /**
2927
+ * Recolour every chart created from now on.
2928
+ *
2929
+ * RaChart.setPalette(['#534ab7', '#2196f3', '#f0334b']);
2930
+ * RaChart.setPalette(lightHexes, darkHexes); // separate dark steps
2931
+ *
2932
+ * Pass one array to use it in both modes. Colours cycle if a chart has more
2933
+ * series than you supply. Existing charts keep their palette until they
2934
+ * rebuild — call replay() on them, or set this before creating any chart.
2935
+ * Overridden per chart by `colors`, and by --ra-chart-series-N in CSS.
2936
+ */
2937
+ RaChart.setPalette = function (light, dark) {
2938
+ if (light && light.length) {
2939
+ PALETTE_LIGHT = light.slice();
2940
+ RaChart.palette = PALETTE_LIGHT;
2941
+ if (!dark || !dark.length) {
2942
+ PALETTE_DARK = light.slice();
2943
+ RaChart.paletteDark = PALETTE_DARK;
2944
+ }
2945
+ }
2946
+ if (dark && dark.length) {
2947
+ PALETTE_DARK = dark.slice();
2948
+ RaChart.paletteDark = PALETTE_DARK;
2949
+ }
2950
+ return RaChart;
2951
+ };
2952
+
2953
+ /** Restore the built-in colourblind-safe palette. */
2954
+ RaChart.resetPalette = function () {
2955
+ PALETTE_LIGHT = DEFAULT_LIGHT.slice();
2956
+ PALETTE_DARK = DEFAULT_DARK.slice();
2957
+ RaChart.palette = PALETTE_LIGHT;
2958
+ RaChart.paletteDark = PALETTE_DARK;
2959
+ return RaChart;
2960
+ };
2855
2961
  RaChart.types = Object.keys(KINDS);
2856
2962
  RaChart.create = function (host, options) { return new RaChart(host, options); };
2857
2963
 
@@ -3018,6 +3124,8 @@
3018
3124
  }
3019
3125
 
3020
3126
  RaChart.defineElement = defineElement;
3127
+ /** Inject the built-in structural stylesheet (called automatically). */
3128
+ RaChart.injectStyles = ensureBaseStyles;
3021
3129
 
3022
3130
  // Auto-register so the tag works with no setup. Harmless when a framework
3023
3131
  // component already owns the element — the stand-down guard handles it.