@opendata-ai/openchart-engine 7.10.0 → 8.0.0-rc.1

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.
Files changed (159) hide show
  1. package/dist/index.d.ts +142 -7
  2. package/dist/index.js +16182 -10032
  3. package/dist/index.js.map +1 -1
  4. package/package.json +11 -4
  5. package/src/__tests__/__snapshots__/compile-snapshot.test.ts.snap +170 -56
  6. package/src/__tests__/annotation-behavior.test.ts +721 -0
  7. package/src/__tests__/axes.test.ts +50 -3
  8. package/src/__tests__/compile-chart.test.ts +30 -0
  9. package/src/__tests__/compile-footnotes.test.ts +277 -0
  10. package/src/__tests__/compile-layer.test.ts +120 -1
  11. package/src/__tests__/dimensions.test.ts +49 -4
  12. package/src/__tests__/helpers/invariants.ts +54 -20
  13. package/src/__tests__/known-bugs.test.ts +455 -2
  14. package/src/__tests__/legend.test.ts +120 -4
  15. package/src/__tests__/ranking-recipes.test.ts +260 -0
  16. package/src/__tests__/scales.test.ts +9 -3
  17. package/src/__tests__/series-search.test.ts +92 -0
  18. package/src/__tests__/spec-sugar.test.ts +801 -0
  19. package/src/__tests__/you-draw-it.test.ts +160 -0
  20. package/src/annotations/__tests__/compute.test.ts +207 -92
  21. package/src/annotations/__tests__/geometry.test.ts +66 -0
  22. package/src/annotations/__tests__/resolve-text.test.ts +527 -27
  23. package/src/annotations/__tests__/rich-text.test.ts +91 -0
  24. package/src/annotations/__tests__/thinning.test.ts +148 -0
  25. package/src/annotations/collisions.ts +130 -84
  26. package/src/annotations/compute.ts +83 -85
  27. package/src/annotations/constants.ts +116 -6
  28. package/src/annotations/geometry.ts +222 -77
  29. package/src/annotations/move.ts +135 -0
  30. package/src/annotations/placement.ts +62 -14
  31. package/src/annotations/resolve-range.ts +2 -0
  32. package/src/annotations/resolve-refline.ts +2 -0
  33. package/src/annotations/resolve-text.ts +312 -111
  34. package/src/annotations/rich-text.ts +65 -0
  35. package/src/annotations/thinning.ts +84 -10
  36. package/src/barlist/compile-barlist.ts +16 -6
  37. package/src/charts/_shared/format-label-value.ts +9 -8
  38. package/src/charts/bar/__tests__/compute.test.ts +57 -10
  39. package/src/charts/bar/__tests__/labels.test.ts +5 -4
  40. package/src/charts/bar/compute.ts +2 -6
  41. package/src/charts/bar/index.ts +8 -1
  42. package/src/charts/bar/labels.ts +3 -3
  43. package/src/charts/beeswarm/__tests__/compute.test.ts +280 -0
  44. package/src/charts/beeswarm/__tests__/dodge.test.ts +148 -0
  45. package/src/charts/beeswarm/compute.ts +203 -0
  46. package/src/charts/beeswarm/dodge.ts +155 -0
  47. package/src/charts/beeswarm/index.ts +32 -0
  48. package/src/charts/builtin.ts +12 -1
  49. package/src/charts/calendar/__tests__/compute.test.ts +417 -0
  50. package/src/charts/calendar/compute.ts +319 -0
  51. package/src/charts/calendar/index.ts +32 -0
  52. package/src/charts/column/__tests__/compute.test.ts +21 -7
  53. package/src/charts/column/__tests__/labels.test.ts +76 -1
  54. package/src/charts/column/compute.ts +2 -6
  55. package/src/charts/column/index.ts +10 -2
  56. package/src/charts/column/labels.ts +95 -21
  57. package/src/charts/dot/index.ts +8 -1
  58. package/src/charts/dot/labels.ts +3 -3
  59. package/src/charts/line/__tests__/compute.test.ts +15 -19
  60. package/src/charts/line/area.ts +8 -23
  61. package/src/charts/line/compute.ts +32 -2
  62. package/src/charts/parliament/__tests__/compute.test.ts +411 -0
  63. package/src/charts/parliament/compute.ts +313 -0
  64. package/src/charts/parliament/index.ts +32 -0
  65. package/src/charts/pie/__tests__/compute.test.ts +103 -0
  66. package/src/charts/pie/compute.ts +63 -8
  67. package/src/charts/pie/labels.ts +1 -0
  68. package/src/charts/range/__tests__/compute.test.ts +486 -0
  69. package/src/charts/range/compute.ts +273 -0
  70. package/src/charts/range/index.ts +82 -0
  71. package/src/charts/range/labels.ts +169 -0
  72. package/src/charts/rect/__tests__/compute.test.ts +120 -0
  73. package/src/charts/rect/index.ts +127 -0
  74. package/src/charts/scatter/compute.ts +7 -21
  75. package/src/charts/text/__tests__/compute.test.ts +307 -0
  76. package/src/charts/text/index.ts +44 -7
  77. package/src/charts/tick/__tests__/compute.test.ts +75 -0
  78. package/src/charts/tick/index.ts +7 -4
  79. package/src/charts/utils.ts +5 -3
  80. package/src/charts/waffle/__tests__/compute.test.ts +305 -0
  81. package/src/charts/waffle/compute.ts +197 -0
  82. package/src/charts/waffle/index.ts +31 -0
  83. package/src/compile/__tests__/color-scale-reverse.test.ts +89 -0
  84. package/src/compile/__tests__/data-clip.test.ts +68 -0
  85. package/src/compile/__tests__/fill-patterns.test.ts +154 -0
  86. package/src/compile/__tests__/size-scale.test.ts +108 -0
  87. package/src/compile/color-scale-range.ts +54 -33
  88. package/src/compile/data-clip.ts +21 -6
  89. package/src/compile/fill-patterns.ts +74 -0
  90. package/src/compile/layer.ts +117 -21
  91. package/src/compile/size-scale.ts +139 -0
  92. package/src/compile/spec-sugar.ts +758 -0
  93. package/src/compile/you-draw-it.ts +123 -0
  94. package/src/compile.ts +315 -103
  95. package/src/compiler/__tests__/a11y-warnings.test.ts +148 -0
  96. package/src/compiler/__tests__/fixtures/vl-parity/axis-null.json +19 -0
  97. package/src/compiler/__tests__/fixtures/vl-parity/color-value.json +20 -0
  98. package/src/compiler/__tests__/fixtures/vl-parity/count-aggregate.json +22 -0
  99. package/src/compiler/__tests__/fixtures/vl-parity/data-values.json +19 -0
  100. package/src/compiler/__tests__/fixtures/vl-parity/layer-axis-null.json +14 -0
  101. package/src/compiler/__tests__/fixtures/vl-parity/layer-count.json +34 -0
  102. package/src/compiler/__tests__/fixtures/vl-parity/layer-data-values.json +22 -0
  103. package/src/compiler/__tests__/fixtures/vl-parity/layer-legend-null.json +41 -0
  104. package/src/compiler/__tests__/fixtures/vl-parity/layer-scheme.json +38 -0
  105. package/src/compiler/__tests__/fixtures/vl-parity/layer-sort.json +28 -0
  106. package/src/compiler/__tests__/fixtures/vl-parity/layer-theta.json +28 -0
  107. package/src/compiler/__tests__/fixtures/vl-parity/layer-title.json +30 -0
  108. package/src/compiler/__tests__/fixtures/vl-parity/layer-value-def.json +29 -0
  109. package/src/compiler/__tests__/fixtures/vl-parity/legend-null.json +32 -0
  110. package/src/compiler/__tests__/fixtures/vl-parity/scheme.json +25 -0
  111. package/src/compiler/__tests__/fixtures/vl-parity/sort-by-value.json +19 -0
  112. package/src/compiler/__tests__/fixtures/vl-parity/theta-arc.json +19 -0
  113. package/src/compiler/__tests__/fixtures/vl-parity/title-subtitle.json +21 -0
  114. package/src/compiler/__tests__/fixtures/vl-parity/width-height.json +23 -0
  115. package/src/compiler/__tests__/normalize.test.ts +65 -1
  116. package/src/compiler/__tests__/validate-did-you-mean.test.ts +86 -0
  117. package/src/compiler/__tests__/validate-near-miss.test.ts +89 -0
  118. package/src/compiler/__tests__/validate.test.ts +156 -0
  119. package/src/compiler/__tests__/vl-parity.test.ts +68 -0
  120. package/src/compiler/a11y-warnings.ts +110 -0
  121. package/src/compiler/normalize.ts +150 -7
  122. package/src/compiler/types.ts +11 -0
  123. package/src/compiler/validate.ts +664 -18
  124. package/src/endpoint-labels/__tests__/compute.test.ts +88 -0
  125. package/src/endpoint-labels/compute.ts +40 -12
  126. package/src/endpoint-labels/format.ts +45 -15
  127. package/src/endpoint-labels/predict.ts +50 -36
  128. package/src/format/__tests__/field-format.test.ts +164 -0
  129. package/src/format/field-format.ts +27 -0
  130. package/src/geo/__tests__/compile-map.test.ts +621 -0
  131. package/src/geo/compile-map.ts +856 -0
  132. package/src/geo/join.ts +115 -0
  133. package/src/geo/projections.ts +45 -0
  134. package/src/geo/types.ts +24 -0
  135. package/src/graphs/__tests__/compile-graph.test.ts +25 -0
  136. package/src/graphs/compile-graph.ts +27 -18
  137. package/src/index.ts +28 -2
  138. package/src/layout/axes/ticks.ts +59 -10
  139. package/src/layout/axes.ts +30 -2
  140. package/src/layout/dimensions.ts +178 -95
  141. package/src/layout/facet.ts +14 -3
  142. package/src/layout/plan.ts +86 -35
  143. package/src/layout/scales.ts +132 -15
  144. package/src/legend/__tests__/continuous.test.ts +318 -0
  145. package/src/legend/__tests__/size.test.ts +348 -0
  146. package/src/legend/__tests__/suppression.test.ts +17 -1
  147. package/src/legend/compute.ts +126 -14
  148. package/src/legend/continuous.ts +327 -0
  149. package/src/legend/size.ts +407 -0
  150. package/src/legend/suppression.ts +8 -7
  151. package/src/legend/wrap.ts +8 -0
  152. package/src/sankey/compile-sankey.ts +31 -19
  153. package/src/tables/format-cells.ts +16 -7
  154. package/src/tilemap/__tests__/compile-tilemap.test.ts +39 -0
  155. package/src/tilemap/compile-tilemap.ts +24 -7
  156. package/src/tooltips/__tests__/compute.test.ts +2 -2
  157. package/src/tooltips/compute.ts +422 -41
  158. package/src/transforms/__tests__/conditional.test.ts +18 -0
  159. package/src/transforms/aggregate.ts +2 -1
@@ -0,0 +1,123 @@
1
+ /**
2
+ * "You draw it" resolution: computes the pixel geometry the vanilla adapter
3
+ * needs to render the hatched drawing region, capture pointer input, and
4
+ * mask/reveal the real line.
5
+ *
6
+ * Runs AFTER marks are computed (needs the target LineMark's pixel points)
7
+ * and needs the x scale to resolve `from` to a pixel position. Single-series
8
+ * line charts only; validateSpec rejects other combinations before this runs.
9
+ */
10
+
11
+ import type {
12
+ LineMark,
13
+ Mark,
14
+ Point,
15
+ Rect,
16
+ ResolvedYouDrawIt,
17
+ YouDrawItConfig,
18
+ YouDrawItSample,
19
+ } from '@opendata-ai/openchart-core';
20
+ import { resolvePosition } from '../annotations/position';
21
+ import type { ResolvedScales } from '../layout/scales';
22
+
23
+ /**
24
+ * Linear-invert two reference pixels through the y scale so the vanilla layer
25
+ * can map a drawn pixel-y back to a data value without the scale object.
26
+ * `.invert()` exists on continuous scales (linear/log/time/pow/sqrt/symlog);
27
+ * for band/ordinal y (never valid with a quantitative line here) it is
28
+ * undefined and this returns undefined, so onReveal falls back to pixel
29
+ * fractions.
30
+ */
31
+ function resolveYInvert(scaleY: ResolvedScales['y'], area: Rect): ResolvedYouDrawIt['yInvert'] {
32
+ if (!scaleY) return undefined;
33
+ const invert = (scaleY.scale as { invert?: (px: number) => number }).invert;
34
+ if (typeof invert !== 'function') return undefined;
35
+ const topData = invert.call(scaleY.scale, area.y);
36
+ const bottomData = invert.call(scaleY.scale, area.y + area.height);
37
+ if (!Number.isFinite(topData) || !Number.isFinite(bottomData)) return undefined;
38
+ return {
39
+ topPixel: area.y,
40
+ bottomPixel: area.y + area.height,
41
+ topData,
42
+ bottomData,
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Resolve `youDrawIt` into pixel geometry, or undefined when the config is
48
+ * absent, no line mark was produced (e.g. empty data), or `from` doesn't
49
+ * resolve to a position on the x scale.
50
+ */
51
+ export function resolveYouDrawIt(
52
+ config: YouDrawItConfig | undefined,
53
+ marks: Mark[],
54
+ scales: ResolvedScales,
55
+ chartArea: Rect,
56
+ xField: string | undefined,
57
+ ): ResolvedYouDrawIt | undefined {
58
+ if (!config || !scales.x) return undefined;
59
+
60
+ const targetLine = marks.find((m): m is LineMark => m.type === 'line');
61
+ if (!targetLine || targetLine.points.length === 0) return undefined;
62
+
63
+ const fromX = resolvePosition(config.from, scales.x);
64
+ if (fromX === null) return undefined;
65
+
66
+ // Pair each pixel-x sample at/after `from` with its data-x value, so the
67
+ // vanilla layer can report the guess in data coordinates on reveal. Prefer
68
+ // dataPoints (carries the original datum) and fall back to the raw point x
69
+ // when dataPoints is absent (e.g. a single-point degenerate line).
70
+ const seen = new Set<number>();
71
+ const samples: YouDrawItSample[] = [];
72
+ if (targetLine.dataPoints?.length) {
73
+ for (const dp of targetLine.dataPoints) {
74
+ if (dp.x < fromX - 0.5) continue;
75
+ if (seen.has(dp.x)) continue;
76
+ seen.add(dp.x);
77
+ const raw = xField ? dp.datum[xField] : undefined;
78
+ const xValue = typeof raw === 'string' || typeof raw === 'number' ? raw : dp.x;
79
+ samples.push({ px: dp.x, xValue });
80
+ }
81
+ }
82
+ if (samples.length === 0) {
83
+ // No dataPoints (or none past `from`): fall back to geometric point xs so
84
+ // drawing still snaps, reporting pixel x as the identity when we can't
85
+ // recover the data value.
86
+ for (const p of targetLine.points) {
87
+ if (p.x < fromX - 0.5) continue;
88
+ if (seen.has(p.x)) continue;
89
+ seen.add(p.x);
90
+ samples.push({ px: p.x, xValue: p.x });
91
+ }
92
+ }
93
+ samples.sort((a, b) => a.px - b.px);
94
+ if (samples.length === 0) return undefined;
95
+
96
+ let comparisonPoints: Point[] | undefined;
97
+ if (config.comparisonLine && config.comparisonLine.length > 0) {
98
+ const resolved: Point[] = [];
99
+ for (const { x, y } of config.comparisonLine) {
100
+ const px = resolvePosition(x, scales.x);
101
+ const py = scales.y ? resolvePosition(y, scales.y) : null;
102
+ if (px !== null && py !== null) resolved.push({ x: px, y: py });
103
+ }
104
+ if (resolved.length > 0) {
105
+ resolved.sort((a, b) => a.x - b.x);
106
+ comparisonPoints = resolved;
107
+ }
108
+ }
109
+
110
+ const yInvert = resolveYInvert(scales.y, chartArea);
111
+
112
+ return {
113
+ fromX,
114
+ area: chartArea,
115
+ samples,
116
+ prompt: config.prompt ?? 'Draw your guess',
117
+ revealLabel: config.revealLabel ?? 'Show me',
118
+ lineColor: targetLine.stroke,
119
+ targetSeriesKey: targetLine.seriesKey,
120
+ ...(yInvert ? { yInvert } : {}),
121
+ ...(comparisonPoints ? { comparisonPoints } : {}),
122
+ };
123
+ }