@bicharts/chart-host 0.5.94 → 0.5.95

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.mjs CHANGED
@@ -1941,9 +1941,16 @@ Mt.config = function(t2) {
1941
1941
 
1942
1942
  // src/palette.ts
1943
1943
  var MIN_DELTA_E = 10;
1944
- function pickDistinctColorFromSeed(seedHex, existing, minDistance = MIN_DELTA_E) {
1944
+ var LEGIBLE_LIGHTNESS = [15, 85];
1945
+ function pickDistinctColorFromSeed(seedHex, existing, minDistance = MIN_DELTA_E, options = {}) {
1945
1946
  const existingCs = [...existing].map((c2) => Mt(c2));
1946
1947
  const seed = Mt(seedHex);
1948
+ const band = options.lightnessBand === void 0 ? LEGIBLE_LIGHTNESS : options.lightnessBand;
1949
+ const legible = (c2) => {
1950
+ if (!band) return true;
1951
+ const l2 = c2.hsl()[2];
1952
+ return l2 > band[0] && l2 < band[1];
1953
+ };
1947
1954
  const minDeltaE = (c2) => existingCs.length === 0 ? Number.POSITIVE_INFINITY : Math.min(...existingCs.map((c22) => c2.deltaE(c22, "CIE2000")));
1948
1955
  if (minDeltaE(seed) >= minDistance) {
1949
1956
  const hex = seed.hex();
@@ -1952,6 +1959,7 @@ function pickDistinctColorFromSeed(seedHex, existing, minDistance = MIN_DELTA_E)
1952
1959
  let bestCandidate = seed;
1953
1960
  let bestMinDist = minDeltaE(seed);
1954
1961
  const tryVariant = (c2) => {
1962
+ if (!legible(c2)) return null;
1955
1963
  const d2 = minDeltaE(c2);
1956
1964
  if (d2 >= minDistance) {
1957
1965
  const hex = c2.hex();
@@ -1977,10 +1985,10 @@ function pickDistinctColorFromSeed(seedHex, existing, minDistance = MIN_DELTA_E)
1977
1985
  }
1978
1986
  return { hex: seed.hex(), registerHex: bestCandidate.hex() };
1979
1987
  }
1980
- function buildPaletteFromSeed(seedHex, count, minDistance = MIN_DELTA_E) {
1981
- return buildPalette(() => seedHex, count, minDistance);
1988
+ function buildPaletteFromSeed(seedHex, count, minDistance = MIN_DELTA_E, options = {}) {
1989
+ return buildPalette(() => seedHex, count, minDistance, options);
1982
1990
  }
1983
- function buildPalette(seedFor, count, minDistance = MIN_DELTA_E) {
1991
+ function buildPalette(seedFor, count, minDistance = MIN_DELTA_E, options = {}) {
1984
1992
  const out = [];
1985
1993
  if (!(count > 0)) return out;
1986
1994
  const issued = /* @__PURE__ */ new Set();
@@ -1999,7 +2007,7 @@ function buildPalette(seedFor, count, minDistance = MIN_DELTA_E) {
1999
2007
  if (!seedHex) seedHex = lastSeed;
2000
2008
  if (!seedHex) break;
2001
2009
  lastSeed = seedHex;
2002
- const { hex, registerHex } = pickDistinctColorFromSeed(seedHex, issued, minDistance);
2010
+ const { hex, registerHex } = pickDistinctColorFromSeed(seedHex, issued, minDistance, options);
2003
2011
  let chosen = hex;
2004
2012
  let register = registerHex;
2005
2013
  if (distance(chosen) < minDistance) {
@@ -2120,6 +2128,7 @@ export {
2120
2128
  LABEL_CONTRAST_CAP,
2121
2129
  LABEL_CONTRAST_DONE_ATTR,
2122
2130
  LEGEND_MARK_CLASS,
2131
+ LEGIBLE_LIGHTNESS,
2123
2132
  LIFT_SELECTED_CLASS,
2124
2133
  LIGHT_TEXT,
2125
2134
  MARK_CLASS,
@@ -27,5 +27,5 @@ export { SCROLL_SLACK_PX, MAX_FRAME_GROW_FACTOR, PHANTOM_FRACTION, FIT_CONTENT_S
27
27
  export { fitRenderedChart, fitReadingFor, measureContainerBoxes, svgInkReach, ctmScaleOf, type FitReading, type InkReach, type FitRenderedChartOptions, type FitRenderedChartResult, } from "./fitDom";
28
28
  export { AXIS_PIN_MIN_LABELS, AXIS_PIN_BAND_PAD_PX, AXIS_PIN_MAX_BAND_FRACTION, AXIS_PIN_TRACK_REACH_PX, isHorizontalLabelRow, labelBand, planAxisPin, axisPinPlacement, type LabelRowBox, type AxisBand, type AxisPinCandidate, type AxisPinPlan, type AxisPinEdge, } from "./fit";
29
29
  export { pinScrolledAxis, unpinScrolledAxis, type AxisPinReport } from "./fitDom";
30
- export { MIN_DELTA_E, pickDistinctColorFromSeed, buildPalette, buildPaletteFromSeed, orderMostDistinct, type PaletteResult, type SeedForSlot, } from "./palette";
30
+ export { MIN_DELTA_E, pickDistinctColorFromSeed, buildPalette, buildPaletteFromSeed, orderMostDistinct, LEGIBLE_LIGHTNESS, type PaletteResult, type SeedForSlot, type PaletteOptions, } from "./palette";
31
31
  export { deltaEHex } from "./deltaE";
@@ -4,6 +4,30 @@
4
4
  * swatches; JND (just-noticeable-difference) at this scale is ≈5.
5
5
  */
6
6
  export declare const MIN_DELTA_E = 10;
7
+ /**
8
+ * THE LIGHTNESS A COLOUR THE WALK INVENTS MUST FALL INSIDE (HSL lightness, 0-100, exclusive).
9
+ *
10
+ * The walk's lightness step moves the seed up to 45 points, so from a light seed it could land on
11
+ * a near-white - and a categorical mark that is near-white on a white page, or near-black on a dark
12
+ * one, is not a colour a reader can find. Measured before this band existed: a green seed's
13
+ * twenty-slot palette put `#ebf4e5` (lightness 93) in slot 7, and a pool of Office theme colours led
14
+ * by a red put `#d5e5f4` (90) in slot 17.
15
+ *
16
+ * INVENTED COLOURS ONLY. A seed the host supplied comes back as supplied, however light or dark -
17
+ * that is a report author's decision - and the spare-colour sweep keeps its own, narrower band.
18
+ */
19
+ export declare const LEGIBLE_LIGHTNESS: readonly [number, number];
20
+ export interface PaletteOptions {
21
+ /**
22
+ * The lightness band invented colours must sit in. Defaults to `LEGIBLE_LIGHTNESS`.
23
+ *
24
+ * `null` walks as the package did before the band existed, colour for colour. It exists for a
25
+ * host that STORED palettes the older walk produced and has to recognise one again by
26
+ * re-deriving it: change the walk under such a host and every stored palette silently stops
27
+ * matching. Nothing should draw with it.
28
+ */
29
+ lightnessBand?: readonly [number, number] | null;
30
+ }
7
31
  /**
8
32
  * Pick a hex color for a palette slot.
9
33
  *
@@ -30,7 +54,7 @@ export interface PaletteResult {
30
54
  /** Hex color to register in the palette-issued set (may differ from `hex` on the give-up fallback). */
31
55
  readonly registerHex: string;
32
56
  }
33
- export declare function pickDistinctColorFromSeed(seedHex: string, existing: ReadonlySet<string>, minDistance?: number): PaletteResult;
57
+ export declare function pickDistinctColorFromSeed(seedHex: string, existing: ReadonlySet<string>, minDistance?: number, options?: PaletteOptions): PaletteResult;
34
58
  /**
35
59
  * A whole categorical palette from ONE seed colour.
36
60
  *
@@ -49,7 +73,7 @@ export declare function pickDistinctColorFromSeed(seedHex: string, existing: Rea
49
73
  * Deterministic: same seed and count in, same array out, which is what lets a host PERSIST the
50
74
  * result and re-derive it later without the colours shifting under a saved chart.
51
75
  */
52
- export declare function buildPaletteFromSeed(seedHex: string, count: number, minDistance?: number): string[];
76
+ export declare function buildPaletteFromSeed(seedHex: string, count: number, minDistance?: number, options?: PaletteOptions): string[];
53
77
  /**
54
78
  * WHERE EACH SLOT'S BASE COLOUR COMES FROM. Called with the slot index, 0-based.
55
79
  *
@@ -75,7 +99,7 @@ export type SeedForSlot = (slot: number) => string | null | undefined;
75
99
  * A host with no such API - an Excel workbook offers exactly one resolvable accent - passes a
76
100
  * constant provider and the walk does the spreading. That is a fallback, not the design.
77
101
  */
78
- export declare function buildPalette(seedFor: SeedForSlot, count: number, minDistance?: number): string[];
102
+ export declare function buildPalette(seedFor: SeedForSlot, count: number, minDistance?: number, options?: PaletteOptions): string[];
79
103
  /**
80
104
  * A POOL OF ACCEPTABLE COLOURS, ORDERED SO THE MOST DISTINCT COME FIRST.
81
105
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicharts/chart-host",
3
- "version": "0.5.94",
3
+ "version": "0.5.95",
4
4
  "description": "Run a BIC-generated D3 chart in any web host: compiles the generated render() function, applies the shared option defaults, resolves mark clicks (through tooltip overlays), owns the selection affordance, and translates row indices between cross-filtered charts. The same contract the BIC Power BI visual implements, minus Power BI. React bindings at @bicharts/chart-host/react.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",