@sophistry/charts 0.0.0-stage → 0.1.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.
Files changed (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -2
  3. package/dist/3d/bar-chart3d.d.ts +55 -0
  4. package/dist/3d/definitions.d.ts +37 -0
  5. package/dist/3d/definitions.js +14 -0
  6. package/dist/3d/forward.d.ts +64 -0
  7. package/dist/3d/index.d.ts +30 -0
  8. package/dist/3d/index.js +1 -0
  9. package/dist/3d/quiver3d.d.ts +52 -0
  10. package/dist/3d/scatter3d.d.ts +44 -0
  11. package/dist/3d/stem3d.d.ts +45 -0
  12. package/dist/3d/surface-grid3d.d.ts +33 -0
  13. package/dist/3d/tri-surface3d.d.ts +45 -0
  14. package/dist/3d/voxels3d.d.ts +25 -0
  15. package/dist/3d/wireframe3d.d.ts +30 -0
  16. package/dist/band.d.ts +20 -0
  17. package/dist/bars/bar-chart.d.ts +143 -0
  18. package/dist/bars/bar-labels.d.ts +116 -0
  19. package/dist/bars/bars.d.ts +223 -0
  20. package/dist/bars/bullet.d.ts +157 -0
  21. package/dist/bars/candlestick.d.ts +97 -0
  22. package/dist/bars/funnel.d.ts +90 -0
  23. package/dist/bars/histogram.d.ts +108 -0
  24. package/dist/bars/index.d.ts +22 -0
  25. package/dist/bars/race.d.ts +28 -0
  26. package/dist/bars/rules.d.ts +121 -0
  27. package/dist/bars/shared.d.ts +41 -0
  28. package/dist/bars/transforms.d.ts +249 -0
  29. package/dist/bars/waterfall.d.ts +106 -0
  30. package/dist/batch.d.ts +142 -0
  31. package/dist/channels-_Xf-p6Lx.js +56 -0
  32. package/dist/chart.d.ts +87 -0
  33. package/dist/color-norm.d.ts +90 -0
  34. package/dist/context.d.ts +111 -0
  35. package/dist/curves/density.d.ts +125 -0
  36. package/dist/curves/ecdf.d.ts +72 -0
  37. package/dist/curves/fill-between.d.ts +100 -0
  38. package/dist/curves/index.d.ts +15 -0
  39. package/dist/curves/line-plot.d.ts +104 -0
  40. package/dist/curves/regression.d.ts +124 -0
  41. package/dist/curves/shared.d.ts +52 -0
  42. package/dist/curves/stack-plot.d.ts +140 -0
  43. package/dist/curves/stairs.d.ts +170 -0
  44. package/dist/data/channels.d.ts +170 -0
  45. package/dist/end-space.d.ts +81 -0
  46. package/dist/entries/definitions.d.ts +20 -0
  47. package/dist/entries/definitions.js +6 -0
  48. package/dist/frame/band-axis.d.ts +42 -0
  49. package/dist/frame/coords.d.ts +111 -0
  50. package/dist/frame/fit.d.ts +170 -0
  51. package/dist/frame/format.d.ts +40 -0
  52. package/dist/frame/guide-metrics.d.ts +36 -0
  53. package/dist/frame/guides.d.ts +67 -0
  54. package/dist/frame/keys.d.ts +96 -0
  55. package/dist/frame/layout.d.ts +145 -0
  56. package/dist/frame/registry.d.ts +31 -0
  57. package/dist/frame/reports.d.ts +53 -0
  58. package/dist/frame/secondary-axes.d.ts +73 -0
  59. package/dist/frame/secondary.d.ts +56 -0
  60. package/dist/frame/tooltip-overlay.d.ts +64 -0
  61. package/dist/frame/types.d.ts +658 -0
  62. package/dist/grids/barbs.d.ts +51 -0
  63. package/dist/grids/cell-rects.d.ts +37 -0
  64. package/dist/grids/cells.d.ts +130 -0
  65. package/dist/grids/contour-f.d.ts +80 -0
  66. package/dist/grids/contour-shared.d.ts +53 -0
  67. package/dist/grids/contour.d.ts +84 -0
  68. package/dist/grids/dendrogram.d.ts +104 -0
  69. package/dist/grids/heatmap.d.ts +163 -0
  70. package/dist/grids/hex-bin.d.ts +93 -0
  71. package/dist/grids/hist2d.d.ts +107 -0
  72. package/dist/grids/imshow.d.ts +84 -0
  73. package/dist/grids/index.d.ts +26 -0
  74. package/dist/grids/pcolormesh.d.ts +90 -0
  75. package/dist/grids/ramp-cells.d.ts +66 -0
  76. package/dist/grids/tri-contour.d.ts +120 -0
  77. package/dist/grids/tri-shared.d.ts +61 -0
  78. package/dist/grids/tripcolor.d.ts +73 -0
  79. package/dist/guides/colorbar.d.ts +110 -0
  80. package/dist/guides/index.d.ts +11 -0
  81. package/dist/guides/legend.d.ts +118 -0
  82. package/dist/guides/nodes.d.ts +13 -0
  83. package/dist/guides/size-legend.d.ts +233 -0
  84. package/dist/hierarchy/breadcrumbs.d.ts +133 -0
  85. package/dist/hierarchy/circle-pack.d.ts +72 -0
  86. package/dist/hierarchy/drill.d.ts +245 -0
  87. package/dist/hierarchy/frame.d.ts +67 -0
  88. package/dist/hierarchy/icicle.d.ts +76 -0
  89. package/dist/hierarchy/index.d.ts +20 -0
  90. package/dist/hierarchy/labels.d.ts +24 -0
  91. package/dist/hierarchy/mosaic.d.ts +130 -0
  92. package/dist/hierarchy/own-tooltip.d.ts +12 -0
  93. package/dist/hierarchy/props.d.ts +13 -0
  94. package/dist/hierarchy/sankey.d.ts +132 -0
  95. package/dist/hierarchy/shared.d.ts +247 -0
  96. package/dist/hierarchy/sunburst.d.ts +74 -0
  97. package/dist/hierarchy/tree.d.ts +124 -0
  98. package/dist/hierarchy/treemap.d.ts +76 -0
  99. package/dist/index.d.ts +29 -0
  100. package/dist/index.js +5 -0
  101. package/dist/item-tooltip.d.ts +33 -0
  102. package/dist/join.d.ts +223 -0
  103. package/dist/math/3d/bar3d.d.ts +27 -0
  104. package/dist/math/3d/quiver3d.d.ts +26 -0
  105. package/dist/math/3d/scatter3d.d.ts +15 -0
  106. package/dist/math/3d/stem3d.d.ts +22 -0
  107. package/dist/math/3d/surfaceGrid3d.d.ts +33 -0
  108. package/dist/math/3d/trisurface.d.ts +11 -0
  109. package/dist/math/3d/voxels.d.ts +17 -0
  110. package/dist/math/aggregate.d.ts +68 -0
  111. package/dist/math/bar.d.ts +31 -0
  112. package/dist/math/barLabels.d.ts +83 -0
  113. package/dist/math/barbs.d.ts +36 -0
  114. package/dist/math/boxplot.d.ts +36 -0
  115. package/dist/math/breadcrumbs.d.ts +128 -0
  116. package/dist/math/bubble.d.ts +38 -0
  117. package/dist/math/bullet.d.ts +110 -0
  118. package/dist/math/chord.d.ts +103 -0
  119. package/dist/math/cluster.d.ts +88 -0
  120. package/dist/math/contour.d.ts +48 -0
  121. package/dist/math/contourf.d.ts +50 -0
  122. package/dist/math/dodge.d.ts +36 -0
  123. package/dist/math/ecdf.d.ts +41 -0
  124. package/dist/math/errorbar.d.ts +27 -0
  125. package/dist/math/eventplot.d.ts +26 -0
  126. package/dist/math/facet.d.ts +90 -0
  127. package/dist/math/fillBetween.d.ts +28 -0
  128. package/dist/math/gauge.d.ts +71 -0
  129. package/dist/math/hexbin.d.ts +20 -0
  130. package/dist/math/hierarchy.d.ts +179 -0
  131. package/dist/math/hierarchyJoin.d.ts +59 -0
  132. package/dist/math/histogram.d.ts +36 -0
  133. package/dist/math/histogram2d.d.ts +44 -0
  134. package/dist/math/imshow.d.ts +26 -0
  135. package/dist/math/index.d.ts +139 -0
  136. package/dist/math/index.js +3 -0
  137. package/dist/math/jitter.d.ts +16 -0
  138. package/dist/math/join.d.ts +135 -0
  139. package/dist/math/keyframes.d.ts +127 -0
  140. package/dist/math/legend.d.ts +120 -0
  141. package/dist/math/line.d.ts +53 -0
  142. package/dist/math/morph.d.ts +81 -0
  143. package/dist/math/mosaic.d.ts +119 -0
  144. package/dist/math/ordinal.d.ts +79 -0
  145. package/dist/math/parallel.d.ts +38 -0
  146. package/dist/math/pcolormesh.d.ts +22 -0
  147. package/dist/math/pie.d.ts +105 -0
  148. package/dist/math/polarArea.d.ts +34 -0
  149. package/dist/math/radar.d.ts +110 -0
  150. package/dist/math/range.d.ts +98 -0
  151. package/dist/math/regression.d.ts +109 -0
  152. package/dist/math/reveal.d.ts +63 -0
  153. package/dist/math/sankey.d.ts +154 -0
  154. package/dist/math/scatter.d.ts +14 -0
  155. package/dist/math/shared/binning.d.ts +23 -0
  156. package/dist/math/shared/gridCells.d.ts +41 -0
  157. package/dist/math/shared/gridExtent.d.ts +5 -0
  158. package/dist/math/shared/pairs.d.ts +2 -0
  159. package/dist/math/shared/polar.d.ts +23 -0
  160. package/dist/math/stack.d.ts +69 -0
  161. package/dist/math/stackplot.d.ts +35 -0
  162. package/dist/math/stairs.d.ts +17 -0
  163. package/dist/math/stem.d.ts +21 -0
  164. package/dist/math/symbol.d.ts +25 -0
  165. package/dist/math/tree.d.ts +117 -0
  166. package/dist/math/tricontour.d.ts +76 -0
  167. package/dist/math/violin.d.ts +99 -0
  168. package/dist/math/waffle.d.ts +48 -0
  169. package/dist/math/waterfall.d.ts +28 -0
  170. package/dist/math-CSHNpGej.js +3648 -0
  171. package/dist/mix.d.ts +24 -0
  172. package/dist/multiview/brush.d.ts +165 -0
  173. package/dist/multiview/chart-group.d.ts +265 -0
  174. package/dist/multiview/chart-link.d.ts +188 -0
  175. package/dist/multiview/chart-zoom.d.ts +144 -0
  176. package/dist/multiview/facet.d.ts +238 -0
  177. package/dist/multiview/group-guides.d.ts +99 -0
  178. package/dist/multiview/index.d.ts +17 -0
  179. package/dist/multiview/joint-plot.d.ts +114 -0
  180. package/dist/multiview/pair-plot.d.ts +153 -0
  181. package/dist/multiview/panels.d.ts +22 -0
  182. package/dist/multiview/parallel-coordinates.d.ts +109 -0
  183. package/dist/points/event-plot.d.ts +67 -0
  184. package/dist/points/index.d.ts +19 -0
  185. package/dist/points/labels.d.ts +70 -0
  186. package/dist/points/links.d.ts +123 -0
  187. package/dist/points/rects.d.ts +80 -0
  188. package/dist/points/rug.d.ts +72 -0
  189. package/dist/points/scatter.d.ts +169 -0
  190. package/dist/points/segment-marks.d.ts +39 -0
  191. package/dist/points/shared.d.ts +34 -0
  192. package/dist/points/stem.d.ts +75 -0
  193. package/dist/points/strip.d.ts +145 -0
  194. package/dist/points/symbol-marker.d.ts +33 -0
  195. package/dist/points/ticks.d.ts +102 -0
  196. package/dist/props.d.ts +126 -0
  197. package/dist/radial/chord.d.ts +148 -0
  198. package/dist/radial/gauge.d.ts +126 -0
  199. package/dist/radial/index.d.ts +15 -0
  200. package/dist/radial/pie-chart.d.ts +143 -0
  201. package/dist/radial/polar-area-chart.d.ts +135 -0
  202. package/dist/radial/radar-chart.d.ts +176 -0
  203. package/dist/radial/radial-bar-chart.d.ts +116 -0
  204. package/dist/radial/shared.d.ts +78 -0
  205. package/dist/radial/waffle.d.ts +130 -0
  206. package/dist/raster.d.ts +43 -0
  207. package/dist/series.d.ts +71 -0
  208. package/dist/src-CwGo1bes.js +19221 -0
  209. package/dist/stagger.d.ts +54 -0
  210. package/dist/statistics/box-plot.d.ts +151 -0
  211. package/dist/statistics/error-bar.d.ts +148 -0
  212. package/dist/statistics/groups.d.ts +140 -0
  213. package/dist/statistics/index.d.ts +7 -0
  214. package/dist/statistics/violin-plot.d.ts +143 -0
  215. package/dist/text-width.d.ts +9 -0
  216. package/dist/tooltip.d.ts +276 -0
  217. package/dist/util.d.ts +33 -0
  218. package/dist/voxels-9lJ2TZS4.js +235 -0
  219. package/dist/wireframe3d-D157GZAq.js +345 -0
  220. package/package.json +86 -3
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Data transforms: plain functions from rows to rows, applied to `data`
3
+ * before it reaches a mark, composing by nesting (`stack(group(rows, ...))`).
4
+ * Derived rows share field names (`x` position, `y` value, `z` series, the
5
+ * input kept as `datum` or `rows`), so they chain without renaming. Dates
6
+ * in an `x` or `by` channel are read as epoch milliseconds.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import type { BandKey } from "@sophistry/core/geometry";
11
+ import type { Channel, PositionValue } from "../data/channels.js";
12
+ import type { NormalizeBasis, Reducer, RollingOptions } from "../math/aggregate.js";
13
+ import type { HistogramOptions } from "../math/histogram.js";
14
+ import type { StackOffset } from "../math/stack.js";
15
+ /** @category Transforms */
16
+ export interface StackOptions<T> {
17
+ /** The position rows stack at; rows sharing an `x` stack on each other. Omitted, all rows stack in one column. */
18
+ x?: Channel<T, BandKey | PositionValue>;
19
+ /** The value. Defaults to the datum itself, for `number[]` data. */
20
+ y?: Channel<T, number>;
21
+ /** The series a row belongs to; series stack in `order`. Omitted, rows stack in data order. */
22
+ z?: Channel<T, BandKey>;
23
+ /**
24
+ * `"zero"`, `"normalize"` (each column 0..1), `"center"` or `"wiggle"` (a
25
+ * streamgraph). See {@link StackOffset}.
26
+ * @default "zero"
27
+ */
28
+ offset?: StackOffset;
29
+ /**
30
+ * Which series sits at the bottom: `"appearance"`, `"reverse"`, `"sum"`
31
+ * (largest on top), `"insideOut"`, or the series keys bottom to top.
32
+ * @default "appearance"
33
+ */
34
+ order?: "appearance" | "reverse" | "sum" | "insideOut" | readonly BandKey[];
35
+ }
36
+ /** @category Transforms */
37
+ export interface StackedRow<T> {
38
+ /** The input row. */
39
+ datum: T;
40
+ /** Its index in the input. */
41
+ index: number;
42
+ /** Its position, as given (undefined without `x`). */
43
+ x: BandKey | undefined;
44
+ /** Its series, as given (undefined without `z`). */
45
+ z: BandKey | undefined;
46
+ /** Its series' 0-based place in first-seen order: cycle a palette by this. */
47
+ zIndex: number;
48
+ /** Its value, as given. */
49
+ y: number;
50
+ /** Where its segment starts (towards the baseline); `NaN` when `y` is not finite. */
51
+ y1: number;
52
+ /** Where its segment ends; `NaN` when `y` is not finite. */
53
+ y2: number;
54
+ }
55
+ /**
56
+ * Stacks rows sharing an `x`, series by series, giving each a `y1` (segment
57
+ * start) and `y2` (segment end): feed them to `bars.create({ base: "y1", value: "y2" })`
58
+ * or any mark with lower and upper channels. Positive values stack up from
59
+ * zero and negative ones down, so diverging stacks need nothing extra.
60
+ *
61
+ * @returns One {@link StackedRow} per input row, in input order.
62
+ * @see https://sophistry.dev/guides/charts/#transforms
63
+ * @category Transforms
64
+ */
65
+ export declare function stack<T>(data: readonly T[], options?: StackOptions<T>): StackedRow<T>[];
66
+ /** @category Transforms */
67
+ export interface DodgeOptions<T> {
68
+ /** The category whose band the rows share; required for `compact`. */
69
+ x?: Channel<T, BandKey | PositionValue>;
70
+ /** The value, copied to each row as `y`. Defaults to the datum itself, for `number[]` data. */
71
+ y?: Channel<T, number>;
72
+ /** The series that split a band, side by side in first-seen order. */
73
+ z: Channel<T, BandKey>;
74
+ /** Fraction of each sub-band left empty between neighbours, 0..1. @default 0.1 */
75
+ padding?: number;
76
+ /**
77
+ * Split each band only among the series present in it. Off, every series
78
+ * keeps its place in every band, so it reads at the same position across
79
+ * categories.
80
+ * @default false
81
+ */
82
+ compact?: boolean;
83
+ }
84
+ /** @category Transforms */
85
+ export interface DodgedRow<T> {
86
+ datum: T;
87
+ index: number;
88
+ x: BandKey | undefined;
89
+ z: BandKey;
90
+ /** Its series' 0-based place in first-seen order. */
91
+ zIndex: number;
92
+ y: number;
93
+ /** The part of its category's band this row takes, as fractions `[from, to]`: `bars.create({ subband: "subband" })`. */
94
+ subband: [number, number];
95
+ }
96
+ /**
97
+ * Splits each category's band among its series, for grouped bars: each row
98
+ * gets a `subband` that `bars` (`subband`) draws.
99
+ *
100
+ * @returns One {@link DodgedRow} per input row, in input order.
101
+ * @see https://sophistry.dev/guides/charts/#transforms
102
+ * @category Transforms
103
+ */
104
+ export declare function dodge<T>(data: readonly T[], options: DodgeOptions<T>): DodgedRow<T>[];
105
+ /** @category Transforms */
106
+ export interface GroupOptions<T> {
107
+ /** What to group by: one channel (the key becomes `x`), or two (`[x, z]`, ready for `stack` or `dodge`). */
108
+ by: Channel<T, BandKey | PositionValue> | readonly [
109
+ Channel<T, BandKey | PositionValue>,
110
+ Channel<T, BandKey | PositionValue>
111
+ ];
112
+ /** The values to reduce. Defaults to the datum itself, for `number[]` data. */
113
+ y?: Channel<T, number>;
114
+ /** How each group's values become its `y`. @default "count" */
115
+ reduce?: Reducer;
116
+ }
117
+ /** @category Transforms */
118
+ export interface GroupedRow<T> {
119
+ /** The group's (first) key. */
120
+ x: BandKey;
121
+ /** The group's second key, when grouped by two. */
122
+ z: BandKey | undefined;
123
+ /** The reduced value. */
124
+ y: number;
125
+ /** The input rows in the group, in input order. */
126
+ rows: T[];
127
+ /** Their indices in the input. */
128
+ indexes: number[];
129
+ }
130
+ /**
131
+ * Groups rows by one or two keys and reduces each group to one number:
132
+ * counts per category, sums per category and series, means, medians, ...
133
+ *
134
+ * @returns One {@link GroupedRow} per group, in first-seen order.
135
+ * @see https://sophistry.dev/guides/charts/#transforms
136
+ * @category Transforms
137
+ */
138
+ export declare function group<T>(data: readonly T[], options: GroupOptions<T>): GroupedRow<T>[];
139
+ /** @category Transforms */
140
+ export interface BinOptions<T, X extends PositionValue = PositionValue> extends HistogramOptions {
141
+ /**
142
+ * The value binned along x; dates bin in equal spans of milliseconds. Defaults to the datum
143
+ * itself, for `number[]` data.
144
+ */
145
+ x?: Channel<T, X>;
146
+ /** The values `reduce` reads in each bin. Defaults to `x`'s. */
147
+ y?: Channel<T, number>;
148
+ /** How each bin's rows become its `y`. @default "count" */
149
+ reduce?: Reducer;
150
+ }
151
+ /** @category Transforms */
152
+ export interface BinnedRow<T> {
153
+ /** The bin's lower edge. */
154
+ x1: number;
155
+ /** Its upper edge. */
156
+ x2: number;
157
+ /** Its centre. */
158
+ x: number;
159
+ /** The reduced value: the count, by default. */
160
+ y: number;
161
+ rows: T[];
162
+ indexes: number[];
163
+ }
164
+ /**
165
+ * Bins rows into equal-width buckets along x (`binCount`, or a `range`
166
+ * step) and reduces each bin: a histogram of counts, sums or means. Rows
167
+ * with a non-finite or out-of-range `x` fall in no bin.
168
+ *
169
+ * @returns One {@link BinnedRow} per bin, left to right, empty bins included.
170
+ * @see https://sophistry.dev/guides/charts/#transforms
171
+ * @category Transforms
172
+ */
173
+ export declare function bin<T, X extends PositionValue = PositionValue>(data: readonly T[], options?: BinOptions<T, X>): BinnedRow<T>[];
174
+ /** @category Transforms */
175
+ export interface SummarizeOptions<T> {
176
+ /** The position rows are pooled at: rows sharing an `x` form one sample. */
177
+ x: Channel<T, BandKey | PositionValue>;
178
+ /** The value. Defaults to the datum itself, for `number[]` data. */
179
+ y?: Channel<T, number>;
180
+ /** `"ci"` (a t-based confidence interval of the mean), `"se"` or `"sd"`. @default "ci" */
181
+ interval?: "ci" | "se" | "sd";
182
+ /** Confidence level for `"ci"`, 0..1. @default 0.95 */
183
+ level?: number;
184
+ }
185
+ /** @category Transforms */
186
+ export interface SummaryRow<T> {
187
+ x: BandKey;
188
+ /** The mean. */
189
+ y: number;
190
+ low: number;
191
+ high: number;
192
+ /** Finite values pooled. */
193
+ n: number;
194
+ rows: T[];
195
+ }
196
+ /**
197
+ * Pools replicate rows by `x` into a mean and an interval around it. Draw
198
+ * `y` with a `LinePlot` and the interval with `fillBetween` (`y1: "high", y2: "low"`) for a confidence band.
199
+ *
200
+ * @returns One {@link SummaryRow} per `x`: ascending when every `x` is a number, else first-seen.
201
+ * @see https://sophistry.dev/guides/charts/#transforms
202
+ * @category Transforms
203
+ */
204
+ export declare function summarize<T>(data: readonly T[], options: SummarizeOptions<T>): SummaryRow<T>[];
205
+ /** @category Transforms */
206
+ export interface RollingTransformOptions<T> extends RollingOptions {
207
+ /** The series, in order. Defaults to the datum itself, for `number[]` data. */
208
+ y?: Channel<T, number>;
209
+ }
210
+ /**
211
+ * A moving-window reduction down the rows (a rolling mean by default), in
212
+ * the order given: one number per row, for a channel such as
213
+ * `y={(_, i) => smooth[i]}`.
214
+ *
215
+ * @category Transforms
216
+ */
217
+ export declare function rolling<T>(data: readonly T[], options?: RollingTransformOptions<T>): number[];
218
+ /** @category Transforms */
219
+ export interface NormalizeOptions<T> {
220
+ /** The series. Defaults to the datum itself, for `number[]` data. */
221
+ y?: Channel<T, number>;
222
+ /** What to normalize against. See {@link NormalizeBasis}. @default "first" */
223
+ basis?: NormalizeBasis;
224
+ }
225
+ /**
226
+ * Normalizes a series against a basis (its first value, sum, extent, ...):
227
+ * one number per row.
228
+ *
229
+ * @category Transforms
230
+ */
231
+ export declare function normalize<T>(data: readonly T[], options?: NormalizeOptions<T>): number[];
232
+ /** @category Transforms */
233
+ export interface JitterTransformOptions<T> {
234
+ /**
235
+ * What each row's offset hashes: something stable, such as an id. Defaults to the row's index.
236
+ */
237
+ key?: Channel<T, string | number>;
238
+ /** Total width the offsets spread over, centred on 0. @default 1 */
239
+ width?: number;
240
+ /** Varies the pattern. @default 0 */
241
+ seed?: number;
242
+ }
243
+ /**
244
+ * Seeded jitter: one offset per row in `[-width / 2, width / 2)`, hashed
245
+ * from the row's `key` and `seed`, so it is stable across frames and scrubs.
246
+ *
247
+ * @category Transforms
248
+ */
249
+ export declare function jitter<T>(data: readonly T[], options?: JitterTransformOptions<T>): number[];
@@ -0,0 +1,106 @@
1
+ /**
2
+ * `waterfall`: how a starting value became a final one, change by change. A
3
+ * preset: a `chart` whose children are a `bars` layer (floating steps) and a
4
+ * `ruleY` layer (the dashed connectors), then the user's children.
5
+ */
6
+ import type { AxisOptions, SceneNode } from "@sophistry/core";
7
+ import type { ColorInput } from "@sophistry/core/color";
8
+ import type { Point, Range } from "@sophistry/core/geometry";
9
+ import type { Channel } from "../data/channels.js";
10
+ import type { TooltipSpec } from "../tooltip.js";
11
+ /**
12
+ * Props of {@link waterfall}: `value` is required unless `data` is `number[]`.
13
+ *
14
+ * @category Charts
15
+ */
16
+ export interface WaterfallProps<T = unknown> {
17
+ /** One step per datum, in order. */
18
+ data: readonly T[];
19
+ /**
20
+ * The change this step makes. Defaults to the datum when `data` is `number[]`; ignored on a
21
+ * total.
22
+ */
23
+ value?: Channel<T, number>;
24
+ /** The name under each bar. Omitted, no names are drawn. */
25
+ label?: Channel<T, string>;
26
+ /** Marks a subtotal/total bar, drawn from zero to the running total. */
27
+ total?: Channel<T, boolean>;
28
+ /** Width of the plotting area. */
29
+ width: number;
30
+ /** Height of the plotting area. */
31
+ height: number;
32
+ /** Centre of the plotting area. Defaults to the origin. */
33
+ center?: Point;
34
+ /** `[min, max, step?]` for the value axis. Omitted, fitted to the running total, including zero. */
35
+ yRange?: Range;
36
+ /** Styling and tick options for the value axis. */
37
+ yAxis?: AxisOptions;
38
+ /**
39
+ * Bar width as a fraction of its slot.
40
+ * @default 0.6
41
+ */
42
+ barWidth?: number;
43
+ /** Colour of an increase. Defaults to the theme's positive colour. */
44
+ upColor?: ColorInput;
45
+ /** Colour of a decrease. Defaults to the theme's negative colour. */
46
+ downColor?: ColorInput;
47
+ /** Colour of a total. Defaults to the theme's first series colour. */
48
+ totalColor?: ColorInput;
49
+ /**
50
+ * Write each step's change past the bar's end (`+20`, `−30`).
51
+ * @default true
52
+ */
53
+ labels?: boolean;
54
+ /**
55
+ * Draw the dashed connector from each bar's end to the next bar's start.
56
+ * @default true
57
+ */
58
+ connectors?: boolean;
59
+ /** Title above the chart. */
60
+ title?: string;
61
+ /**
62
+ * Reveal, 0..1: the frame, then the steps left to right (each growing from the running total),
63
+ * connectors after.
64
+ * @see https://sophistry.dev/guides/chart-animation/#reveals
65
+ */
66
+ progress?: number;
67
+ /**
68
+ * Fraction of the data reveal spent staggering step after step, 0..0.95.
69
+ * @default 0.6
70
+ */
71
+ stagger?: number;
72
+ /** Hover tooltip per step. Defaults to the step's name and change. */
73
+ tooltip?: TooltipSpec<T>;
74
+ zIndex?: number;
75
+ visible?: boolean;
76
+ /** Placed inside the chart's coordinate context (slot `i` is centred at `i + 0.5`). */
77
+ children?: readonly SceneNode[];
78
+ }
79
+ /**
80
+ * A waterfall chart: how a starting value became a final one, change by
81
+ * change. Each bar floats from the running total before it to the total
82
+ * after; `total` bars stand on zero. A preset over `chart`, {@link bars}
83
+ * and {@link ruleY}.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { createScene } from "@sophistry/core";
88
+ * import { waterfall } from "@sophistry/charts";
89
+ *
90
+ * const scene = createScene({ host: document.querySelector("#figure")!, units: 10 });
91
+ * scene.add(
92
+ * waterfall.create({
93
+ * data: [{ name: "Start", v: 100 }, { name: "Sales", v: 40 }, { name: "Costs", v: -25 }, { name: "End", total: true }],
94
+ * value: "v",
95
+ * label: "name",
96
+ * total: "total",
97
+ * width: 8,
98
+ * height: 4,
99
+ * }),
100
+ * );
101
+ * ```
102
+ *
103
+ * @see https://sophistry.dev/reference/chart-catalogue/#waterfalls-funnels-and-candlesticks
104
+ * @category Charts
105
+ */
106
+ export declare const waterfall: import("@sophistry/core").Definition<WaterfallProps<any>, import("@sophistry/core/internal").CompositeNode<WaterfallProps<any>>, keyof WaterfallProps<any>>;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The batched-mark helper every per-datum mark draws through: one
3
+ * `instances()` node for the whole layer, keyed by datum key.
4
+ *
5
+ * A per-datum mark is always one instances node:
6
+ *
7
+ * - **Items.** The mark computes one plain item per drawn key on each update
8
+ * (its scene-unit position, size, colour and opacity at this frame of the
9
+ * reveal or keyed `to`/`blend` transition) and hands them over with
10
+ * {@link BatchedMark.update}. The node reconciles them by `key`.
11
+ * - **Seekable transitions** (`to` + `blend`, reveals, range transitions)
12
+ * are computed by the mark, so every frame is exact and scrubs: the node
13
+ * is updated instantly.
14
+ * - **Clock-driven transitions** (the mark's `transition` prop): when the
15
+ * mark's data changes and no `to` is given, the node tweens (or springs)
16
+ * kept items to their new values in its tween bank, entering items from
17
+ * the mark's enter state and exiting ones to its exit state. Only data
18
+ * changes animate this way; a reveal or a range change stays exact.
19
+ * - **Picking.** Handlers get `event.item` (the spec index) and `event.key`;
20
+ * {@link BatchedMark.itemAt} turns either into the mark's item.
21
+ * - **Individuality.** `node.promote(key)` gives one item a real node.
22
+ *
23
+ * The first items a mark draws appear in place (its reveal brings them in);
24
+ * only later data changes move through the bank.
25
+ *
26
+ * Every enter/exit prop must also be a channel, so turning a transition on
27
+ * or off never rebuilds the node's bank.
28
+ */
29
+ import type { Bindable, Definition, InstanceChannels, InstancesNode, InstanceTiming, InstanceValues, SceneNode } from "@sophistry/core";
30
+ import type { BandKey } from "@sophistry/core/geometry";
31
+ /**
32
+ * A per-datum mark's `transition` prop: how its marks move when its `data`
33
+ * changes (not during a `to`/`blend` transition, which is seekable). A
34
+ * tween (`duration`, `easing`) or a spring (`spring`), with `delay` and
35
+ * `stagger`. `enter` / `exit` say whether new marks grow in and departing
36
+ * ones shrink out (each mark decides how), with their own timing if given.
37
+ *
38
+ * @see https://sophistry.dev/guides/chart-animation/#data-transitions
39
+ * @category Charts
40
+ */
41
+ export interface MarkTransition extends InstanceTiming {
42
+ /**
43
+ * Entering marks grow in the way the mark reveals; `false` makes them
44
+ * appear at once. @default true
45
+ */
46
+ enter?: boolean | InstanceTiming;
47
+ /**
48
+ * Departing marks shrink out the way the mark reveals, reversed; `false`
49
+ * removes them at once. @default true
50
+ */
51
+ exit?: boolean | InstanceTiming;
52
+ }
53
+ /** An item of a batched mark: anything with the datum's key. */
54
+ export interface BatchItem {
55
+ key: BandKey;
56
+ }
57
+ /**
58
+ * Options of {@link createBatchedMark}.
59
+ *
60
+ * @category Extending
61
+ */
62
+ export interface BatchedMarkOptions<D, P, I extends keyof P> {
63
+ /** Per-item props read off the item; keep them stable (made once). */
64
+ channels: InstanceChannels<D, P, I>;
65
+ /** Where an entering item starts under a `transition` (its keys must be channels). */
66
+ enter?: InstanceValues<D, P, I>;
67
+ /** Where an exiting item ends under a `transition` (its keys must be channels). */
68
+ exit?: InstanceValues<D, P, I>;
69
+ /** Props every item shares from the start (any prop; a `Readable` binds). */
70
+ shared?: Bindable<P>;
71
+ }
72
+ /**
73
+ * A batched mark: its node, and the update it is driven by.
74
+ *
75
+ * @category Extending
76
+ */
77
+ export interface BatchedMark<D extends BatchItem, P extends object, N extends SceneNode<P>, I extends keyof P> {
78
+ /** The instances node; put it in the mark's children. */
79
+ readonly node: InstancesNode<D, P, N, I, BandKey>;
80
+ /**
81
+ * Writes one update's items and shared props. With `transition` (and
82
+ * `animate` true) changed items move through the node's tween bank;
83
+ * otherwise the change is instant.
84
+ */
85
+ update(items: readonly D[], shared?: Bindable<P>, motion?: {
86
+ transition: MarkTransition | undefined;
87
+ animate: boolean;
88
+ }): void;
89
+ /** The item at a spec index (`event.item`), or undefined (an exiting item, or none). */
90
+ itemAt(index: number | null | undefined): D | undefined;
91
+ /** The current item with `key`, or undefined. */
92
+ item(key: BandKey): D | undefined;
93
+ /** The current items, in order. */
94
+ readonly items: readonly D[];
95
+ }
96
+ /**
97
+ * Makes the one instances node of a per-datum mark. Call once, in `setup`;
98
+ * call `update` in every `update` of the mark.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { type CompositeContext, circle, defineComposite, Invalidate } from "@sophistry/core";
103
+ * import { createBatchedMark } from "@sophistry/charts";
104
+ *
105
+ * interface DotsProps {
106
+ * points: readonly { x: number; y: number }[];
107
+ * }
108
+ * interface Dot {
109
+ * key: number;
110
+ * at: { x: number; y: number };
111
+ * }
112
+ *
113
+ * const createDots = () =>
114
+ * createBatchedMark(circle, {
115
+ * channels: { center: (item: Dot) => item.at },
116
+ * enter: { radius: 0 },
117
+ * exit: { radius: 0 },
118
+ * });
119
+ * const marks = new WeakMap<object, ReturnType<typeof createDots>>();
120
+ *
121
+ * function draw(ctx: CompositeContext<DotsProps>) {
122
+ * const dots = marks.get(ctx.node)!;
123
+ * const items = ctx.props.points.map((at, key) => ({ key, at }));
124
+ * dots.update(items, { radius: 0.1, strokeWidth: 0 }, { transition: { duration: 0.4 }, animate: true });
125
+ * return [dots.node];
126
+ * }
127
+ *
128
+ * export const dots = defineComposite<DotsProps>({
129
+ * name: "Dots",
130
+ * props: { points: { default: [], invalidates: Invalidate.UPDATE } },
131
+ * setup: (ctx) => {
132
+ * marks.set(ctx.node, createDots());
133
+ * return draw(ctx);
134
+ * },
135
+ * update: (_changed, ctx) => draw(ctx),
136
+ * });
137
+ * ```
138
+ *
139
+ * @param definition - The shape every item is (`circle`, `rect`, `line`, ...).
140
+ * @category Extending
141
+ */
142
+ export declare function createBatchedMark<D extends BatchItem, P extends object, N extends SceneNode<P>, I extends keyof P>(definition: Definition<P, N, I>, options: BatchedMarkOptions<D, P, I>): BatchedMark<D, P, N, I>;
@@ -0,0 +1,56 @@
1
+ import { createContextKey as e } from "@sophistry/core";
2
+ import { cssColor as t, temporalEpochMs as n } from "@sophistry/core/internal";
3
+ //#region src/data/channels.ts
4
+ var r = (e) => e, i = (e, t) => t;
5
+ function a(e, t, r = "channel", i) {
6
+ let a;
7
+ if (e === void 0) a = t;
8
+ else if (typeof e == "function") a = e;
9
+ else {
10
+ let t = typeof e;
11
+ if (t !== "string" && t !== "symbol") throw TypeError(`\`${r}\` must be a key of the datum or a function (d, i) => value, got ${e === null ? "null" : t}.`);
12
+ let n = e;
13
+ a = (e) => e[n];
14
+ }
15
+ if (!a) return;
16
+ let s = a, c = o.get(r), l = c ? i ?? void 0 : void 0;
17
+ return (e, t) => {
18
+ let r = s(e, t);
19
+ if (typeof r != "object" || !r) return r;
20
+ let i = r instanceof Date ? r.getTime() : n(r, c && l ? l.timeZone(c) : "UTC");
21
+ return i === void 0 ? r : (c && l?.note(c), i);
22
+ };
23
+ }
24
+ var o = /* @__PURE__ */ new Map([
25
+ ["x", "x"],
26
+ ["x1", "x"],
27
+ ["x2", "x"],
28
+ ["y", "y"],
29
+ ["y1", "y"],
30
+ ["y2", "y"]
31
+ ]), s = e("chartDates", null);
32
+ function c(e, t) {
33
+ return typeof e == "number" ? () => e : a(e, t);
34
+ }
35
+ function l(e, t, n, r, i) {
36
+ let o = a(t, n, r, i);
37
+ return e.map((e, t) => o ? o(e, t) : void 0);
38
+ }
39
+ function u(e, t, n, r, i) {
40
+ return l(e, t, n, r, i).map((e) => typeof e == "number" ? e : NaN);
41
+ }
42
+ function d(e) {
43
+ if (typeof e == "function") return (n, r) => {
44
+ let i = e(n, r);
45
+ return i == null ? i : t(i);
46
+ };
47
+ if (!e) return;
48
+ let n = t(e);
49
+ return () => n;
50
+ }
51
+ function f(e, n, r) {
52
+ let i = d(e);
53
+ return (e, a) => i?.(e, a) ?? t(n.length === 0 ? r : n[a % n.length]);
54
+ }
55
+ //#endregion
56
+ export { i as a, d as c, r as i, c as l, f as n, u as o, s as r, a as s, l as t };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The chart frame: an `axes` that fits itself to the data drawn inside it.
3
+ *
4
+ * Layers (`bars`, `scatter`, ...) report their data extent through
5
+ * {@link chartLayer}; the frame fits every axis to the union, lays categories
6
+ * out on band axes, and shares one colour scale and legend across all
7
+ * layers. `progress` draws the frame first, then the data, then the legend.
8
+ *
9
+ * How it runs (one commit, no microtask): `setup` provides the stable
10
+ * contexts (where reports go, the tooltip, the date sink, the secondary
11
+ * axes' lift) and places the layers. Each layer's first update reports its
12
+ * extent, which asks the chart to update again (`ctx.invalidate`) in the
13
+ * same commit; the chart fits its axes, publishes a new {@link ChartFrame}
14
+ * and coordinate system, and the layers that read them update once more. A
15
+ * report equal by value to the last one changes nothing, so the loop
16
+ * settles. Every step of the fit (`frame/*`) keeps its last result while
17
+ * its inputs are unchanged, so a frame of a keyed transition redoes only
18
+ * what the blend moves, and a `ChartFrame` keeps its identity while nothing
19
+ * in it changed.
20
+ */
21
+ import type { ContextKey, SceneNode } from "@sophistry/core";
22
+ import type { SecondaryFlags } from "./frame/secondary.js";
23
+ import type { ChartFrame, ChartHandle, ChartLayerExtent, ChartProps } from "./frame/types.js";
24
+ export type * from "./frame/types.js";
25
+ /**
26
+ * How `secondaryX` and `secondaryY` find their chart's secondary contexts.
27
+ *
28
+ * @internal
29
+ */
30
+ export interface SecondaryLift {
31
+ /** The frame (and its coordinates) of `parent` with `axis` mapped through its secondary scale. */
32
+ lift(parent: ChartFrame, axis: "x" | "y"): ChartFrame;
33
+ /** Which secondary axes a frame of this chart maps through. */
34
+ flagsOf(frame: ChartFrame): SecondaryFlags;
35
+ }
36
+ /**
37
+ * The enclosing chart's secondary lift, or null outside a chart.
38
+ *
39
+ * @internal
40
+ */
41
+ export declare const secondaryLiftContext: ContextKey<SecondaryLift | null>;
42
+ /**
43
+ * A plotting frame that fits its axes to the layers inside it: an `axes`
44
+ * with ranges worked out for you, categorical axes, grid, title, legend and
45
+ * colour bar. Anything given explicitly (`xRange`, `yRange`,
46
+ * `xAxis.categories`) wins over fitting. Children see the coordinate system
47
+ * as in `axes`, so core's graphs plot in data space inside it.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * import { createScene } from "@sophistry/core";
52
+ * import { chart, okabeIto, scatter } from "@sophistry/charts";
53
+ *
54
+ * const scene = createScene({ host: document.querySelector("#figure")!, units: 10 });
55
+ * const temps = [
56
+ * { month: 1, city: "Oslo", c: -4 },
57
+ * { month: 7, city: "Oslo", c: 17 },
58
+ * { month: 1, city: "Rome", c: 8 },
59
+ * { month: 7, city: "Rome", c: 25 },
60
+ * ];
61
+ * scene.add(
62
+ * chart.create({
63
+ * width: 8,
64
+ * height: 4,
65
+ * color: { range: okabeIto },
66
+ * legendTitle: "City",
67
+ * children: [scatter.create({ data: temps, x: "month", y: "c", series: "city" })],
68
+ * }),
69
+ * );
70
+ * ```
71
+ *
72
+ * @see https://sophistry.dev/guides/charts/#the-chart-frame
73
+ * @category Charts
74
+ */
75
+ export declare const chart: import("@sophistry/core").Definition<ChartProps, import("@sophistry/core/internal").CompositeNode<ChartProps>, keyof ChartProps>;
76
+ /**
77
+ * A chart node's handle: its coordinate system,
78
+ * band scales and colours, as of its last update. Brings the node up to date
79
+ * first, so it works right after `create`.
80
+ *
81
+ * @param node - A node made by {@link chart}.
82
+ * @returns The handle, or null for a node that is not a chart.
83
+ * @category Charts
84
+ */
85
+ export declare function chartHandle(node: SceneNode): ChartHandle | null;
86
+ /** For tests: the chart reports in `node`'s registry. @internal */
87
+ export declare function chartReports(node: SceneNode): readonly ChartLayerExtent[];