basalt-ui 1.22.0 → 1.23.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/AGENTS.md +9 -1
- package/CHANGELOG.md +19 -0
- package/MIGRATING.md +125 -12
- package/README.md +45 -11
- package/agent/rules/basalt-app.md +26 -2
- package/agent/rules/basalt-charts.md +40 -5
- package/agent/rules/basalt-tokens.md +17 -1
- package/agent/skills/basalt-charts/SKILL.md +23 -8
- package/agent/templates/DESIGN.md.tpl +3 -1
- package/configs/oxlint-plugin.js +49 -8
- package/configs/oxlint-plugin.test.ts +88 -31
- package/dist/charts/hooks/useBandPlot.d.ts +138 -0
- package/dist/charts/hooks/useBandPlot.d.ts.map +1 -0
- package/dist/charts/hooks/useBandPlot.js +127 -0
- package/dist/charts/index.d.ts +4 -0
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +14 -0
- package/dist/charts/kinds/BandStrip.d.ts +113 -0
- package/dist/charts/kinds/BandStrip.d.ts.map +1 -0
- package/dist/charts/kinds/BandStrip.js +218 -0
- package/dist/charts/kinds/BandStrip.test.d.ts +2 -0
- package/dist/charts/kinds/BandStrip.test.d.ts.map +1 -0
- package/dist/charts/kinds/Bars.d.ts +5 -1
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +2 -0
- package/dist/charts/kinds/MirroredBars.d.ts +93 -0
- package/dist/charts/kinds/MirroredBars.d.ts.map +1 -0
- package/dist/charts/kinds/MirroredBars.js +315 -0
- package/dist/charts/kinds/MirroredBars.test.d.ts +2 -0
- package/dist/charts/kinds/MirroredBars.test.d.ts.map +1 -0
- package/dist/charts/kinds/MultiLine.d.ts +5 -1
- package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
- package/dist/charts/kinds/MultiLine.js +2 -0
- package/dist/charts/kinds/StackedArea.d.ts +5 -1
- package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
- package/dist/charts/kinds/StackedArea.js +2 -0
- package/dist/charts/kinds/ZonedLine.d.ts +5 -1
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/kinds/ZonedLine.js +2 -0
- package/dist/charts/primitives/CartesianChart.d.ts +18 -2
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
- package/dist/charts/primitives/CartesianChart.js +5 -2
- package/dist/charts/primitives/HatchPattern.d.ts +31 -0
- package/dist/charts/primitives/HatchPattern.d.ts.map +1 -0
- package/dist/charts/primitives/HatchPattern.js +31 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +47 -8
- package/dist/cli/shipped-versions.test.d.ts +2 -0
- package/dist/cli/shipped-versions.test.d.ts.map +1 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +32 -11
- package/dist/vite.d.ts +42 -3
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +67 -30
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/hooks/useBandPlot.ts +302 -0
- package/src/charts/index.ts +14 -0
- package/src/charts/kinds/BandStrip.test.tsx +200 -0
- package/src/charts/kinds/BandStrip.tsx +364 -0
- package/src/charts/kinds/Bars.tsx +7 -1
- package/src/charts/kinds/DualPanel.test.tsx +10 -4
- package/src/charts/kinds/MirroredBars.test.tsx +193 -0
- package/src/charts/kinds/MirroredBars.tsx +455 -0
- package/src/charts/kinds/MultiLine.tsx +7 -1
- package/src/charts/kinds/StackedArea.tsx +7 -1
- package/src/charts/kinds/ZonedLine.tsx +7 -1
- package/src/charts/primitives/CartesianChart.test.tsx +86 -4
- package/src/charts/primitives/CartesianChart.tsx +28 -3
- package/src/charts/primitives/HatchPattern.tsx +55 -0
- package/src/cli/index.ts +125 -18
- package/src/cli/shipped-versions.test.ts +83 -0
- package/src/cli/toolchain-wiring.test.ts +171 -4
- package/src/cli/waiver-audit.test.ts +7 -3
- package/src/guard/check-source.test.ts +138 -42
- package/src/guard/index.ts +83 -17
- package/src/vite.test.ts +79 -0
- package/src/vite.ts +141 -39
package/configs/oxlint-plugin.js
CHANGED
|
@@ -245,8 +245,49 @@ function allComments(context) {
|
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
/**
|
|
248
|
-
*
|
|
249
|
-
*
|
|
248
|
+
* Every comment that REACHES `nodeLine` — the comment on the node's own line, the one directly
|
|
249
|
+
* above it, and any further comment separated from that one by nothing but comment.
|
|
250
|
+
*
|
|
251
|
+
* This is the plugin's half of "which node does this annotation scope to", and it has to answer the
|
|
252
|
+
* same question `src/guard`'s forward walk answers: **an annotation reaches the first line below its
|
|
253
|
+
* comment that is not itself comment.** The test used to be a flat `end.line === nodeLine ||
|
|
254
|
+
* nodeLine - 1`, which is the same rule only when the annotation is the LAST comment above the node
|
|
255
|
+
* — so anything sitting between the annotation and the node, comment included, was reported here
|
|
256
|
+
* while the guard waived it:
|
|
257
|
+
*
|
|
258
|
+
* ```text
|
|
259
|
+
* // theme-allow raw-hex — the vendor brand hex, kept in sync with ← a reason that wrapped
|
|
260
|
+
* // the marketing site's own palette onto a second comment
|
|
261
|
+
* const BRAND = '#ff0000'
|
|
262
|
+
*
|
|
263
|
+
* {/* theme-allow card-inset — … *\/}
|
|
264
|
+
* {/* 3. the density row *\/} ← an unrelated note
|
|
265
|
+
* <Card p={0} />
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* The wrapped-reason one is not hypothetical: it is pinned in the guard's tests as a shape argo
|
|
269
|
+
* writes. A blank line still separates, because a blank line is not comment — which is what makes
|
|
270
|
+
* "this comment is not about the next statement" expressible in both halves.
|
|
271
|
+
*
|
|
272
|
+
* Returned bottom-up, which is also the cheap order to walk: stop at the first gap.
|
|
273
|
+
*/
|
|
274
|
+
function reachingComments(context, nodeLine) {
|
|
275
|
+
const comments = allComments(context).toSorted((a, b) => a.loc.start.line - b.loc.start.line)
|
|
276
|
+
const out = []
|
|
277
|
+
let reach = nodeLine
|
|
278
|
+
for (let i = comments.length - 1; i >= 0; i--) {
|
|
279
|
+
const comment = comments[i]
|
|
280
|
+
if (comment.loc.end.line > nodeLine) continue
|
|
281
|
+
if (comment.loc.end.line < reach - 1) break
|
|
282
|
+
out.push(comment)
|
|
283
|
+
reach = Math.min(reach, comment.loc.start.line)
|
|
284
|
+
}
|
|
285
|
+
return out
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* True when a NODE-scoped `theme-allow` covering `ruleId` reaches `node` (see
|
|
290
|
+
* {@link reachingComments}) — or when the file carries a `theme-allow-file` declaration for it.
|
|
250
291
|
*
|
|
251
292
|
* The `ruleId` argument is what stops one exemption from being a blanket one: a `theme-allow
|
|
252
293
|
* raw-hex — …` written for a color no longer silently switches off `card-inset` on the same line.
|
|
@@ -254,13 +295,11 @@ function allComments(context) {
|
|
|
254
295
|
*/
|
|
255
296
|
function hasThemeAllow(context, node, ruleId) {
|
|
256
297
|
if (hasFileDeclaration(context, ruleId)) return true
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (comment.loc.end.line !== nodeLine && comment.loc.end.line !== nodeLine - 1) return false
|
|
260
|
-
return parseThemeAllows(comment.value).some(
|
|
298
|
+
return reachingComments(context, node.loc.start.line).some((comment) =>
|
|
299
|
+
parseThemeAllows(comment.value).some(
|
|
261
300
|
(allow) => allow.scope === 'line' && allowCovers(allow, ruleId),
|
|
262
|
-
)
|
|
263
|
-
|
|
301
|
+
),
|
|
302
|
+
)
|
|
264
303
|
}
|
|
265
304
|
|
|
266
305
|
/**
|
|
@@ -535,10 +574,12 @@ const cardInset = {
|
|
|
535
574
|
// ── Rule 3 — chart-in-raw-surface ───────────────────────────────────────────────────────────────
|
|
536
575
|
|
|
537
576
|
const CHART_TAGS = new Set([
|
|
577
|
+
'BandStrip',
|
|
538
578
|
'Bars',
|
|
539
579
|
'Donut',
|
|
540
580
|
'DualPanel',
|
|
541
581
|
'Heatmap',
|
|
582
|
+
'MirroredBars',
|
|
542
583
|
'MultiLine',
|
|
543
584
|
'StackedArea',
|
|
544
585
|
'ZonedLine',
|
|
@@ -984,55 +984,112 @@ describe('basalt/shadow-basalt-export', () => {
|
|
|
984
984
|
})
|
|
985
985
|
})
|
|
986
986
|
|
|
987
|
-
// ── theme-allow
|
|
987
|
+
// ── theme-allow shape grid (the plugin half of the annotation contract) ──────
|
|
988
988
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
989
|
+
/**
|
|
990
|
+
* The plugin's copy of the grid pinned in `src/guard/check-source.test.ts`, row name for row name.
|
|
991
|
+
*
|
|
992
|
+
* Five holes in four rounds, twice because the two parsers disagreed about what an annotation IS —
|
|
993
|
+
* so the shapes are enumerated over the axes that vary (comment style × token position × where the
|
|
994
|
+
* closer falls × what follows), not collected as anecdotes. Every row here has a twin there; the
|
|
995
|
+
* guard-only dialects (CSS continuation lines, HTML, the JSON member form) have no twin because
|
|
996
|
+
* oxlint never parses those files.
|
|
997
|
+
*
|
|
998
|
+
* `no-raw-font-size` is the vehicle — a JSXAttribute rule, so the reported node's line is exactly
|
|
999
|
+
* the line an annotation has to reach.
|
|
1000
|
+
*/
|
|
1001
|
+
/** Wraps JSX children in a component, so a `{/* … *\/}` child is legal source. */
|
|
1002
|
+
const jsxShape = (body: string): string =>
|
|
1003
|
+
`export const C = () => (\n <div>\n${body}\n </div>\n)\n`
|
|
1004
|
+
|
|
1005
|
+
describe('theme-allow shape grid', () => {
|
|
1006
|
+
const REASON = 'deliberate legacy value'
|
|
1007
|
+
const A = `theme-allow no-raw-font-size — ${REASON}`
|
|
1008
|
+
const AF = `theme-allow-file no-raw-font-size — ${REASON}`
|
|
1009
|
+
const T = `<Text fz={10} />`
|
|
1010
|
+
const J = jsxShape
|
|
1011
|
+
|
|
1012
|
+
const waives = (source: string): boolean => !run(source).rules.has('no-raw-font-size')
|
|
994
1013
|
|
|
995
1014
|
it.each([
|
|
1015
|
+
['// own line', `// ${A}\nexport const C = ${T}\n`],
|
|
1016
|
+
['// indented', `function f() {\n // ${A}\n return ${T}\n}\n`],
|
|
1017
|
+
['// no space after the marker', `//${A}\nexport const C = ${T}\n`],
|
|
1018
|
+
['// trailing', `export const C = ${T} // ${A}\n`],
|
|
996
1019
|
[
|
|
997
|
-
'
|
|
998
|
-
`//
|
|
999
|
-
],
|
|
1000
|
-
[
|
|
1001
|
-
'trailing //',
|
|
1002
|
-
`export const C = <Text fz={10} /> // theme-allow no-raw-font-size — deliberate\n`,
|
|
1020
|
+
'// reason wrapped onto a second // comment',
|
|
1021
|
+
`// ${A},\n// continued here\nexport const C = ${T}\n`,
|
|
1003
1022
|
],
|
|
1023
|
+
['/* */ own line', `/* ${A} */\nexport const C = ${T}\n`],
|
|
1024
|
+
['/* */ trailing', `export const C = ${T} /* ${A} */\n`],
|
|
1025
|
+
['/** */ own line (docblock opener)', `/** ${A} */\nexport const C = ${T}\n`],
|
|
1026
|
+
['/* opener + token, closer on its own line', `/* ${A}\n*/\nexport const C = ${T}\n`],
|
|
1027
|
+
['/* gutter token, closer on the token line', `/*\n ${A} */\nexport const C = ${T}\n`],
|
|
1028
|
+
['/* gutter token, closer on its own line', `/*\n ${A}\n*/\nexport const C = ${T}\n`],
|
|
1029
|
+
['/** star gutter, closer on the token line', `/**\n * ${A} */\nexport const C = ${T}\n`],
|
|
1030
|
+
['/** star gutter, closer on its own line', `/**\n * ${A}\n */\nexport const C = ${T}\n`],
|
|
1031
|
+
['/** token then 1 prose line', `/**\n * ${A}\n * more\n */\nexport const C = ${T}\n`],
|
|
1004
1032
|
[
|
|
1005
|
-
'
|
|
1006
|
-
|
|
1033
|
+
'/** token then 12 prose lines',
|
|
1034
|
+
`/**\n * ${A}\n${' * p\n'.repeat(12)} */\nexport const C = ${T}\n`,
|
|
1007
1035
|
],
|
|
1008
1036
|
[
|
|
1009
|
-
'
|
|
1010
|
-
|
|
1037
|
+
'/** prose first, token on a later gutter line',
|
|
1038
|
+
`/**\n * some prose\n * ${A}\n */\nexport const C = ${T}\n`,
|
|
1011
1039
|
],
|
|
1040
|
+
['{/* */} own line', J(` {/* ${A} */}\n ${T}`)],
|
|
1041
|
+
['{/* */} trailing on the target line', J(` ${T} {/* ${A} */}`)],
|
|
1042
|
+
['{/* opener + token, closer on its own line', J(` {/* ${A}\n */}\n ${T}`)],
|
|
1043
|
+
['{/* gutter token, closer on the token line', J(` {/*\n ${A} */}\n ${T}`)],
|
|
1044
|
+
['{/* gutter token, closer on its own line', J(` {/*\n ${A}\n */}\n ${T}`)],
|
|
1045
|
+
['{/** star gutter, closer on the token line', J(` {/**\n * ${A} */}\n ${T}`)],
|
|
1046
|
+
['{/** star gutter, closer on its own line', J(` {/**\n * ${A}\n */}\n ${T}`)],
|
|
1012
1047
|
[
|
|
1013
|
-
'
|
|
1014
|
-
`
|
|
1048
|
+
'{/** token then 6 prose lines',
|
|
1049
|
+
J(` {/**\n * ${A}\n${' * p\n'.repeat(6)} */}\n ${T}`),
|
|
1015
1050
|
],
|
|
1051
|
+
['{/* target on the closer line', J(` {/*\n ${A}\n */}${T}`)],
|
|
1052
|
+
['{/* closer alone, tab indented', J(`\t{/*\n\t ${A}\n\t*/}\n\t${T}`)],
|
|
1053
|
+
['{/* closer alone, space between */ and }', J(` {/*\n ${A}\n */ }\n ${T}`)],
|
|
1016
1054
|
[
|
|
1017
|
-
'block
|
|
1018
|
-
|
|
1055
|
+
'{/* closer alone, two annotations in one block',
|
|
1056
|
+
J(` {/*\n ${A}\n theme-allow card-inset — ${REASON}\n */}\n ${T}`),
|
|
1019
1057
|
],
|
|
1020
1058
|
[
|
|
1021
|
-
'
|
|
1022
|
-
`/**
|
|
1059
|
+
'/** */ then an unrelated // note',
|
|
1060
|
+
`/** ${A} */\n// an unrelated note\nexport const C = ${T}\n`,
|
|
1023
1061
|
],
|
|
1062
|
+
['{/* */} then an unrelated {/* */}', J(` {/* ${A} */}\n {/* unrelated */}\n ${T}`)],
|
|
1063
|
+
['theme-allow-file, {/* closer on its own line', J(` {/*\n ${AF}\n */}\n ${T}`)],
|
|
1064
|
+
['theme-allow-file, /** star gutter', `/**\n * ${AF}\n */\nexport const C = ${T}\n`],
|
|
1024
1065
|
])('%s waives', (_name, source) => {
|
|
1025
|
-
expect(
|
|
1066
|
+
expect(waives(source as string)).toBe(true)
|
|
1026
1067
|
})
|
|
1027
1068
|
|
|
1028
|
-
//
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
),
|
|
1035
|
-
|
|
1069
|
+
// ── UNSUPPORTED — asserted, so a hole can never pass for a design decision ──
|
|
1070
|
+
it.each([
|
|
1071
|
+
['blank line after a // annotation', `// ${A}\n\nexport const C = ${T}\n`],
|
|
1072
|
+
['blank line after a {/* */} annotation', J(` {/* ${A} */}\n\n ${T}`)],
|
|
1073
|
+
[
|
|
1074
|
+
'blank line after a {/* closer on its own line',
|
|
1075
|
+
J(` {/*\n ${A}\n */}\n\n ${T}`),
|
|
1076
|
+
],
|
|
1077
|
+
['mid-sentence in a line comment', `// we normally write a ${A} here\nexport const C = ${T}\n`],
|
|
1078
|
+
[
|
|
1079
|
+
'mid-sentence in a docblock gutter',
|
|
1080
|
+
`/**\n * Each value is escaped with a ${A} annotation.\n */\nexport const C = ${T}\n`,
|
|
1081
|
+
],
|
|
1082
|
+
[
|
|
1083
|
+
'mid-sentence in a JSX expression comment',
|
|
1084
|
+
J(` {/* the shape here is a ${A} comment */}\n ${T}`),
|
|
1085
|
+
],
|
|
1086
|
+
[
|
|
1087
|
+
'inside a string literal',
|
|
1088
|
+
`const doc = 'theme-allow no-raw-font-size'\nexport const C = ${T}\n`,
|
|
1089
|
+
],
|
|
1090
|
+
['above a multi-line opening tag', J(` {/* ${A} */}\n <Text\n fz={10}\n />`)],
|
|
1091
|
+
])('%s does NOT waive', (_name, source) => {
|
|
1092
|
+
expect(waives(source as string)).toBe(false)
|
|
1036
1093
|
})
|
|
1037
1094
|
})
|
|
1038
1095
|
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The choreography shared by every BANDED x plot — one slot per datum, drawn as a rect, with no
|
|
3
|
+
* point in between.
|
|
4
|
+
*
|
|
5
|
+
* `CartesianChart` cannot host these: its x scale is `scalePoint` (positions, no width) and it
|
|
6
|
+
* renders `AxisLeftNumeric` unconditionally. `BandStrip` has no numeric y axis at all and
|
|
7
|
+
* `MirroredBars` has two, in two independent scales. Both are therefore
|
|
8
|
+
* `basalt/hand-rolled-plot` shapes — and this module is what stops the second one from being a
|
|
9
|
+
* copy of the first, per `DualPanel`'s own instruction to "promote the shared choreography rather
|
|
10
|
+
* than copying this file".
|
|
11
|
+
*
|
|
12
|
+
* What lives here: width-driven folding, the measured gutters, the band scale and its
|
|
13
|
+
* half-bandwidth cursor correction, the shared cursor itself, and the source/follower tooltip
|
|
14
|
+
* anchor arithmetic. What does NOT: any mark. See `docs/CHARTS-SPEC.md` § "The contract".
|
|
15
|
+
*/
|
|
16
|
+
import { scaleBand } from '@visx/scale';
|
|
17
|
+
import type { ReactNode, RefObject } from 'react';
|
|
18
|
+
import type { ChartMargin } from '../../tokens/index.js';
|
|
19
|
+
import type { CursorResolution } from '../cursor/resolve.js';
|
|
20
|
+
import type { ChartCursor, CursorAnchor } from './useChartCursor.js';
|
|
21
|
+
type BandScale = ReturnType<typeof scaleBand<string>>;
|
|
22
|
+
/**
|
|
23
|
+
* Collapse adjacent data into one drawn band at widths where one-band-per-datum sub-pixels.
|
|
24
|
+
*
|
|
25
|
+
* 288 buckets over a 234px plot is a 0.81px pitch: every band draws at a flat 1px and a single
|
|
26
|
+
* catastrophic slot can be overdrawn by its neighbour. Folding is the only honest answer — the
|
|
27
|
+
* alternative is a chart that silently loses its worst column.
|
|
28
|
+
*/
|
|
29
|
+
export type BandFold<T> = {
|
|
30
|
+
/**
|
|
31
|
+
* Floor on the px pitch of a drawn band. Default 3 — not 2, because a band also has to be wide
|
|
32
|
+
* enough for a partial-absence split (`absentFraction`) to render as two visibly distinct
|
|
33
|
+
* pieces, and at 2px the fill and the hatch antialias into one smudge.
|
|
34
|
+
*/
|
|
35
|
+
minBandPx?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Collapse a group of adjacent source data into the one datum drawn in its place.
|
|
38
|
+
*
|
|
39
|
+
* The merge is the CONSUMER's, deliberately: whether a folded slot's value is a max, a sum, or
|
|
40
|
+
* a rate recomputed from summed parts is a question about the measurement, not about the
|
|
41
|
+
* chart — and averaging a fully-down bucket into its clean neighbours describes a bucket that
|
|
42
|
+
* never happened. The kind owns only the arithmetic of how many groups there are.
|
|
43
|
+
*
|
|
44
|
+
* Identity (`getX`) MUST come from `group[0]`, or the axis stops being monotone and the cursor
|
|
45
|
+
* key stops naming a real slot start.
|
|
46
|
+
*/
|
|
47
|
+
merge: (group: T[]) => T;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* The grouping half of {@link BandFold}, exported so a consumer can test their `merge` against the
|
|
51
|
+
* arithmetic that will actually run rather than re-implementing it in the test file — the merge is
|
|
52
|
+
* where the honesty rules live (max vs mean vs a rate recomputed from summed parts), and a test
|
|
53
|
+
* that groups differently from the kind is testing the wrong function.
|
|
54
|
+
*/
|
|
55
|
+
export declare function foldBands<T>(data: readonly T[], cap: number, merge: (group: T[]) => T): T[];
|
|
56
|
+
/** Tooltip seams shared by `BandStrip` and `MirroredBars` — the `CartesianTooltipConfig` subset
|
|
57
|
+
* that means anything on a banded plot (there is no per-point `follow` distinction to make that
|
|
58
|
+
* `CartesianChart` doesn't already document identically). */
|
|
59
|
+
export type BandTooltipConfig<T> = {
|
|
60
|
+
/** Default true — the tooltip tracks the pointer. `false` anchors it to the crosshair at the
|
|
61
|
+
* plot's top edge, so a column of charts sharing one cursor lines every tooltip up on one x. */
|
|
62
|
+
follow?: boolean;
|
|
63
|
+
/** Right-aligned badge in the tooltip header. */
|
|
64
|
+
label?: (d: T) => {
|
|
65
|
+
text: string;
|
|
66
|
+
color: string;
|
|
67
|
+
} | null;
|
|
68
|
+
/** Overrides the header's date text — same seam, same reason, as
|
|
69
|
+
* `CartesianTooltipConfig.formatHeader`. */
|
|
70
|
+
formatHeader?: (key: string, d: T) => string;
|
|
71
|
+
/** Rows rendered BEFORE the derived rows. `hidden` is the same legend-toggle set the marks
|
|
72
|
+
* draw from, so a hand-authored row cannot desync from it. */
|
|
73
|
+
prependRows?: (d: T, ctx: BandTooltipRowContext) => ReactNode;
|
|
74
|
+
/** Rows appended after the derived rows. Same `ctx` as {@link prependRows}. */
|
|
75
|
+
extraRows?: (d: T, ctx: BandTooltipRowContext) => ReactNode;
|
|
76
|
+
/**
|
|
77
|
+
* Render this chart's tooltip when it is a cursor FOLLOWER, not only when it is the SOURCE.
|
|
78
|
+
* Default false. A follower has no pointer under it, so it always anchors to the crosshair
|
|
79
|
+
* regardless of `follow`; only the SOURCE is `aria-live`. Costs one `getBoundingClientRect`
|
|
80
|
+
* per hovered frame per opted-in chart — see `CartesianTooltipConfig.onFollow`.
|
|
81
|
+
*/
|
|
82
|
+
onFollow?: boolean;
|
|
83
|
+
};
|
|
84
|
+
export type BandTooltipRowContext = {
|
|
85
|
+
hidden: ReadonlySet<string>;
|
|
86
|
+
};
|
|
87
|
+
export type UseBandPlotInput<T> = {
|
|
88
|
+
data: readonly T[];
|
|
89
|
+
chartId: string;
|
|
90
|
+
getX: (d: T) => string;
|
|
91
|
+
formatX: (key: string) => string;
|
|
92
|
+
/** The plot rect's width, as handed down by `ChartFrame`. */
|
|
93
|
+
width: number;
|
|
94
|
+
fold?: BandFold<T>;
|
|
95
|
+
cursorResolution?: CursorResolution;
|
|
96
|
+
/**
|
|
97
|
+
* Which of the (possibly folded) keys get a tick. Default `smartTicks`. The seam exists because
|
|
98
|
+
* `smartTicks` appends the final value unconditionally, which on a dense time axis puts the last
|
|
99
|
+
* two labels on top of each other — a chart whose x labels are richer than `DD.MM` needs its own
|
|
100
|
+
* rule.
|
|
101
|
+
*/
|
|
102
|
+
xTickValues?: (keys: readonly string[], plotWidth: number) => readonly string[];
|
|
103
|
+
/** Left-axis tick labels, already formatted. Empty for a plot with no left axis. */
|
|
104
|
+
leftLabels?: readonly string[];
|
|
105
|
+
/** Per-side margin overrides — applied last, so the escape hatch always wins. */
|
|
106
|
+
margin?: Partial<ChartMargin>;
|
|
107
|
+
tooltip?: BandTooltipConfig<T> | false;
|
|
108
|
+
};
|
|
109
|
+
export type BandPlot<T> = {
|
|
110
|
+
/** The data actually drawn — `data` when it fits, the folded slots when it does not. */
|
|
111
|
+
bands: T[];
|
|
112
|
+
keys: string[];
|
|
113
|
+
margin: ChartMargin;
|
|
114
|
+
plotWidth: number;
|
|
115
|
+
scale: BandScale;
|
|
116
|
+
cursor: ChartCursor<T>;
|
|
117
|
+
point: T | null;
|
|
118
|
+
/** Plot-local x of the crosshair, or null when no point resolves. */
|
|
119
|
+
crosshairX: number | null;
|
|
120
|
+
/** Pitch between adjacent band origins. */
|
|
121
|
+
step: number;
|
|
122
|
+
/** Drawn width of one band — the pitch minus a 1px separator, floored at 1. */
|
|
123
|
+
bandWidth: number;
|
|
124
|
+
tickValues: string[];
|
|
125
|
+
svgRef: RefObject<SVGSVGElement | null>;
|
|
126
|
+
tooltipAnchor: CursorAnchor | null;
|
|
127
|
+
showTooltip: boolean;
|
|
128
|
+
/** Only the cursor SOURCE announces — N followers on one page would fire N live-region updates
|
|
129
|
+
* per pointer move. */
|
|
130
|
+
ariaLive: boolean;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Wire a banded plot into the framework's measured margins, band scale, shared cursor and tooltip
|
|
134
|
+
* positioning. Returns everything except the marks.
|
|
135
|
+
*/
|
|
136
|
+
export declare function useBandPlot<T>(input: UseBandPlotInput<T>): BandPlot<T>;
|
|
137
|
+
export {};
|
|
138
|
+
//# sourceMappingURL=useBandPlot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBandPlot.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useBandPlot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { scaleBand } from "@visx/scale";
|
|
2
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
3
|
+
import { VX } from "../../tokens/index.js";
|
|
4
|
+
import { autoMargin } from "../layout/auto-margin.js";
|
|
5
|
+
import { maxTextWidth } from "../utils/measure-text.js";
|
|
6
|
+
import { smartTicks } from "../utils/ticks.js";
|
|
7
|
+
import { useChartCursor } from "./useChartCursor.js";
|
|
8
|
+
const DEFAULT_MIN_BAND_PX = 3;
|
|
9
|
+
const TERMINAL_GUTTER_MAX_FRACTION = { left: 0.14, right: 0.12 };
|
|
10
|
+
function foldBands(data, cap, merge) {
|
|
11
|
+
if (cap <= 0) return [];
|
|
12
|
+
if (data.length <= cap) return [...data];
|
|
13
|
+
const groupSize = Math.ceil(data.length / cap);
|
|
14
|
+
const out = [];
|
|
15
|
+
for (let i = 0; i < data.length; i += groupSize) out.push(merge(data.slice(i, i + groupSize)));
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function useBandPlot(input) {
|
|
19
|
+
const {
|
|
20
|
+
data,
|
|
21
|
+
chartId,
|
|
22
|
+
getX,
|
|
23
|
+
formatX,
|
|
24
|
+
width,
|
|
25
|
+
fold,
|
|
26
|
+
cursorResolution,
|
|
27
|
+
xTickValues,
|
|
28
|
+
leftLabels,
|
|
29
|
+
margin: marginOverride,
|
|
30
|
+
tooltip
|
|
31
|
+
} = input;
|
|
32
|
+
const hasLeftAxis = leftLabels !== void 0 && leftLabels.length > 0;
|
|
33
|
+
const xLabelsAll = useMemo(() => data.map((d) => formatX(getX(d))), [data, getX, formatX]);
|
|
34
|
+
const margin = useMemo(() => {
|
|
35
|
+
const measured = autoMargin({
|
|
36
|
+
...leftLabels !== void 0 && { left: leftLabels },
|
|
37
|
+
bottom: xLabelsAll,
|
|
38
|
+
...marginOverride !== void 0 && { override: marginOverride }
|
|
39
|
+
});
|
|
40
|
+
if (marginOverride?.left !== void 0 && marginOverride.right !== void 0) return measured;
|
|
41
|
+
const halfXLabel = Math.ceil(maxTextWidth(xLabelsAll, VX.axisFont) / 2);
|
|
42
|
+
const left = hasLeftAxis ? measured.left : Math.max(measured.left, halfXLabel);
|
|
43
|
+
return {
|
|
44
|
+
...measured,
|
|
45
|
+
...marginOverride?.left === void 0 && {
|
|
46
|
+
left: hasLeftAxis ? left : capTerminalGutter(left, width, TERMINAL_GUTTER_MAX_FRACTION.left, VX.margin.left)
|
|
47
|
+
},
|
|
48
|
+
...marginOverride?.right === void 0 && {
|
|
49
|
+
right: capTerminalGutter(
|
|
50
|
+
measured.right,
|
|
51
|
+
width,
|
|
52
|
+
TERMINAL_GUTTER_MAX_FRACTION.right,
|
|
53
|
+
VX.margin.right
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}, [leftLabels, xLabelsAll, marginOverride, hasLeftAxis, width]);
|
|
58
|
+
const plotWidth = Math.max(width - margin.left - margin.right, 0);
|
|
59
|
+
const minBandPx = fold?.minBandPx ?? DEFAULT_MIN_BAND_PX;
|
|
60
|
+
const merge = fold?.merge;
|
|
61
|
+
const bands = useMemo(
|
|
62
|
+
() => merge === void 0 ? [...data] : foldBands(data, Math.floor(plotWidth / minBandPx), merge),
|
|
63
|
+
[data, plotWidth, minBandPx, merge]
|
|
64
|
+
);
|
|
65
|
+
const keys = useMemo(() => bands.map(getX), [bands, getX]);
|
|
66
|
+
const scale = useMemo(
|
|
67
|
+
() => scaleBand({ domain: keys, range: [0, plotWidth] }),
|
|
68
|
+
[keys, plotWidth]
|
|
69
|
+
);
|
|
70
|
+
const bandCenter = useCallback(
|
|
71
|
+
(key) => {
|
|
72
|
+
const v = scale(key);
|
|
73
|
+
return v === void 0 ? void 0 : v + scale.bandwidth() / 2;
|
|
74
|
+
},
|
|
75
|
+
[scale]
|
|
76
|
+
);
|
|
77
|
+
const cursor = useChartCursor({
|
|
78
|
+
data: bands,
|
|
79
|
+
chartId,
|
|
80
|
+
getKey: getX,
|
|
81
|
+
xScale: bandCenter,
|
|
82
|
+
marginLeft: margin.left,
|
|
83
|
+
...cursorResolution !== void 0 && { resolution: cursorResolution }
|
|
84
|
+
});
|
|
85
|
+
const tickValues = useMemo(
|
|
86
|
+
() => [
|
|
87
|
+
...xTickValues === void 0 ? smartTicks(keys, plotWidth) : xTickValues(keys, plotWidth)
|
|
88
|
+
],
|
|
89
|
+
[keys, plotWidth, xTickValues]
|
|
90
|
+
);
|
|
91
|
+
const svgRef = useRef(null);
|
|
92
|
+
const point = cursor.point;
|
|
93
|
+
const crosshairX = point === null ? null : bandCenter(getX(point)) ?? null;
|
|
94
|
+
const cfg = tooltip === false ? void 0 : tooltip;
|
|
95
|
+
const isFollowerRender = !cursor.isSource && cfg?.onFollow === true;
|
|
96
|
+
const showTooltip = tooltip !== false && point !== null && (cursor.isSource || isFollowerRender);
|
|
97
|
+
const useAnchored = cfg?.follow === false || isFollowerRender;
|
|
98
|
+
const anchorX = useAnchored ? crosshairX : null;
|
|
99
|
+
const svgRect = anchorX === null ? void 0 : svgRef.current?.getBoundingClientRect();
|
|
100
|
+
const tooltipAnchor = svgRect === void 0 || anchorX === null ? cursor.anchor : { x: svgRect.left + margin.left + anchorX, y: svgRect.top + margin.top };
|
|
101
|
+
const step = bands.length > 0 ? plotWidth / bands.length : 0;
|
|
102
|
+
const bandWidth = Math.max(step - 1, 1);
|
|
103
|
+
return {
|
|
104
|
+
bands,
|
|
105
|
+
keys,
|
|
106
|
+
margin,
|
|
107
|
+
plotWidth,
|
|
108
|
+
scale,
|
|
109
|
+
cursor,
|
|
110
|
+
point,
|
|
111
|
+
crosshairX,
|
|
112
|
+
step,
|
|
113
|
+
bandWidth,
|
|
114
|
+
tickValues,
|
|
115
|
+
svgRef,
|
|
116
|
+
tooltipAnchor,
|
|
117
|
+
showTooltip,
|
|
118
|
+
ariaLive: cursor.isSource
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function capTerminalGutter(gutter, width, fraction, floor) {
|
|
122
|
+
return Math.min(gutter, Math.max(floor, Math.round(width * fraction)));
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
foldBands,
|
|
126
|
+
useBandPlot
|
|
127
|
+
};
|
package/dist/charts/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { CartesianChart, resolveAxisDomain, type CartesianChartProps, type Carte
|
|
|
20
20
|
export { ChartFrame, type ChartFrameProps, type ChartFrameLegend, type PlotRect, resolveLegend, } from './primitives/ChartFrame.js';
|
|
21
21
|
export { ChartCenter, type ChartCenterProps, ChartPending, type ChartPendingProps, } from './primitives/ChartPending.js';
|
|
22
22
|
export { Crosshair, SeriesDot } from './primitives/Crosshair.js';
|
|
23
|
+
export { HatchPattern, hatchFill, hatchSizeFor } from './primitives/HatchPattern.js';
|
|
23
24
|
export { ChartCard } from './primitives/ChartCard.js';
|
|
24
25
|
export { ChartLegend, type LegendEntry } from './primitives/ChartLegend.js';
|
|
25
26
|
export { ChartTooltipFloat, TooltipHeader, TooltipRow, TooltipBody, } from './primitives/ChartTooltip.js';
|
|
@@ -29,6 +30,7 @@ export { ZoneRects, type ZoneSpec } from './primitives/ZoneRects.js';
|
|
|
29
30
|
export { XZoneRects, type XZoneSpec } from './primitives/XZoneRects.js';
|
|
30
31
|
export { AreaGradient, areaFillUrl } from './primitives/AreaGradient.js';
|
|
31
32
|
export { useChartCursor, type ChartCursor, type CursorAnchor } from './hooks/useChartCursor.js';
|
|
33
|
+
export { foldBands, type BandFold, type BandTooltipConfig, type BandTooltipRowContext, } from './hooks/useBandPlot.js';
|
|
32
34
|
export type { CursorResolution } from './cursor/resolve.js';
|
|
33
35
|
export { useChartSize, type UseChartSizeResult, type ChartSize } from './hooks/useChartSize.js';
|
|
34
36
|
export { fmtAxisDate, fmtTooltipDate } from './utils/format.js';
|
|
@@ -42,6 +44,8 @@ export { Donut, type DonutProps, type DonutDatum } from './kinds/Donut.js';
|
|
|
42
44
|
export { MultiLine, type MultiLineProps } from './kinds/MultiLine.js';
|
|
43
45
|
export { DualPanel, type DualPanelProps } from './kinds/DualPanel.js';
|
|
44
46
|
export { Heatmap, type HeatmapProps } from './kinds/Heatmap.js';
|
|
47
|
+
export { BandStrip, type BandStripProps, type BandStripSeries, type BandSpan, } from './kinds/BandStrip.js';
|
|
48
|
+
export { MirroredBars, type MirroredBarsProps, type MirroredBarPane } from './kinds/MirroredBars.js';
|
|
45
49
|
export { LineSparkline, BarSparkline } from './sparklines/index.js';
|
|
46
50
|
export { Group } from '@visx/group';
|
|
47
51
|
export { GridRows, GridColumns } from '@visx/grid';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"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"}
|
package/dist/charts/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
ChartPending
|
|
31
31
|
} from "./primitives/ChartPending.js";
|
|
32
32
|
import { Crosshair, SeriesDot } from "./primitives/Crosshair.js";
|
|
33
|
+
import { HatchPattern, hatchFill, hatchSizeFor } from "./primitives/HatchPattern.js";
|
|
33
34
|
import { ChartCard } from "./primitives/ChartCard.js";
|
|
34
35
|
import { ChartLegend } from "./primitives/ChartLegend.js";
|
|
35
36
|
import {
|
|
@@ -44,6 +45,9 @@ import { ZoneRects } from "./primitives/ZoneRects.js";
|
|
|
44
45
|
import { XZoneRects } from "./primitives/XZoneRects.js";
|
|
45
46
|
import { AreaGradient, areaFillUrl } from "./primitives/AreaGradient.js";
|
|
46
47
|
import { useChartCursor } from "./hooks/useChartCursor.js";
|
|
48
|
+
import {
|
|
49
|
+
foldBands
|
|
50
|
+
} from "./hooks/useBandPlot.js";
|
|
47
51
|
import { useChartSize } from "./hooks/useChartSize.js";
|
|
48
52
|
import { fmtAxisDate, fmtTooltipDate } from "./utils/format.js";
|
|
49
53
|
import { smartTicks, smartTicksEvery } from "./utils/ticks.js";
|
|
@@ -60,6 +64,10 @@ import { Donut } from "./kinds/Donut.js";
|
|
|
60
64
|
import { MultiLine } from "./kinds/MultiLine.js";
|
|
61
65
|
import { DualPanel } from "./kinds/DualPanel.js";
|
|
62
66
|
import { Heatmap } from "./kinds/Heatmap.js";
|
|
67
|
+
import {
|
|
68
|
+
BandStrip
|
|
69
|
+
} from "./kinds/BandStrip.js";
|
|
70
|
+
import { MirroredBars } from "./kinds/MirroredBars.js";
|
|
63
71
|
import { LineSparkline, BarSparkline } from "./sparklines/index.js";
|
|
64
72
|
import { Group } from "@visx/group";
|
|
65
73
|
import { GridRows, GridColumns } from "@visx/grid";
|
|
@@ -80,6 +88,7 @@ export {
|
|
|
80
88
|
AxisBottomDate,
|
|
81
89
|
AxisLeftNumeric,
|
|
82
90
|
AxisRightNumeric,
|
|
91
|
+
BandStrip,
|
|
83
92
|
Bar,
|
|
84
93
|
BarGroup,
|
|
85
94
|
BarSparkline,
|
|
@@ -99,11 +108,13 @@ export {
|
|
|
99
108
|
GridColumns,
|
|
100
109
|
GridRows,
|
|
101
110
|
Group,
|
|
111
|
+
HatchPattern,
|
|
102
112
|
Heatmap,
|
|
103
113
|
HoverOverlay,
|
|
104
114
|
Line,
|
|
105
115
|
LinePath,
|
|
106
116
|
LineSparkline,
|
|
117
|
+
MirroredBars,
|
|
107
118
|
MultiLine,
|
|
108
119
|
Pie,
|
|
109
120
|
SeriesDot,
|
|
@@ -133,8 +144,11 @@ export {
|
|
|
133
144
|
deriveTooltipRows,
|
|
134
145
|
fmtAxisDate,
|
|
135
146
|
fmtTooltipDate,
|
|
147
|
+
foldBands,
|
|
136
148
|
globalCursorStore,
|
|
137
149
|
groupTokens,
|
|
150
|
+
hatchFill,
|
|
151
|
+
hatchSizeFor,
|
|
138
152
|
maxTextWidth,
|
|
139
153
|
measureText,
|
|
140
154
|
probeAxisLabels,
|