@fasl-work/caos-app-shell 0.17.0 → 0.18.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/chart.css +5 -0
- package/dist/chart.d.ts +68 -9
- package/dist/chart.js +127 -33
- package/dist/{chunk-YECZXGVG.js → chunk-DBCMAL2G.js} +73 -1
- package/dist/index.d.ts +3 -37
- package/dist/index.js +12 -80
- package/dist/{tokens-BTOzar-U.d.ts → text-DyQ1A8oo.d.ts} +39 -1
- package/gate/inpage.mjs +1 -1
- package/gate/run.mjs +3 -1
- package/package.json +1 -1
- package/reserved-classes.json +2 -0
package/chart.css
CHANGED
|
@@ -22,3 +22,8 @@
|
|
|
22
22
|
.caos-chart.fill[data-parity] > .caos-chart-plot { display: flex; align-items: center; justify-content: center; }
|
|
23
23
|
.caos-chart[data-pick] .u-over { cursor: pointer; }
|
|
24
24
|
.caos-chart .u-cursor-x, .caos-chart .u-cursor-y { border-color: var(--color-fg-faint) !important; }
|
|
25
|
+
/* The key that solos a series (`solo`, 0.18.0): each entry is a button. At rest it reads as the plain key; the soloed one is
|
|
26
|
+
set off by a border and bold text, in the text colour, never by colour alone. */
|
|
27
|
+
.caos-chart-key-button { display: inline-flex; align-items: center; gap: 0.3rem; min-width: 0; margin: 0; padding: 0.15rem 0.45rem; border: 1px solid transparent; border-radius: 0.4rem; background: none; color: inherit; font: inherit; line-height: inherit; text-align: start; cursor: pointer; }
|
|
28
|
+
.caos-chart-key-button:hover { border-color: var(--color-border); }
|
|
29
|
+
.caos-chart-key-button[aria-pressed="true"] { border-color: var(--color-fg-subtle); color: var(--color-fg); font-weight: 600; }
|
package/dist/chart.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import uPlot from 'uplot';
|
|
3
|
-
import { F as FormatOptions, S as ShellColorToken } from './
|
|
4
|
-
|
|
3
|
+
import { F as FormatOptions, S as ShellColorToken } from './text-DyQ1A8oo.js';
|
|
4
|
+
export { r as referenceLineName } from './text-DyQ1A8oo.js';
|
|
5
|
+
import { B as BiText, L as Lang } from './text-BlY47nIt.js';
|
|
5
6
|
import 'zustand';
|
|
6
7
|
|
|
7
8
|
interface ChartSeries {
|
|
9
|
+
/** What identifies the series to the solo key (0.18.0): the solo follows the series with this id when the list of series
|
|
10
|
+
* changes (one dropped, one added, a label changed), not its position. Without an id the English label is the key. Unique
|
|
11
|
+
* within the chart; with two series of one key the first is taken. */
|
|
12
|
+
id?: string;
|
|
8
13
|
label: BiText;
|
|
9
14
|
/** One value per x; `null` leaves a gap. */
|
|
10
15
|
values: (number | null)[];
|
|
@@ -20,6 +25,14 @@ interface ChartSeries {
|
|
|
20
25
|
* value. It is drawn over the plot on its own x, outside the curve's data, so it takes no part in the cursor, the
|
|
21
26
|
* pick or the readout, and the axes take its extent in. */
|
|
22
27
|
x?: number[];
|
|
28
|
+
/** A dot at each value of a `line` series (CAOS_Fragmenta drew them under 40 values: `dots={x.length < 40}`). Off by
|
|
29
|
+
* default; no dot is drawn at a `null`. */
|
|
30
|
+
dots?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** A named x tick: the x value it sits at and the text the axis reads there (and the readout, for an x on it). */
|
|
33
|
+
interface ChartTick {
|
|
34
|
+
value: number;
|
|
35
|
+
label: BiText;
|
|
23
36
|
}
|
|
24
37
|
/** What a reference line may be dragged over: the range it stays inside, and the step it snaps to (a hundredth of the
|
|
25
38
|
* range when not given; on a log axis the step is a factor). */
|
|
@@ -46,6 +59,17 @@ interface UPlotChartProps {
|
|
|
46
59
|
values: number[];
|
|
47
60
|
time?: boolean;
|
|
48
61
|
log?: boolean;
|
|
62
|
+
/** Named ticks (0.18.0): the axis ticks exactly at these values, no other, each labelled with its text in the page
|
|
63
|
+
* language (a categorical axis: protocols, blast ids). The readout names an x that sits on one by its label. A tick
|
|
64
|
+
* outside the range is not drawn; an empty list leaves uPlot its own ticks. A value listed twice keeps its first label.
|
|
65
|
+
* Labels must be different from each other, adjacent or not (the gate fails any repeated label, G6). An x is on a tick
|
|
66
|
+
* when it is within 1e-9 of the x span of it. Ignored on a time axis. */
|
|
67
|
+
ticks?: ChartTick[];
|
|
68
|
+
/** The x scale spans at least this range (0.18.0), as `y.range` fixes the y scale: widen it past the data so an end tick's
|
|
69
|
+
* label is not cut by the plot edge. The data and the overlays still widen it further. On a log axis a range that reaches 0
|
|
70
|
+
* or below is ignored (the overlays still widen the scale); on a parity chart it is ignored, the chart's own shared range
|
|
71
|
+
* rules. */
|
|
72
|
+
range?: [number, number];
|
|
49
73
|
};
|
|
50
74
|
y: ChartAxis & {
|
|
51
75
|
log?: boolean;
|
|
@@ -58,10 +82,10 @@ interface UPlotChartProps {
|
|
|
58
82
|
label: BiText;
|
|
59
83
|
}[];
|
|
60
84
|
/** Horizontal reference lines at y values, labelled at their right end (a null model's constant prediction, a
|
|
61
|
-
* target, a limit). */
|
|
85
|
+
* target, a limit). A line without a `label` is drawn with no label box and nothing reserved for one (a zero line). */
|
|
62
86
|
yMarks?: {
|
|
63
87
|
y: number;
|
|
64
|
-
label
|
|
88
|
+
label?: BiText;
|
|
65
89
|
tone?: YMarkTone;
|
|
66
90
|
drag?: YMarkDrag;
|
|
67
91
|
}[];
|
|
@@ -88,7 +112,40 @@ interface UPlotChartProps {
|
|
|
88
112
|
readout?: (index: number) => string;
|
|
89
113
|
/** The readout at rest; by default "Hover the chart to read the values". */
|
|
90
114
|
hint?: BiText;
|
|
115
|
+
/** The key solos a series (0.18.0): each entry is a button (`aria-pressed`, Tab, click, Enter or Space) that dims every
|
|
116
|
+
* other series (alpha 0.12, 1 px) and leaves the chosen one as drawn; pressing it again releases it, pressing another
|
|
117
|
+
* moves the solo. The chart is redrawn, not rebuilt. A chart of one series shows the key too. Off by default. */
|
|
118
|
+
solo?: boolean;
|
|
91
119
|
}
|
|
120
|
+
/** The alpha a series takes when another one is soloed (0.18.0; what CAOS_Fragmenta's key did). */
|
|
121
|
+
declare const SOLO_DIM_ALPHA = 0.12;
|
|
122
|
+
/** How a series is drawn while `solo` (the index in `series` of the soloed one, or null) is held: as given, or dimmed to
|
|
123
|
+
* `SOLO_DIM_ALPHA` and 1 px when another is soloed. Dimmed, never hidden, so the reader keeps the context. */
|
|
124
|
+
declare function soloStyle(solo: number | null, i: number, width: number): {
|
|
125
|
+
alpha: number;
|
|
126
|
+
width: number;
|
|
127
|
+
};
|
|
128
|
+
/** The values a named x axis ticks at inside [min, max]: ascending, each once; on a log axis only the ones above 0. A value
|
|
129
|
+
* that is not a number is dropped. */
|
|
130
|
+
declare function tickSplits(ticks: readonly ChartTick[], min: number, max: number, log?: boolean): number[];
|
|
131
|
+
/** The label of the named tick at an x, in the page language; null when no tick sits there. An x is on a tick when it is
|
|
132
|
+
* within 1e-9 of `span` (the x span, as `tickSplits` takes the range) of its value, so 0.1 + 0.2 is on a tick at 0.3; without
|
|
133
|
+
* a span only an equal x is. A value listed twice keeps its first label. */
|
|
134
|
+
declare function tickLabelAt(ticks: readonly ChartTick[] | undefined, x: number, lang: Lang, span?: number): string | null;
|
|
135
|
+
/** How many of the labels of named ticks repeat another's, adjacent or not (the gate's check of numeric ticks counts only
|
|
136
|
+
* neighbours, and on a categorical axis order means nothing), and which ones; an empty label is no label. */
|
|
137
|
+
declare function namedRepeats(labels: readonly string[]): {
|
|
138
|
+
n: number;
|
|
139
|
+
names: string[];
|
|
140
|
+
};
|
|
141
|
+
/** What a series is known by to the solo key: its id, else its English label. */
|
|
142
|
+
declare function soloKey(s: ChartSeries): string;
|
|
143
|
+
/** The x scale of a chart whose x range is fixed, or whose overlays reach past the curve: the data's extent widened by the
|
|
144
|
+
* given range and by the overlays' x; null when none is given (uPlot's own range), and on a log axis when the data would reach 0.
|
|
145
|
+
* One x alone gets a unit either side, a decade on a log axis. `xs` is sorted ascending. */
|
|
146
|
+
declare function xScaleRange(xs: readonly number[], ext: {
|
|
147
|
+
x: [number, number];
|
|
148
|
+
} | null, range: readonly [number, number] | undefined, log: boolean): [number, number] | null;
|
|
92
149
|
/** The colour and dash of a series: its own, or the rotation's; when the rotation comes round (a seventh series
|
|
93
150
|
* repeats the first colour) the repeat is dashed, so two series never look the same (CAOS_Fragmenta drew this for
|
|
94
151
|
* itself until 0.9.0). */
|
|
@@ -169,12 +226,12 @@ declare function drawMarks(u: uPlot, marks: {
|
|
|
169
226
|
/**
|
|
170
227
|
* The horizontal reference lines of a chart and their labels: a dashed line across the plot, its label at the right
|
|
171
228
|
* end above the line (below it when the line runs along the top), inside the plot, haloed; a label that would overlap
|
|
172
|
-
* the one placed before it moves left of it. A line outside the y range is not drawn. A mark's `color` (the tone's) draws
|
|
229
|
+
* the one placed before it moves left of it. A line outside the y range is not drawn; a line without a label is drawn alone. A mark's `color` (the tone's) draws
|
|
173
230
|
* its line and its label; without one `style.color` does.
|
|
174
231
|
*/
|
|
175
232
|
declare function drawYMarks(u: uPlot, marks: {
|
|
176
233
|
y: number;
|
|
177
|
-
label
|
|
234
|
+
label?: string;
|
|
178
235
|
color?: string;
|
|
179
236
|
}[], style: {
|
|
180
237
|
color: string;
|
|
@@ -195,8 +252,10 @@ declare function nearestPoint(xs: readonly number[], ys: readonly (readonly (num
|
|
|
195
252
|
* uPlot's legend, which a sized host clips (known shell defect 3). A chart of two or more series keys every series
|
|
196
253
|
* under the plot, always (its colour, a dashed or a dotted swatch, its label): at rest the readout names none of them
|
|
197
254
|
* (known shell defect 17). An axis with fixed decimals ticks only where its labels differ (`tickSteps`). The host
|
|
198
|
-
* declares `data-series`, `data-axis-titles`, `data-ticks-cut`, `data-ticks-repeat` and `data-drawn` for the gate.
|
|
255
|
+
* declares `data-series`, `data-axis-titles`, `data-ticks-cut`, `data-ticks-repeat` and `data-drawn` for the gate. Since
|
|
256
|
+
* 0.18.0: named x ticks (`x.ticks`, declared in `data-x-tick-labels`), an x range (`x.range`), a key that solos a series
|
|
257
|
+
* (`solo`, declared in `data-solo`), dots on a line (`ChartSeries.dots`) and reference lines without a label.
|
|
199
258
|
*/
|
|
200
|
-
declare function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height, onCursor, onPick, parity, readout, hint }: UPlotChartProps): react.JSX.Element;
|
|
259
|
+
declare function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height, onCursor, onPick, parity, readout, hint, solo }: UPlotChartProps): react.JSX.Element;
|
|
201
260
|
|
|
202
|
-
export { type ChartAxis, type ChartSeries, LOG_TABLE_FLOOR, UPlotChart, type UPlotChartProps, YMARK_TONE_TOKENS, type YMarkDrag, type YMarkTone, clampMark, decadeOnly, drawMarks, drawYMarks, logDecades, nearestPoint, nudgeMark, overlayExtent, parityBox, parityRange, rangeWithLevels, repeatedLabels, seriesStyle, smallestPositive, sortOrder, tickSteps };
|
|
261
|
+
export { type ChartAxis, type ChartSeries, type ChartTick, LOG_TABLE_FLOOR, SOLO_DIM_ALPHA, UPlotChart, type UPlotChartProps, YMARK_TONE_TOKENS, type YMarkDrag, type YMarkTone, clampMark, decadeOnly, drawMarks, drawYMarks, logDecades, namedRepeats, nearestPoint, nudgeMark, overlayExtent, parityBox, parityRange, rangeWithLevels, repeatedLabels, seriesStyle, smallestPositive, soloKey, soloStyle, sortOrder, tickLabelAt, tickSplits, tickSteps, xScaleRange };
|
package/dist/chart.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useShellLang, useThemeStore, useStageSize,
|
|
1
|
+
import { pick, useShellLang, useThemeStore, useStageSize, resolveToken, NBSP, formatNumber, formatTicks, referenceLineName } from './chunk-DBCMAL2G.js';
|
|
2
|
+
export { referenceLineName } from './chunk-DBCMAL2G.js';
|
|
2
3
|
import './chunk-33WTUQ7Q.js';
|
|
3
|
-
import { useRef, useCallback, useState,
|
|
4
|
+
import { useRef, useCallback, useState, useEffect, useMemo } from 'react';
|
|
4
5
|
import uPlot from 'uplot';
|
|
5
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
8
|
var YMARK_TONE_TOKENS = {
|
|
8
9
|
warn: "--color-warn",
|
|
@@ -11,6 +12,52 @@ var YMARK_TONE_TOKENS = {
|
|
|
11
12
|
neutral: "--color-fg-subtle"
|
|
12
13
|
};
|
|
13
14
|
var ROTATION = ["--color-accent", "--color-magenta", "--color-accent-2", "--color-good", "--color-warn", "--color-bad"];
|
|
15
|
+
var SOLO_DIM_ALPHA = 0.12;
|
|
16
|
+
function soloStyle(solo, i, width) {
|
|
17
|
+
return solo !== null && solo !== i ? { alpha: SOLO_DIM_ALPHA, width: 1 } : { alpha: 1, width };
|
|
18
|
+
}
|
|
19
|
+
function tickSplits(ticks, min, max, log = false) {
|
|
20
|
+
const eps = Math.abs(max - min) * 1e-9;
|
|
21
|
+
const values = ticks.map((t) => t.value).filter((v) => Number.isFinite(v) && (!log || v > 0) && v >= min - eps && v <= max + eps);
|
|
22
|
+
return [...new Set(values)].sort((a, b) => a - b);
|
|
23
|
+
}
|
|
24
|
+
function tickLabelAt(ticks, x, lang, span = 0) {
|
|
25
|
+
const eps = Math.abs(span) * 1e-9;
|
|
26
|
+
const t = ticks?.find((one) => Math.abs(one.value - x) <= eps);
|
|
27
|
+
return t ? pick(t.label, lang) : null;
|
|
28
|
+
}
|
|
29
|
+
function namedRepeats(labels) {
|
|
30
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31
|
+
const names = [];
|
|
32
|
+
let n = 0;
|
|
33
|
+
for (const l of labels) {
|
|
34
|
+
if (!l) continue;
|
|
35
|
+
if (seen.has(l)) {
|
|
36
|
+
n++;
|
|
37
|
+
if (!names.includes(l)) names.push(l);
|
|
38
|
+
} else seen.add(l);
|
|
39
|
+
}
|
|
40
|
+
return { n, names };
|
|
41
|
+
}
|
|
42
|
+
function soloKey(s) {
|
|
43
|
+
return s.id ?? pick(s.label, "en");
|
|
44
|
+
}
|
|
45
|
+
function xScaleRange(xs, ext, range, log) {
|
|
46
|
+
const given = range && !(log && Math.min(range[0], range[1]) <= 0) ? range : void 0;
|
|
47
|
+
if (!ext && !given || xs.length === 0) return null;
|
|
48
|
+
let lo = xs[0];
|
|
49
|
+
let hi = xs[xs.length - 1];
|
|
50
|
+
if (ext) {
|
|
51
|
+
lo = Math.min(lo, ext.x[0]);
|
|
52
|
+
hi = Math.max(hi, ext.x[1]);
|
|
53
|
+
}
|
|
54
|
+
if (given) {
|
|
55
|
+
lo = Math.min(lo, given[0], given[1]);
|
|
56
|
+
hi = Math.max(hi, given[0], given[1]);
|
|
57
|
+
}
|
|
58
|
+
if (log && !(lo > 0)) return null;
|
|
59
|
+
return hi > lo ? [lo, hi] : log ? [lo / 10, hi * 10] : [lo - 1, hi + 1];
|
|
60
|
+
}
|
|
14
61
|
function seriesStyle(s, i) {
|
|
15
62
|
const color = s.color ?? ROTATION[i % ROTATION.length];
|
|
16
63
|
const dash = s.dash ?? (!s.color && i >= ROTATION.length ? [6, 4] : void 0);
|
|
@@ -221,6 +268,7 @@ function drawYMarks(u, marks, style) {
|
|
|
221
268
|
ctx.lineTo(right, py);
|
|
222
269
|
ctx.stroke();
|
|
223
270
|
ctx.setLineDash([]);
|
|
271
|
+
if (!m.label) continue;
|
|
224
272
|
const w = ctx.measureText(m.label).width;
|
|
225
273
|
const base = py - gap - textH < top ? py + gap + textH : py - gap;
|
|
226
274
|
let x1 = right - gap;
|
|
@@ -255,7 +303,7 @@ function nearestPoint(xs, ys, left, top) {
|
|
|
255
303
|
}
|
|
256
304
|
return best;
|
|
257
305
|
}
|
|
258
|
-
function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280, onCursor, onPick, parity, readout, hint }) {
|
|
306
|
+
function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280, onCursor, onPick, parity, readout, hint, solo }) {
|
|
259
307
|
const lang = useShellLang();
|
|
260
308
|
const theme = useThemeStore((s) => s.theme);
|
|
261
309
|
const fill = height === "fill";
|
|
@@ -273,6 +321,14 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
273
321
|
const uRef = useRef(null);
|
|
274
322
|
const hostRef = useRef(null);
|
|
275
323
|
const [cursor, setCursor] = useState(null);
|
|
324
|
+
const [soloPick, setSoloPick] = useState(null);
|
|
325
|
+
const soloFound = solo && soloPick !== null ? series.findIndex((s) => soloKey(s) === soloPick) : -1;
|
|
326
|
+
const soloIdx = soloFound >= 0 ? soloFound : null;
|
|
327
|
+
const soloRef = useRef(soloIdx);
|
|
328
|
+
soloRef.current = soloIdx;
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
if (soloPick !== null && soloIdx === null) setSoloPick(null);
|
|
331
|
+
}, [soloPick, soloIdx]);
|
|
276
332
|
const onCursorRef = useRef(onCursor);
|
|
277
333
|
onCursorRef.current = onCursor;
|
|
278
334
|
const onPickRef = useRef(onPick);
|
|
@@ -290,19 +346,15 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
290
346
|
const levels = useMemo(() => (yMarks ?? []).flatMap((m) => m.drag ? [m.drag.min, m.drag.max] : [m.y]), [yMarks]);
|
|
291
347
|
const range = useMemo(() => parity ? parityRange(xs, ...ys, levels, ext ? [...ext.x, ...ext.y] : []) : null, [parity, xs, ys, levels, ext]);
|
|
292
348
|
const yLevels = !parity && !y.range && (levels.length > 0 || ext) ? [...levels, ...ext ? ext.y : []] : null;
|
|
293
|
-
const xExt = useMemo(() =>
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const hi = Math.max(xs[xs.length - 1], ext.x[1]);
|
|
297
|
-
if (x.log && !(lo > 0)) return null;
|
|
298
|
-
return hi > lo ? [lo, hi] : x.log ? [lo / 10, hi * 10] : [lo - 1, hi + 1];
|
|
299
|
-
}, [ext, range, xs, x.log]);
|
|
349
|
+
const xExt = useMemo(() => range ? null : xScaleRange(xs, ext, x.range, Boolean(x.log)), [ext, range, xs, x.log, x.range]);
|
|
350
|
+
const xSpan = xs.length > 0 ? Math.max(Math.abs(xs[xs.length - 1] - xs[0]), x.range ? Math.abs(x.range[1] - x.range[0]) : 0) : 0;
|
|
351
|
+
const ticks = !x.time && x.ticks && x.ticks.length > 0 ? x.ticks : void 0;
|
|
300
352
|
const tiny = useMemo(
|
|
301
353
|
() => ({
|
|
302
|
-
x: Boolean(x.log) && smallestPositive(ext ? [xs, ext.x] : [xs], range) < LOG_TABLE_FLOOR,
|
|
354
|
+
x: !ticks && Boolean(x.log) && smallestPositive(ext ? [xs, ext.x] : [xs], range) < LOG_TABLE_FLOOR,
|
|
303
355
|
y: Boolean(y.log) && smallestPositive(yLevels ? [...ys, yLevels] : ys, range ?? y.range) < LOG_TABLE_FLOOR
|
|
304
356
|
}),
|
|
305
|
-
[x.log, y.log, xs, ys, range, y.range, yLevels, ext]
|
|
357
|
+
[x.log, y.log, xs, ys, range, y.range, yLevels, ext, ticks]
|
|
306
358
|
);
|
|
307
359
|
const xLabel = pick(x.label, lang);
|
|
308
360
|
const yLabel = pick(y.label, lang);
|
|
@@ -318,14 +370,14 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
318
370
|
const xUnit = x.unit ? pick(x.unit, lang) : "";
|
|
319
371
|
const yUnit = y.unit ? pick(y.unit, lang) : "";
|
|
320
372
|
const structure = JSON.stringify({
|
|
321
|
-
s: series.map((s, i) => [pick(s.label, lang), seriesStyle(s, i), s.width ?? 2, s.mode ?? "line", s.size ?? 9, isOverlay(s)]),
|
|
322
|
-
x: [xLabel, xUnit, Boolean(x.time), Boolean(x.log), x.format ?? null, tiny.x, xExt],
|
|
373
|
+
s: series.map((s, i) => [pick(s.label, lang), seriesStyle(s, i), s.width ?? 2, s.mode ?? "line", s.size ?? 9, isOverlay(s), Boolean(s.dots)]),
|
|
374
|
+
x: [xLabel, xUnit, Boolean(x.time), Boolean(x.log), x.format ?? null, tiny.x, xExt, ticks ? ticks.map((t) => [t.value, pick(t.label, lang)]) : null],
|
|
323
375
|
oe: ext,
|
|
324
376
|
p: range,
|
|
325
377
|
pick: Boolean(onPick),
|
|
326
378
|
y: [yLabel, yUnit, Boolean(y.log), y.range ?? null, y.format ?? null, tiny.y],
|
|
327
379
|
m: (marks ?? []).map((m) => [m.x, pick(m.label, lang)]),
|
|
328
|
-
ym: (yMarks ?? []).map((m) => m.drag ? ["drag", m.drag] : [m.y, pick(m.label, lang), m.tone ?? "warn"]),
|
|
380
|
+
ym: (yMarks ?? []).map((m) => m.drag ? ["drag", m.drag, Boolean(m.label)] : [m.y, m.label ? pick(m.label, lang) : null, m.tone ?? "warn"]),
|
|
329
381
|
theme,
|
|
330
382
|
lang,
|
|
331
383
|
h,
|
|
@@ -342,12 +394,24 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
342
394
|
const font = `11px ${family}`;
|
|
343
395
|
const surface = resolveToken("--color-surface", "#fff");
|
|
344
396
|
const repeats = { x: 0, y: 0 };
|
|
397
|
+
const declareTicks = (axis, labels, repeated = repeatedLabels(labels)) => {
|
|
398
|
+
repeats[axis] = repeated;
|
|
399
|
+
hostRef.current?.setAttribute("data-ticks-repeat", String(repeats.x + repeats.y));
|
|
400
|
+
hostRef.current?.setAttribute(`data-ticks-${axis}`, String(labels.filter((l) => l).length));
|
|
401
|
+
};
|
|
345
402
|
const tick = (fmt, axis, pre) => (_u, vals) => {
|
|
346
403
|
const labels = formatTicks(pre ? pre(vals) : vals, lang, fmt ?? { digits: 4 });
|
|
347
404
|
if (axis === "x" && pre) hostRef.current?.setAttribute("data-log-labels", labels.filter((l) => l).join("|"));
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
405
|
+
declareTicks(axis, labels);
|
|
406
|
+
return labels;
|
|
407
|
+
};
|
|
408
|
+
const namedTicks = (_u, vals) => {
|
|
409
|
+
const labels = vals.map((v) => v === null || v === void 0 ? "" : tickLabelAt(ticks, v, lang) ?? "");
|
|
410
|
+
hostRef.current?.setAttribute("data-x-tick-labels", labels.filter((l) => l).join("|"));
|
|
411
|
+
const dup = namedRepeats(labels);
|
|
412
|
+
if (dup.n > 0) hostRef.current?.setAttribute("data-ticks-repeated", dup.names.join("|"));
|
|
413
|
+
else hostRef.current?.removeAttribute("data-ticks-repeated");
|
|
414
|
+
declareTicks("x", labels, dup.n);
|
|
351
415
|
return labels;
|
|
352
416
|
};
|
|
353
417
|
const near = { left: NaN, top: NaN, idx: null };
|
|
@@ -401,10 +465,15 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
401
465
|
label: xUnit ? `${xLabel} (${xUnit})` : xLabel,
|
|
402
466
|
labelFont: font,
|
|
403
467
|
// a log x axis labels the decades only; the ticks between stay drawn, unlabelled
|
|
404
|
-
values: x.time ? void 0 : tick(x.format, "x", x.log && !tiny.x ? decadeOnly : void 0),
|
|
405
|
-
...
|
|
406
|
-
|
|
407
|
-
|
|
468
|
+
values: x.time ? void 0 : ticks ? namedTicks : tick(x.format, "x", x.log && !tiny.x ? decadeOnly : void 0),
|
|
469
|
+
...ticks ? (
|
|
470
|
+
// exactly the named values, no other tick
|
|
471
|
+
{ splits: (_u, _i, min, max) => tickSplits(ticks, min, max, Boolean(x.log)), filter: (_u, splits) => splits }
|
|
472
|
+
) : {
|
|
473
|
+
...xSteps ? { incrs: xSteps } : {},
|
|
474
|
+
...range ? { space: PARITY_TICK_SPACE } : {},
|
|
475
|
+
...tiny.x ? DECADE_AXIS : {}
|
|
476
|
+
}
|
|
408
477
|
},
|
|
409
478
|
{
|
|
410
479
|
stroke: fg,
|
|
@@ -434,7 +503,8 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
434
503
|
...baseEntries.map(({ s, i }) => {
|
|
435
504
|
const style = seriesStyle(s, i);
|
|
436
505
|
const stroke = resolveToken(style.color, "#4a8");
|
|
437
|
-
|
|
506
|
+
const dim = soloStyle(soloRef.current, i, s.mode === "points" ? 1.5 : s.width ?? 2);
|
|
507
|
+
return s.mode === "points" ? { label: pick(s.label, lang), stroke, width: dim.width, alpha: dim.alpha, paths: () => null, points: { show: true, space: 0, size: s.size ?? 9, fill: stroke } } : { label: pick(s.label, lang), stroke, width: dim.width, alpha: dim.alpha, dash: style.dash, spanGaps: false, points: s.dots ? { show: true, size: 5, fill: stroke } : { show: false } };
|
|
438
508
|
})
|
|
439
509
|
],
|
|
440
510
|
hooks: {
|
|
@@ -529,6 +599,7 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
529
599
|
ctx.rect(u.bbox.left, u.bbox.top, u.bbox.width, u.bbox.height);
|
|
530
600
|
ctx.clip();
|
|
531
601
|
for (const { s, i } of dots) {
|
|
602
|
+
ctx.globalAlpha = soloStyle(soloRef.current, i, 1).alpha;
|
|
532
603
|
ctx.fillStyle = resolveToken(seriesStyle(s, i).color, "#4a8");
|
|
533
604
|
ctx.strokeStyle = surface;
|
|
534
605
|
ctx.lineWidth = Math.max(1, pr);
|
|
@@ -552,7 +623,7 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
552
623
|
}
|
|
553
624
|
const markStyle = { color: resolveToken("--color-warn", "#c80"), halo: surface, family };
|
|
554
625
|
const lines = yMarksRef.current ?? [];
|
|
555
|
-
if (lines.length) drawYMarks(u, lines.map((m, i) => ({ y: liveRef.current[i] ?? m.y, label: pick(m.label, lang), color: resolveToken(YMARK_TONE_TOKENS[m.tone ?? "warn"], "#c80") })), markStyle);
|
|
626
|
+
if (lines.length) drawYMarks(u, lines.map((m, i) => ({ y: liveRef.current[i] ?? m.y, label: m.label ? pick(m.label, lang) : void 0, color: resolveToken(YMARK_TONE_TOKENS[m.tone ?? "warn"], "#c80") })), markStyle);
|
|
556
627
|
u.over.querySelectorAll("[data-y-handle]").forEach((el2) => {
|
|
557
628
|
const i = Number(el2.getAttribute("data-y-handle"));
|
|
558
629
|
const m = lines[i];
|
|
@@ -561,16 +632,22 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
561
632
|
const top = u.valToPos(v, "y");
|
|
562
633
|
el2.style.display = Number.isFinite(top) && top >= 0 && top <= u.bbox.height / (uPlot.pxRatio || 1) ? "" : "none";
|
|
563
634
|
el2.style.top = `${top - HANDLE_HEIGHT / 2}px`;
|
|
564
|
-
const label = pick(m.label, lang);
|
|
565
|
-
|
|
635
|
+
const label = m.label ? pick(m.label, lang) : "";
|
|
636
|
+
const shown = `${formatNumber(v, lang, y.format ?? { digits: 4 })}${yUnit ? `${NBSP}${yUnit}` : ""}`;
|
|
637
|
+
const unnamed = lines.flatMap((one, k) => one.drag && !one.label ? [k] : []);
|
|
638
|
+
el2.setAttribute("aria-label", label || referenceLineName(lang, unnamed.indexOf(i) + 1, unnamed.length));
|
|
566
639
|
el2.setAttribute("aria-valuenow", String(Number(v.toPrecision(12))));
|
|
567
|
-
el2.setAttribute("aria-valuetext",
|
|
640
|
+
el2.setAttribute("aria-valuetext", label ? `${label}: ${shown}` : shown);
|
|
568
641
|
});
|
|
569
642
|
if (marks?.length) drawMarks(u, marks.map((m) => ({ x: m.x, label: pick(m.label, lang) })), markStyle);
|
|
570
643
|
}
|
|
571
644
|
]
|
|
572
645
|
}
|
|
573
646
|
};
|
|
647
|
+
if (!ticks) {
|
|
648
|
+
hostRef.current?.removeAttribute("data-x-tick-labels");
|
|
649
|
+
hostRef.current?.removeAttribute("data-ticks-repeated");
|
|
650
|
+
}
|
|
574
651
|
uRef.current?.destroy();
|
|
575
652
|
uRef.current = new uPlot(opts, data, el);
|
|
576
653
|
return () => {
|
|
@@ -582,12 +659,25 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
582
659
|
uRef.current?.setData(data);
|
|
583
660
|
}, [data]);
|
|
584
661
|
const overlaysKey = JSON.stringify(overlays.map(({ s, i }) => [i, s.x, s.values, s.size ?? 9, seriesStyle(s, i).color]));
|
|
585
|
-
const linesKey = JSON.stringify((yMarks ?? []).map((m) => [m.y, pick(m.label, lang), m.tone ?? "warn"]));
|
|
662
|
+
const linesKey = JSON.stringify((yMarks ?? []).map((m) => [m.y, m.label ? pick(m.label, lang) : null, m.tone ?? "warn"]));
|
|
586
663
|
useEffect(() => {
|
|
587
664
|
uRef.current?.redraw(false);
|
|
588
665
|
}, [linesKey, overlaysKey]);
|
|
666
|
+
useEffect(() => {
|
|
667
|
+
const u = uRef.current;
|
|
668
|
+
if (!u) return;
|
|
669
|
+
baseEntries.forEach(({ s, i }, k) => {
|
|
670
|
+
const dim = soloStyle(soloIdx, i, s.mode === "points" ? 1.5 : s.width ?? 2);
|
|
671
|
+
const one = u.series[k + 1];
|
|
672
|
+
if (!one) return;
|
|
673
|
+
one.alpha = dim.alpha;
|
|
674
|
+
one.width = dim.width;
|
|
675
|
+
});
|
|
676
|
+
u.redraw(false);
|
|
677
|
+
}, [soloIdx, baseEntries]);
|
|
589
678
|
const read = cursor !== null && readout ? readout(order ? order[cursor] : cursor) : cursor !== null ? [
|
|
590
|
-
|
|
679
|
+
// an x that sits on a named tick is named by it, not by its number
|
|
680
|
+
tickLabelAt(ticks, xs[cursor], lang, xSpan) !== null ? `${xLabel} ${tickLabelAt(ticks, xs[cursor], lang, xSpan)}` : `${xLabel} ${formatNumber(xs[cursor], lang, x.format ?? { digits: 4 })}${xUnit ? `${NBSP}${xUnit}` : ""}`,
|
|
591
681
|
...baseEntries.map(({ s }, k) => ({ s, v: ys[k][cursor] ?? null })).filter(({ v }) => !scatter || v !== null).map(({ s, v }) => `${pick(s.label, lang)} ${formatNumber(v, lang, y.format ?? { digits: 4 })}${yUnit ? `${NBSP}${yUnit}` : ""}`)
|
|
592
682
|
].join(" \xB7 ") : hint ? pick(hint, lang) : lang === "es" ? "Pase el cursor sobre el gr\xE1fico para leer los valores" : "Hover the chart to read the values";
|
|
593
683
|
return /* @__PURE__ */ jsxs(
|
|
@@ -606,16 +696,20 @@ function UPlotChart({ x, y, series, marks, yMarks, onYMarkChange, height = 280,
|
|
|
606
696
|
"data-y-marks": yMarks?.length ? String(yMarks.length) : void 0,
|
|
607
697
|
"data-y-drag": dragCount ? String(dragCount) : void 0,
|
|
608
698
|
"data-overlay": overlays.length ? String(overlays.length) : void 0,
|
|
699
|
+
"data-solo": soloIdx !== null ? String(soloIdx) : void 0,
|
|
609
700
|
children: [
|
|
610
701
|
/* @__PURE__ */ jsx("div", { ref: setPlot, className: "caos-chart-plot" }),
|
|
611
|
-
series.length > 1 && /* @__PURE__ */ jsx("ul", { className: "caos-chart-legend", "aria-label": lang === "es" ? "Series del gr\xE1fico" : "Series of the chart", children: series.map((s, i) => /* @__PURE__ */
|
|
702
|
+
(series.length > 1 || solo) && /* @__PURE__ */ jsx("ul", { className: "caos-chart-legend", "aria-label": lang === "es" ? "Series del gr\xE1fico" : "Series of the chart", children: series.map((s, i) => /* @__PURE__ */ jsx("li", { className: "caos-chart-key", "data-mode": s.mode ?? "line", "data-dash": seriesStyle(s, i).dash ? "1" : void 0, children: solo ? /* @__PURE__ */ jsxs("button", { type: "button", className: "caos-chart-key-button", "aria-pressed": soloIdx === i, onClick: () => setSoloPick(soloIdx === i ? null : soloKey(s)), children: [
|
|
703
|
+
/* @__PURE__ */ jsx("span", { className: "caos-chart-swatch", style: { "--swatch": `var(${seriesStyle(s, i).color})` }, "aria-hidden": "true" }),
|
|
704
|
+
pick(s.label, lang)
|
|
705
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
612
706
|
/* @__PURE__ */ jsx("span", { className: "caos-chart-swatch", style: { "--swatch": `var(${seriesStyle(s, i).color})` }, "aria-hidden": "true" }),
|
|
613
707
|
pick(s.label, lang)
|
|
614
|
-
] }, i)) }),
|
|
708
|
+
] }) }, i)) }),
|
|
615
709
|
/* @__PURE__ */ jsx("p", { className: "caos-chart-readout", "aria-live": "polite", title: read, children: read })
|
|
616
710
|
]
|
|
617
711
|
}
|
|
618
712
|
);
|
|
619
713
|
}
|
|
620
714
|
|
|
621
|
-
export { LOG_TABLE_FLOOR, UPlotChart, YMARK_TONE_TOKENS, clampMark, decadeOnly, drawMarks, drawYMarks, logDecades, nearestPoint, nudgeMark, overlayExtent, parityBox, parityRange, rangeWithLevels, repeatedLabels, seriesStyle, smallestPositive, sortOrder, tickSteps };
|
|
715
|
+
export { LOG_TABLE_FLOOR, SOLO_DIM_ALPHA, UPlotChart, YMARK_TONE_TOKENS, clampMark, decadeOnly, drawMarks, drawYMarks, logDecades, namedRepeats, nearestPoint, nudgeMark, overlayExtent, parityBox, parityRange, rangeWithLevels, repeatedLabels, seriesStyle, smallestPositive, soloKey, soloStyle, sortOrder, tickLabelAt, tickSplits, tickSteps, xScaleRange };
|
|
@@ -214,4 +214,76 @@ function Stage({ label, children, className }) {
|
|
|
214
214
|
);
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
|
|
217
|
+
// src/chart/text.ts
|
|
218
|
+
function referenceLineName(lang, n, of) {
|
|
219
|
+
const base = lang === "es" ? "L\xEDnea de referencia" : "Reference line";
|
|
220
|
+
return of > 1 ? `${base} ${n}` : base;
|
|
221
|
+
}
|
|
222
|
+
var context;
|
|
223
|
+
function fontFamily() {
|
|
224
|
+
if (typeof document === "undefined") return "sans-serif";
|
|
225
|
+
return getComputedStyle(document.documentElement).getPropertyValue("--font-sans").trim() || "sans-serif";
|
|
226
|
+
}
|
|
227
|
+
function textWidth(text, px, weight = 400) {
|
|
228
|
+
if (context === void 0) {
|
|
229
|
+
try {
|
|
230
|
+
context = typeof document === "undefined" ? null : document.createElement("canvas").getContext("2d");
|
|
231
|
+
} catch {
|
|
232
|
+
context = null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (!context) return text.length * px * 0.62;
|
|
236
|
+
context.font = `${weight} ${px}px ${fontFamily()}`;
|
|
237
|
+
return context.measureText(text).width;
|
|
238
|
+
}
|
|
239
|
+
function widestLabel(labels, px, weight = 400) {
|
|
240
|
+
return Math.max(0, ...labels.map((label) => textWidth(label, px, weight)));
|
|
241
|
+
}
|
|
242
|
+
function shorten(line, width, px) {
|
|
243
|
+
if (textWidth(line, px) <= width) return line;
|
|
244
|
+
let cut = line;
|
|
245
|
+
while (cut.length > 1 && textWidth(`${cut}\u2026`, px) > width) cut = cut.slice(0, -1);
|
|
246
|
+
return `${cut.trimEnd()}\u2026`;
|
|
247
|
+
}
|
|
248
|
+
function fitLabel(label, width, px, maxLines = 2) {
|
|
249
|
+
if (textWidth(label, px) <= width) return { lines: [label], shortened: false };
|
|
250
|
+
const words = label.split(" ");
|
|
251
|
+
if (maxLines === 2 && words.length > 1) {
|
|
252
|
+
let best = null;
|
|
253
|
+
let bestWidth = Infinity;
|
|
254
|
+
for (let k = 1; k < words.length; k += 1) {
|
|
255
|
+
const first = words.slice(0, k).join(" ");
|
|
256
|
+
const second = words.slice(k).join(" ");
|
|
257
|
+
const widest = Math.max(textWidth(first, px), textWidth(second, px));
|
|
258
|
+
if (widest < bestWidth) {
|
|
259
|
+
bestWidth = widest;
|
|
260
|
+
best = [first, second];
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (best && bestWidth <= width) return { lines: best, shortened: false };
|
|
264
|
+
if (best) return { lines: [shorten(best[0], width, px), shorten(best[1], width, px)], shortened: true };
|
|
265
|
+
}
|
|
266
|
+
return { lines: [shorten(label, width, px)], shortened: true };
|
|
267
|
+
}
|
|
268
|
+
function niceStep(x) {
|
|
269
|
+
if (!(x > 0) || !Number.isFinite(x)) return 1;
|
|
270
|
+
const magnitude = 10 ** Math.floor(Math.log10(x));
|
|
271
|
+
return ([1, 2, 2.5, 5, 10].find((m) => m * magnitude >= x * (1 - 1e-12)) ?? 10) * magnitude;
|
|
272
|
+
}
|
|
273
|
+
function niceTicks(lo, hi, room, labelSize, most = 6) {
|
|
274
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi)) return [0];
|
|
275
|
+
if (hi < lo) [lo, hi] = [hi, lo];
|
|
276
|
+
if (hi === lo) hi = lo === 0 ? 1 : lo + Math.abs(lo);
|
|
277
|
+
const count = Math.max(2, Math.min(most, Math.floor(room / (labelSize + 16)) + 1));
|
|
278
|
+
const step = niceStep((hi - lo) / (count - 1));
|
|
279
|
+
const first = Math.floor(lo / step + 1e-9) * step;
|
|
280
|
+
const ticks = [];
|
|
281
|
+
for (let k = 0; first + k * step <= hi + step * 1e-9 || ticks.length < 2; k += 1) {
|
|
282
|
+
ticks.push(Number((first + k * step).toPrecision(12)));
|
|
283
|
+
if (ticks.length > 50) break;
|
|
284
|
+
}
|
|
285
|
+
if (ticks[ticks.length - 1] < hi - step * 1e-9) ticks.push(Number((ticks[ticks.length - 1] + step).toPrecision(12)));
|
|
286
|
+
return ticks;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export { NBSP, NOT_AVAILABLE, SCIENTIFIC_BELOW, SHELL_TOKENS, Stage, applyTheme, fitLabel, fontFamily, formatNumber, formatTicks, niceStep, niceTicks, pick, readTheme, referenceLineName, resolveToken, textWidth, useFormat, useLangStore, useShellLang, useStageSize, useThemeStore, useThemeTokens, widestLabel };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export { A as APP_ROUTE, a as AppShell, b as ArchTab, c as ArchitectureConfig, d
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, Component, ErrorInfo } from 'react';
|
|
4
4
|
import * as zustand from 'zustand';
|
|
5
|
-
import { F as FormatOptions } from './
|
|
6
|
-
export { N as NBSP,
|
|
5
|
+
import { F as FormatOptions } from './text-DyQ1A8oo.js';
|
|
6
|
+
export { a as FittedLabel, N as NBSP, b as NOT_AVAILABLE, c as SCIENTIFIC_BELOW, d as SHELL_TOKENS, S as ShellColorToken, e as ShellToken, f as fitLabel, g as fontFamily, h as formatNumber, i as formatTicks, n as niceStep, j as niceTicks, k as resolveToken, t as textWidth, u as useFormat, l as useThemeTokens, w as widestLabel } from './text-DyQ1A8oo.js';
|
|
7
7
|
import { L as Lang, B as BiText } from './text-BlY47nIt.js';
|
|
8
8
|
export { p as pick, u as useLangStore, a as useShellLang } from './text-BlY47nIt.js';
|
|
9
9
|
|
|
@@ -1118,40 +1118,6 @@ interface BarChartProps {
|
|
|
1118
1118
|
*/
|
|
1119
1119
|
declare function BarChart({ title, data, axis, orientation, values, height, onSelect }: BarChartProps): react.JSX.Element;
|
|
1120
1120
|
|
|
1121
|
-
/**
|
|
1122
|
-
* Text that fits the drawing it labels, measured in the font the page renders.
|
|
1123
|
-
*
|
|
1124
|
-
* Products drew their axes and labels with fixed margins and a fixed width per character. The Linux fonts (DejaVu
|
|
1125
|
-
* Sans) are wider than the Windows ones and Spanish labels are longer than English ones, so a column sized for one
|
|
1126
|
-
* ran its labels out of the drawing in the other (CAOS_Fragmenta 0.05.000: "Tamaño medio clásico, limitado al bloque
|
|
1127
|
-
* in situ" read "dio clásico, limitado al bloque in situ"; its deploy gate failed on Linux). Here a label is measured
|
|
1128
|
-
* with the canvas text metrics of the page's own font (`--font-sans`, which the gate's wide-font pass replaces),
|
|
1129
|
-
* broken over two lines at a word when it does not fit, and only then shortened with an ellipsis, so the drawing can
|
|
1130
|
-
* give the whole label as its title. Ported from CAOS_Fragmenta `viz/text.ts` (0.07.000).
|
|
1131
|
-
*/
|
|
1132
|
-
/** The page's sans-serif stack as the shell token resolves it. */
|
|
1133
|
-
declare function fontFamily(): string;
|
|
1134
|
-
/** The width of one line of text at a font size, in CSS pixels; outside a browser, an estimate on the wide side. */
|
|
1135
|
-
declare function textWidth(text: string, px: number, weight?: number): number;
|
|
1136
|
-
/** The widest a set of labels needs, each on one line. */
|
|
1137
|
-
declare function widestLabel(labels: readonly string[], px: number, weight?: number): number;
|
|
1138
|
-
interface FittedLabel {
|
|
1139
|
-
/** One or two lines; the last is shortened with an ellipsis only when the lines allowed are not enough. */
|
|
1140
|
-
lines: string[];
|
|
1141
|
-
/** Whether the label was shortened, so the drawing gives the whole label as its title. */
|
|
1142
|
-
shortened: boolean;
|
|
1143
|
-
}
|
|
1144
|
-
/** A label in at most `maxLines` lines of `width` pixels: whole when it fits, broken at a word, shortened last. */
|
|
1145
|
-
declare function fitLabel(label: string, width: number, px: number, maxLines?: 1 | 2): FittedLabel;
|
|
1146
|
-
/** The 1, 2, 2.5 or 5 times a power of ten at or above `x`. */
|
|
1147
|
-
declare function niceStep(x: number): number;
|
|
1148
|
-
/**
|
|
1149
|
-
* Round ticks covering [lo, hi], as many as leave room for labels about `labelSize` pixels along an axis of `room`
|
|
1150
|
-
* pixels (at least two, at most `most`). The first tick is at or below `lo` and the last at or above `hi`, so a bar
|
|
1151
|
-
* or a point never runs past the last labelled value.
|
|
1152
|
-
*/
|
|
1153
|
-
declare function niceTicks(lo: number, hi: number, room: number, labelSize: number, most?: number): number[];
|
|
1154
|
-
|
|
1155
1121
|
/** One section of the control rail. A rail whose content does not fit is SPLIT into sections, one shown at a
|
|
1156
1122
|
* time, never scrolled (ADR-0071 rule 6: a panel must show its own controls). */
|
|
1157
1123
|
interface RailSection {
|
|
@@ -1380,4 +1346,4 @@ interface ViewsRowProps {
|
|
|
1380
1346
|
*/
|
|
1381
1347
|
declare function ViewsRow({ children, shares }: ViewsRowProps): react.JSX.Element;
|
|
1382
1348
|
|
|
1383
|
-
export { BREAKPOINTS, BarChart, type BarChartProps, type BarDatum, BiText, Callout, CardDeck, type CardDeckProps, type CaseDef, type CaseFocusConfig, type CaseGroup, type CaseKind, CaseSelector, type CaseSelectorProps, type CaseSelectorText, CaseWorkbench, type CaseWorkbenchProps, ChipGroup, type ChipGroupProps, type ChipOption, type Citation, CitationsProvider, Cite, DECK_TEXT, DOC_AREAS, type DeckCard, DocPage, type DocPageProps, DocReferences, DocRefsScope, DocSection, type DocSectionProps, EXECUTIVE_SCHEMA_VERSION, Equation, type ExecutiveData, type ExecutiveProblem, ExecutiveView, type ExecutiveViewProps, FLIP_LIMITS, FLIP_TEXT, FOCUS_PARAM, FOCUS_TEXT, FOUR_CS, Figure,
|
|
1349
|
+
export { BREAKPOINTS, BarChart, type BarChartProps, type BarDatum, BiText, Callout, CardDeck, type CardDeckProps, type CaseDef, type CaseFocusConfig, type CaseGroup, type CaseKind, CaseSelector, type CaseSelectorProps, type CaseSelectorText, CaseWorkbench, type CaseWorkbenchProps, ChipGroup, type ChipGroupProps, type ChipOption, type Citation, CitationsProvider, Cite, DECK_TEXT, DOC_AREAS, type DeckCard, DocPage, type DocPageProps, DocReferences, DocRefsScope, DocSection, type DocSectionProps, EXECUTIVE_SCHEMA_VERSION, Equation, type ExecutiveData, type ExecutiveProblem, ExecutiveView, type ExecutiveViewProps, FLIP_LIMITS, FLIP_TEXT, FOCUS_PARAM, FOCUS_TEXT, FOUR_CS, Figure, FlipCard, type FlipCardProps, type FocusMode, type FocusModeConfig, type FocusModeOptions, FocusShell, type FocusShellProps, FormatOptions, Gauge, type GaugeProps, type GaugeZone, Glossary, type GlossaryEntry, InlineMath, Knob, type KnobProps, Landing, type Lane, LaneBadge, Lang, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, type PausedVizController, PlotCard, type PlotCardProps, type Provenance, Question, type QuestionProps, type RailSection, Readout, type ReadoutItem, type ReadoutProps, ReferenceList, Refs, Stage, type StageSize, Stat, type StatProps, type SubTabDef, SubTabs, type SubTabsProps, type SurfaceFocusConfig, SurfacePage, type SurfacePageProps, type TabDef, type TabGroupDef, TabGroups, type TabGroupsProps, Tabs, type TabsProps, type Theme, ThemeToggle, type Tone, type UsePausedVizOptions, VariantBar, type VariantBarProps, type VariantDef, Verdict, type VerdictProps, type ViewFocusConfig, ViewsRow, type ViewsRowProps, type VizFrame, type VizLoop, type VizLoopDeps, type VizLoopOptions, type WorkbenchGroup, WorkbenchLayout, type WorkbenchLayoutProps, type WorkbenchRoute, WorkbenchShell, type WorkbenchShellProps, type WorkbenchState, WorkbenchStateContext, applyTheme, caseKind, caseTooltip, casesInSource, createVizLoop, deckPosition, deckWindow, firstAppearance, groupByCategory, isStale, makeStateKey, perPageFor, readCaseParam, readTheme, removeQueryParam, replaceQueryParam, sourcesPresent, useFocusMode, usePausedViz, useStageSize, useThemeStore, useUrlView, useWorkbenchState, validateExecutive, viewParamOf, withCaseParam };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useThemeStore, useShellLang, useLangStore, SHELL_TOKENS, pick, useStageSize, NOT_AVAILABLE, formatTicks, formatNumber, NBSP } from './chunk-
|
|
2
|
-
export { NBSP, NOT_AVAILABLE, SCIENTIFIC_BELOW, SHELL_TOKENS, Stage, applyTheme, formatNumber, formatTicks, pick, readTheme, resolveToken, useFormat, useLangStore, useShellLang, useStageSize, useThemeStore, useThemeTokens } from './chunk-
|
|
1
|
+
import { useThemeStore, useShellLang, useLangStore, SHELL_TOKENS, pick, useStageSize, NOT_AVAILABLE, widestLabel, fitLabel, formatTicks, niceTicks, textWidth, formatNumber, NBSP } from './chunk-DBCMAL2G.js';
|
|
2
|
+
export { NBSP, NOT_AVAILABLE, SCIENTIFIC_BELOW, SHELL_TOKENS, Stage, applyTheme, fitLabel, fontFamily, formatNumber, formatTicks, niceStep, niceTicks, pick, readTheme, resolveToken, textWidth, useFormat, useLangStore, useShellLang, useStageSize, useThemeStore, useThemeTokens, widestLabel } from './chunk-DBCMAL2G.js';
|
|
3
3
|
import { APP_ROUTE, LANDING_ROUTE } from './chunk-33WTUQ7Q.js';
|
|
4
4
|
export { APP_ROUTE, LANDING_ROUTE, LANG_STORAGE_KEY, STANDARD_ROUTES, THEME_BOOT_SCRIPT, THEME_STORAGE_KEY } from './chunk-33WTUQ7Q.js';
|
|
5
5
|
import { createContext, Component, useState, useRef, useId, useEffect, useLayoutEffect, useCallback, useContext, useMemo, Children, isValidElement } from 'react';
|
|
@@ -2092,7 +2092,7 @@ function executiveTextFields(d) {
|
|
|
2092
2092
|
add("title", d.title, 1);
|
|
2093
2093
|
add("key_statement", d.key_statement, 2);
|
|
2094
2094
|
d.headline_figures.forEach((f, i) => figure(`headline_figures[${i}]`, f));
|
|
2095
|
-
const { pain, context
|
|
2095
|
+
const { pain, context, situation, trends, proposal } = d;
|
|
2096
2096
|
add("pain.key_message", pain.key_message, 1);
|
|
2097
2097
|
pain.paragraphs.forEach((p, i) => add(`pain.paragraphs[${i}]`, p, void 0, EXEC_LIMITS.minParagraphWords));
|
|
2098
2098
|
pain.bearers.forEach((b, i) => {
|
|
@@ -2102,11 +2102,11 @@ function executiveTextFields(d) {
|
|
|
2102
2102
|
});
|
|
2103
2103
|
pain.figures.forEach((f, i) => figure(`pain.figures[${i}]`, f));
|
|
2104
2104
|
pain.causes.forEach((c, i) => add(`pain.causes[${i}].cause`, c.cause));
|
|
2105
|
-
add("context.key_message",
|
|
2106
|
-
|
|
2107
|
-
add("context.setting",
|
|
2108
|
-
|
|
2109
|
-
|
|
2105
|
+
add("context.key_message", context.key_message, 1);
|
|
2106
|
+
context.paragraphs.forEach((p, i) => add(`context.paragraphs[${i}]`, p, void 0, EXEC_LIMITS.minParagraphWords));
|
|
2107
|
+
add("context.setting", context.setting);
|
|
2108
|
+
context.forces.forEach((f, i) => add(`context.forces[${i}].force`, f.force));
|
|
2109
|
+
context.evidence.forEach((e, i) => add(`context.evidence[${i}].statement`, e.statement, 1));
|
|
2110
2110
|
add("situation.key_message", situation.key_message, 1);
|
|
2111
2111
|
situation.roles.forEach((r, i) => {
|
|
2112
2112
|
add(`situation.roles[${i}].role`, r.role);
|
|
@@ -3133,74 +3133,6 @@ var BREAKPOINTS = {
|
|
|
3133
3133
|
/** The gate's large screen: the viewport rules of ADR-0071 are measured from here up. */
|
|
3134
3134
|
large: 1280
|
|
3135
3135
|
};
|
|
3136
|
-
|
|
3137
|
-
// src/chart/text.ts
|
|
3138
|
-
var context;
|
|
3139
|
-
function fontFamily() {
|
|
3140
|
-
if (typeof document === "undefined") return "sans-serif";
|
|
3141
|
-
return getComputedStyle(document.documentElement).getPropertyValue("--font-sans").trim() || "sans-serif";
|
|
3142
|
-
}
|
|
3143
|
-
function textWidth(text, px, weight = 400) {
|
|
3144
|
-
if (context === void 0) {
|
|
3145
|
-
try {
|
|
3146
|
-
context = typeof document === "undefined" ? null : document.createElement("canvas").getContext("2d");
|
|
3147
|
-
} catch {
|
|
3148
|
-
context = null;
|
|
3149
|
-
}
|
|
3150
|
-
}
|
|
3151
|
-
if (!context) return text.length * px * 0.62;
|
|
3152
|
-
context.font = `${weight} ${px}px ${fontFamily()}`;
|
|
3153
|
-
return context.measureText(text).width;
|
|
3154
|
-
}
|
|
3155
|
-
function widestLabel(labels, px, weight = 400) {
|
|
3156
|
-
return Math.max(0, ...labels.map((label) => textWidth(label, px, weight)));
|
|
3157
|
-
}
|
|
3158
|
-
function shorten(line, width, px) {
|
|
3159
|
-
if (textWidth(line, px) <= width) return line;
|
|
3160
|
-
let cut = line;
|
|
3161
|
-
while (cut.length > 1 && textWidth(`${cut}\u2026`, px) > width) cut = cut.slice(0, -1);
|
|
3162
|
-
return `${cut.trimEnd()}\u2026`;
|
|
3163
|
-
}
|
|
3164
|
-
function fitLabel(label, width, px, maxLines = 2) {
|
|
3165
|
-
if (textWidth(label, px) <= width) return { lines: [label], shortened: false };
|
|
3166
|
-
const words = label.split(" ");
|
|
3167
|
-
if (maxLines === 2 && words.length > 1) {
|
|
3168
|
-
let best = null;
|
|
3169
|
-
let bestWidth = Infinity;
|
|
3170
|
-
for (let k = 1; k < words.length; k += 1) {
|
|
3171
|
-
const first = words.slice(0, k).join(" ");
|
|
3172
|
-
const second = words.slice(k).join(" ");
|
|
3173
|
-
const widest = Math.max(textWidth(first, px), textWidth(second, px));
|
|
3174
|
-
if (widest < bestWidth) {
|
|
3175
|
-
bestWidth = widest;
|
|
3176
|
-
best = [first, second];
|
|
3177
|
-
}
|
|
3178
|
-
}
|
|
3179
|
-
if (best && bestWidth <= width) return { lines: best, shortened: false };
|
|
3180
|
-
if (best) return { lines: [shorten(best[0], width, px), shorten(best[1], width, px)], shortened: true };
|
|
3181
|
-
}
|
|
3182
|
-
return { lines: [shorten(label, width, px)], shortened: true };
|
|
3183
|
-
}
|
|
3184
|
-
function niceStep(x) {
|
|
3185
|
-
if (!(x > 0) || !Number.isFinite(x)) return 1;
|
|
3186
|
-
const magnitude = 10 ** Math.floor(Math.log10(x));
|
|
3187
|
-
return ([1, 2, 2.5, 5, 10].find((m) => m * magnitude >= x * (1 - 1e-12)) ?? 10) * magnitude;
|
|
3188
|
-
}
|
|
3189
|
-
function niceTicks(lo, hi, room, labelSize, most = 6) {
|
|
3190
|
-
if (!Number.isFinite(lo) || !Number.isFinite(hi)) return [0];
|
|
3191
|
-
if (hi < lo) [lo, hi] = [hi, lo];
|
|
3192
|
-
if (hi === lo) hi = lo === 0 ? 1 : lo + Math.abs(lo);
|
|
3193
|
-
const count = Math.max(2, Math.min(most, Math.floor(room / (labelSize + 16)) + 1));
|
|
3194
|
-
const step = niceStep((hi - lo) / (count - 1));
|
|
3195
|
-
const first = Math.floor(lo / step + 1e-9) * step;
|
|
3196
|
-
const ticks = [];
|
|
3197
|
-
for (let k = 0; first + k * step <= hi + step * 1e-9 || ticks.length < 2; k += 1) {
|
|
3198
|
-
ticks.push(Number((first + k * step).toPrecision(12)));
|
|
3199
|
-
if (ticks.length > 50) break;
|
|
3200
|
-
}
|
|
3201
|
-
if (ticks[ticks.length - 1] < hi - step * 1e-9) ticks.push(Number((ticks[ticks.length - 1] + step).toPrecision(12)));
|
|
3202
|
-
return ticks;
|
|
3203
|
-
}
|
|
3204
3136
|
var PX = 11;
|
|
3205
3137
|
var LINE = 13;
|
|
3206
3138
|
var TONE = {
|
|
@@ -3489,7 +3421,7 @@ function panel(id, lane, provenance, content) {
|
|
|
3489
3421
|
return /* @__PURE__ */ jsx("div", { className: "caos-cw-panel", "data-group": id, "data-lane": lane, "data-provenance": provenance, children: content });
|
|
3490
3422
|
}
|
|
3491
3423
|
function CaseWorkbench(props) {
|
|
3492
|
-
const { caseId, cases, source, controls, replayOnly, variants, rail, railLabel, groups, compare, context
|
|
3424
|
+
const { caseId, cases, source, controls, replayOnly, variants, rail, railLabel, groups, compare, context, group, onGroupChange, deepLinkView = true, ariaLabel, focus } = props;
|
|
3493
3425
|
const lang = useShellLang();
|
|
3494
3426
|
const focusCfg = focus === true ? {} : focus || null;
|
|
3495
3427
|
const { show: showFocus, setFocus, enterRef, memory } = useFocusMode(focusCfg);
|
|
@@ -3509,8 +3441,8 @@ function CaseWorkbench(props) {
|
|
|
3509
3441
|
}
|
|
3510
3442
|
tabs.push({
|
|
3511
3443
|
id: "context",
|
|
3512
|
-
label: pick(
|
|
3513
|
-
content: /* @__PURE__ */ jsx("div", { className: "prose caos-cw-context", children:
|
|
3444
|
+
label: pick(context.label ?? { en: "Context", es: "Contexto" }, lang),
|
|
3445
|
+
content: /* @__PURE__ */ jsx("div", { className: "prose caos-cw-context", children: context.content })
|
|
3514
3446
|
});
|
|
3515
3447
|
if (tabs.length > MAX_WORKBENCH_GROUPS) {
|
|
3516
3448
|
throw new Error(
|
|
@@ -3778,4 +3710,4 @@ function ViewsRow({ children, shares }) {
|
|
|
3778
3710
|
}) });
|
|
3779
3711
|
}
|
|
3780
3712
|
|
|
3781
|
-
export { AppShell, ArchitectureModal, BREAKPOINTS, BarChart, Callout, CardDeck, CaseSelector, CaseWorkbench, ChipGroup, CitationsProvider, Cite, DECK_TEXT, DOC_AREAS, DocPage, DocReferences, DocRefsScope, DocSection, EXECUTIVE_SCHEMA_VERSION, Equation, ExecutiveView, FLIP_LIMITS, FLIP_TEXT, FOCUS_PARAM, FOCUS_TEXT, FOUR_CS, Figure, FlipCard, FocusShell, Gauge, Glossary, InlineMath, Knob, Landing, LaneBadge, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, PlotCard, Question, Readout, ReferenceList, Refs, Stat, SubTabs, SurfacePage, TabGroups, Tabs, ThemeToggle, VariantBar, Verdict, ViewsRow, WorkbenchLayout, WorkbenchShell, WorkbenchStateContext, caseKind, caseTooltip, casesInSource, createVizLoop, deckPosition, deckWindow, firstAppearance,
|
|
3713
|
+
export { AppShell, ArchitectureModal, BREAKPOINTS, BarChart, Callout, CardDeck, CaseSelector, CaseWorkbench, ChipGroup, CitationsProvider, Cite, DECK_TEXT, DOC_AREAS, DocPage, DocReferences, DocRefsScope, DocSection, EXECUTIVE_SCHEMA_VERSION, Equation, ExecutiveView, FLIP_LIMITS, FLIP_TEXT, FOCUS_PARAM, FOCUS_TEXT, FOUR_CS, Figure, FlipCard, FocusShell, Gauge, Glossary, InlineMath, Knob, Landing, LaneBadge, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, PlotCard, Question, Readout, ReferenceList, Refs, Stat, SubTabs, SurfacePage, TabGroups, Tabs, ThemeToggle, VariantBar, Verdict, ViewsRow, WorkbenchLayout, WorkbenchShell, WorkbenchStateContext, caseKind, caseTooltip, casesInSource, createVizLoop, deckPosition, deckWindow, firstAppearance, groupByCategory, isStale, makeStateKey, perPageFor, readCaseParam, removeQueryParam, replaceQueryParam, sourcesPresent, useFocusMode, usePausedViz, useUrlView, useWorkbenchState, validateArchitectureConfig, validateExecutive, viewParamOf, withCaseParam };
|
|
@@ -58,4 +58,42 @@ declare function resolveToken(token: string, fallback?: string): string;
|
|
|
58
58
|
*/
|
|
59
59
|
declare function useThemeTokens(): Record<ShellToken, string>;
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Text that fits the drawing it labels, measured in the font the page renders.
|
|
63
|
+
*
|
|
64
|
+
* Products drew their axes and labels with fixed margins and a fixed width per character. The Linux fonts (DejaVu
|
|
65
|
+
* Sans) are wider than the Windows ones and Spanish labels are longer than English ones, so a column sized for one
|
|
66
|
+
* ran its labels out of the drawing in the other (CAOS_Fragmenta 0.05.000: "Tamaño medio clásico, limitado al bloque
|
|
67
|
+
* in situ" read "dio clásico, limitado al bloque in situ"; its deploy gate failed on Linux). Here a label is measured
|
|
68
|
+
* with the canvas text metrics of the page's own font (`--font-sans`, which the gate's wide-font pass replaces),
|
|
69
|
+
* broken over two lines at a word when it does not fit, and only then shortened with an ellipsis, so the drawing can
|
|
70
|
+
* give the whole label as its title. Ported from CAOS_Fragmenta `viz/text.ts` (0.07.000).
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
/** The name of a reference line that has no label, for the handle a reader drags (a screen reader says it): numbered when
|
|
74
|
+
* several unlabelled lines of one chart can be dragged, so each handle has a name of its own. */
|
|
75
|
+
declare function referenceLineName(lang: Lang, n: number, of: number): string;
|
|
76
|
+
/** The page's sans-serif stack as the shell token resolves it. */
|
|
77
|
+
declare function fontFamily(): string;
|
|
78
|
+
/** The width of one line of text at a font size, in CSS pixels; outside a browser, an estimate on the wide side. */
|
|
79
|
+
declare function textWidth(text: string, px: number, weight?: number): number;
|
|
80
|
+
/** The widest a set of labels needs, each on one line. */
|
|
81
|
+
declare function widestLabel(labels: readonly string[], px: number, weight?: number): number;
|
|
82
|
+
interface FittedLabel {
|
|
83
|
+
/** One or two lines; the last is shortened with an ellipsis only when the lines allowed are not enough. */
|
|
84
|
+
lines: string[];
|
|
85
|
+
/** Whether the label was shortened, so the drawing gives the whole label as its title. */
|
|
86
|
+
shortened: boolean;
|
|
87
|
+
}
|
|
88
|
+
/** A label in at most `maxLines` lines of `width` pixels: whole when it fits, broken at a word, shortened last. */
|
|
89
|
+
declare function fitLabel(label: string, width: number, px: number, maxLines?: 1 | 2): FittedLabel;
|
|
90
|
+
/** The 1, 2, 2.5 or 5 times a power of ten at or above `x`. */
|
|
91
|
+
declare function niceStep(x: number): number;
|
|
92
|
+
/**
|
|
93
|
+
* Round ticks covering [lo, hi], as many as leave room for labels about `labelSize` pixels along an axis of `room`
|
|
94
|
+
* pixels (at least two, at most `most`). The first tick is at or below `lo` and the last at or above `hi`, so a bar
|
|
95
|
+
* or a point never runs past the last labelled value.
|
|
96
|
+
*/
|
|
97
|
+
declare function niceTicks(lo: number, hi: number, room: number, labelSize: number, most?: number): number[];
|
|
98
|
+
|
|
99
|
+
export { type FormatOptions as F, NBSP as N, type ShellColorToken as S, type FittedLabel as a, NOT_AVAILABLE as b, SCIENTIFIC_BELOW as c, SHELL_TOKENS as d, type ShellToken as e, fitLabel as f, fontFamily as g, formatNumber as h, formatTicks as i, niceTicks as j, resolveToken as k, useThemeTokens as l, niceStep as n, referenceLineName as r, textWidth as t, useFormat as u, widestLabel as w };
|
package/gate/inpage.mjs
CHANGED
|
@@ -498,7 +498,7 @@ export function installLib() {
|
|
|
498
498
|
// charts whose axis gives a tick the label of the tick before it (UPlotChart declares data-ticks-repeat)
|
|
499
499
|
repeatedTicks: [...document.querySelectorAll('[data-ticks-repeat]')]
|
|
500
500
|
.filter((el) => visible(el) && Number(el.getAttribute('data-ticks-repeat')) > 0)
|
|
501
|
-
.map((el) => ({ label: describe(el.closest('[data-plot]') || el), n: Number(el.getAttribute('data-ticks-repeat')) })),
|
|
501
|
+
.map((el) => ({ label: describe(el.closest('[data-plot]') || el), n: Number(el.getAttribute('data-ticks-repeat')), names: el.getAttribute('data-ticks-repeated') || '' })),
|
|
502
502
|
// the drawing a filling card keeps under its note (G6 stage floor): the body of every visible `PlotCard fill`
|
|
503
503
|
fillStages: [...document.querySelectorAll('.caos-plot.fill')]
|
|
504
504
|
.filter(visible)
|
package/gate/run.mjs
CHANGED
|
@@ -481,7 +481,9 @@ export async function runGate(o) {
|
|
|
481
481
|
if (d) s.walkState.doc.push(d);
|
|
482
482
|
}
|
|
483
483
|
for (const r of f.repeatedTicks ?? []) {
|
|
484
|
-
|
|
484
|
+
// named x ticks (UPlotChart declares the repeated names): a name used twice, wherever the two ticks sit on the axis
|
|
485
|
+
if (r.names) fail('G6', where, `${r.label}: ${r.n} named x tick label(s) repeat another tick's label (${r.names.split('|').map((n) => `"${n}"`).join(', ')}); give every named tick a label of its own`);
|
|
486
|
+
else fail('G6', where, `${r.label}: ${r.n} axis tick label(s) repeat the label before them (give the axis fixed decimals)`);
|
|
485
487
|
}
|
|
486
488
|
// a filling card whose note leaves its drawing under the floor (CAOS_APP_SHELL#95); below 1280 px the document scrolls
|
|
487
489
|
if (big) for (const c of f.fillStages ?? []) if (c.h < opt.stageFloor) fail('G6', where, `the drawing of ${c.label} keeps ${Math.round(c.h)} px under its note (floor ${opt.stageFloor} px)`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fasl-work/caos-app-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Shared web-app shell, workbench primitives, content primitives, design system and measured gate for the CAOS / Faena public apps (ADR-0016, ADR-0017, ADR-0071).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Felipe Santibáñez-Leal",
|
package/reserved-classes.json
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"caos-card",
|
|
26
26
|
"caos-chart",
|
|
27
27
|
"caos-chart-key",
|
|
28
|
+
"caos-chart-key-button",
|
|
28
29
|
"caos-chart-legend",
|
|
29
30
|
"caos-chart-plot",
|
|
30
31
|
"caos-chart-readout",
|
|
@@ -338,6 +339,7 @@
|
|
|
338
339
|
"caos-card",
|
|
339
340
|
"caos-chart",
|
|
340
341
|
"caos-chart-key",
|
|
342
|
+
"caos-chart-key-button",
|
|
341
343
|
"caos-chart-legend",
|
|
342
344
|
"caos-chart-plot",
|
|
343
345
|
"caos-chart-readout",
|