@pibbl/core 0.0.2 → 0.0.3-alpha.85.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 (233) hide show
  1. package/THIRD_PARTY_NOTICES.txt +81 -0
  2. package/dist/features/textures/index.d.ts +12 -2
  3. package/dist/features/textures/index.js +33 -1
  4. package/dist/features/textures/index.js.map +2 -2
  5. package/dist/features/textures/lib/chemical-field.d.ts +56 -0
  6. package/dist/features/textures/lib/chemical-field.js +154 -0
  7. package/dist/features/textures/lib/chemical-field.js.map +7 -0
  8. package/dist/features/textures/lib/chemical-recipes.d.ts +119 -0
  9. package/dist/features/textures/lib/chemical-recipes.js +275 -0
  10. package/dist/features/textures/lib/chemical-recipes.js.map +7 -0
  11. package/dist/features/textures/lib/definitions.d.ts +3 -18
  12. package/dist/features/textures/lib/definitions.js +15 -20
  13. package/dist/features/textures/lib/definitions.js.map +2 -2
  14. package/dist/features/textures/lib/geometric-patterns.d.ts +149 -0
  15. package/dist/features/textures/lib/geometric-patterns.js +305 -0
  16. package/dist/features/textures/lib/geometric-patterns.js.map +7 -0
  17. package/dist/features/textures/lib/gray-scott.d.ts +55 -0
  18. package/dist/features/textures/lib/gray-scott.js +39 -0
  19. package/dist/features/textures/lib/gray-scott.js.map +7 -0
  20. package/dist/features/textures/lib/patterns.d.ts +123 -0
  21. package/dist/features/textures/lib/patterns.js +344 -0
  22. package/dist/features/textures/lib/patterns.js.map +7 -0
  23. package/dist/features/textures/lib/reaction-diffusion.d.ts +3 -2
  24. package/dist/features/textures/lib/reaction-diffusion.js +9 -20
  25. package/dist/features/textures/lib/reaction-diffusion.js.map +2 -2
  26. package/dist/features/textures/lib/simulation.d.ts +10 -4
  27. package/dist/features/textures/lib/simulation.js +23 -13
  28. package/dist/features/textures/lib/simulation.js.map +2 -2
  29. package/dist/features/viz/index.d.ts +55 -6
  30. package/dist/features/viz/index.js +107 -2
  31. package/dist/features/viz/index.js.map +2 -2
  32. package/dist/features/viz/inspection/bar.d.ts +79 -0
  33. package/dist/features/viz/inspection/bar.js +49 -0
  34. package/dist/features/viz/inspection/bar.js.map +7 -0
  35. package/dist/features/viz/inspection/candle.d.ts +156 -0
  36. package/dist/features/viz/inspection/candle.js +120 -0
  37. package/dist/features/viz/inspection/candle.js.map +7 -0
  38. package/dist/features/viz/inspection/capture-types.d.ts +65 -0
  39. package/dist/features/viz/inspection/capture.d.ts +16 -0
  40. package/dist/features/viz/inspection/capture.js +49 -0
  41. package/dist/features/viz/inspection/capture.js.map +7 -0
  42. package/dist/features/viz/inspection/handler.d.ts +36 -0
  43. package/dist/features/viz/inspection/handler.js +91 -0
  44. package/dist/features/viz/inspection/handler.js.map +7 -0
  45. package/dist/features/viz/inspection/ohlc-bar.d.ts +132 -0
  46. package/dist/features/viz/inspection/ohlc-bar.js +118 -0
  47. package/dist/features/viz/inspection/ohlc-bar.js.map +7 -0
  48. package/dist/features/viz/inspection/owned-ref.d.ts +16 -0
  49. package/dist/features/viz/inspection/owned-ref.js +99 -0
  50. package/dist/features/viz/inspection/owned-ref.js.map +7 -0
  51. package/dist/features/viz/inspection/painted-point.d.ts +22 -0
  52. package/dist/features/viz/inspection/painted-point.js +29 -0
  53. package/dist/features/viz/inspection/painted-point.js.map +7 -0
  54. package/dist/features/viz/inspection/queries.d.ts +100 -0
  55. package/dist/features/viz/inspection/queries.js +192 -0
  56. package/dist/features/viz/inspection/queries.js.map +7 -0
  57. package/dist/features/viz/inspection/query-types.d.ts +177 -0
  58. package/dist/features/viz/inspection/volume.d.ts +104 -0
  59. package/dist/features/viz/inspection/volume.js +95 -0
  60. package/dist/features/viz/inspection/volume.js.map +7 -0
  61. package/dist/features/viz/inspection.d.ts +19 -0
  62. package/dist/features/viz/inspection.js +54 -0
  63. package/dist/features/viz/inspection.js.map +7 -0
  64. package/dist/features/viz/inspection.mjs +1 -0
  65. package/dist/features/viz/lib/area-series.d.ts +62 -0
  66. package/dist/features/viz/lib/area-series.js +120 -0
  67. package/dist/features/viz/lib/area-series.js.map +7 -0
  68. package/dist/features/viz/lib/axis.js +1 -1
  69. package/dist/features/viz/lib/axis.js.map +2 -2
  70. package/dist/features/viz/lib/bar-series.d.ts +3 -1
  71. package/dist/features/viz/lib/bar-series.js +16 -1
  72. package/dist/features/viz/lib/bar-series.js.map +2 -2
  73. package/dist/features/viz/lib/baseline-series.d.ts +55 -0
  74. package/dist/features/viz/lib/baseline-series.js +136 -0
  75. package/dist/features/viz/lib/baseline-series.js.map +7 -0
  76. package/dist/features/viz/lib/candlestick-series.d.ts +62 -0
  77. package/dist/features/viz/lib/candlestick-series.js +150 -0
  78. package/dist/features/viz/lib/candlestick-series.js.map +7 -0
  79. package/dist/features/viz/lib/censored-point-series.d.ts +71 -0
  80. package/dist/features/viz/lib/censored-point-series.js +129 -0
  81. package/dist/features/viz/lib/censored-point-series.js.map +7 -0
  82. package/dist/features/viz/lib/color-context.d.ts +4 -0
  83. package/dist/features/viz/lib/color-context.js +41 -0
  84. package/dist/features/viz/lib/color-context.js.map +7 -0
  85. package/dist/features/viz/lib/color-math.d.ts +4 -0
  86. package/dist/features/viz/lib/color-math.js +31 -0
  87. package/dist/features/viz/lib/color-math.js.map +7 -0
  88. package/dist/features/viz/lib/color-types.d.ts +53 -0
  89. package/dist/features/viz/lib/curve-definition.d.ts +49 -0
  90. package/dist/features/viz/lib/curve-definition.js +148 -0
  91. package/dist/features/viz/lib/curve-definition.js.map +7 -0
  92. package/dist/features/viz/lib/diverging-color-scale.d.ts +11 -0
  93. package/dist/features/viz/lib/diverging-color-scale.js +51 -0
  94. package/dist/features/viz/lib/diverging-color-scale.js.map +7 -0
  95. package/dist/features/viz/lib/domain-navigation.d.ts +40 -0
  96. package/dist/features/viz/lib/domain-navigation.js +77 -0
  97. package/dist/features/viz/lib/domain-navigation.js.map +7 -0
  98. package/dist/features/viz/lib/editable-chart-elements.d.ts +178 -0
  99. package/dist/features/viz/lib/editable-chart-elements.js +733 -0
  100. package/dist/features/viz/lib/editable-chart-elements.js.map +7 -0
  101. package/dist/features/viz/lib/financial-aggregation.d.ts +127 -0
  102. package/dist/features/viz/lib/financial-aggregation.js +116 -0
  103. package/dist/features/viz/lib/financial-aggregation.js.map +7 -0
  104. package/dist/features/viz/lib/financial-autoscale.d.ts +64 -0
  105. package/dist/features/viz/lib/financial-autoscale.js +61 -0
  106. package/dist/features/viz/lib/financial-autoscale.js.map +7 -0
  107. package/dist/features/viz/lib/financial-comparison.d.ts +62 -0
  108. package/dist/features/viz/lib/financial-comparison.js +98 -0
  109. package/dist/features/viz/lib/financial-comparison.js.map +7 -0
  110. package/dist/features/viz/lib/financial-geometry.d.ts +77 -0
  111. package/dist/features/viz/lib/financial-geometry.js +67 -0
  112. package/dist/features/viz/lib/financial-geometry.js.map +7 -0
  113. package/dist/features/viz/lib/financial-indicators.d.ts +114 -0
  114. package/dist/features/viz/lib/financial-indicators.js +135 -0
  115. package/dist/features/viz/lib/financial-indicators.js.map +7 -0
  116. package/dist/features/viz/lib/financial-oscillators.d.ts +171 -0
  117. package/dist/features/viz/lib/financial-oscillators.js +265 -0
  118. package/dist/features/viz/lib/financial-oscillators.js.map +7 -0
  119. package/dist/features/viz/lib/hover-data.d.ts +1 -1
  120. package/dist/features/viz/lib/hover-data.js +5 -2
  121. package/dist/features/viz/lib/hover-data.js.map +2 -2
  122. package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
  123. package/dist/features/viz/lib/interval-band-series.js +136 -0
  124. package/dist/features/viz/lib/interval-band-series.js.map +7 -0
  125. package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
  126. package/dist/features/viz/lib/interval-diamond-series.js +124 -0
  127. package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
  128. package/dist/features/viz/lib/interval-series.d.ts +79 -0
  129. package/dist/features/viz/lib/interval-series.js +158 -0
  130. package/dist/features/viz/lib/interval-series.js.map +7 -0
  131. package/dist/features/viz/lib/line-series.d.ts +1 -1
  132. package/dist/features/viz/lib/line-series.js +47 -28
  133. package/dist/features/viz/lib/line-series.js.map +2 -2
  134. package/dist/features/viz/lib/linear-scale.js +1 -1
  135. package/dist/features/viz/lib/linear-scale.js.map +2 -2
  136. package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
  137. package/dist/features/viz/lib/monotone-curve.js +63 -0
  138. package/dist/features/viz/lib/monotone-curve.js.map +7 -0
  139. package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
  140. package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
  141. package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
  142. package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
  143. package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
  144. package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
  145. package/dist/features/viz/lib/paired-series.d.ts +44 -0
  146. package/dist/features/viz/lib/paired-series.js +93 -0
  147. package/dist/features/viz/lib/paired-series.js.map +7 -0
  148. package/dist/features/viz/lib/plot-series.js +11 -6
  149. package/dist/features/viz/lib/plot-series.js.map +2 -2
  150. package/dist/features/viz/lib/plot-types.d.ts +4 -3
  151. package/dist/features/viz/lib/point-series.d.ts +1 -1
  152. package/dist/features/viz/lib/point-series.js +36 -9
  153. package/dist/features/viz/lib/point-series.js.map +2 -2
  154. package/dist/features/viz/lib/point-types.d.ts +5 -2
  155. package/dist/features/viz/lib/scale-context.d.ts +1 -1
  156. package/dist/features/viz/lib/scale-ticks.js +21 -6
  157. package/dist/features/viz/lib/scale-ticks.js.map +2 -2
  158. package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
  159. package/dist/features/viz/lib/sequential-color-scale.js +49 -0
  160. package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
  161. package/dist/features/viz/lib/series-position.d.ts +12 -0
  162. package/dist/features/viz/lib/series-position.js +44 -0
  163. package/dist/features/viz/lib/series-position.js.map +7 -0
  164. package/dist/features/viz/lib/step-curves.d.ts +19 -0
  165. package/dist/features/viz/lib/step-curves.js +53 -0
  166. package/dist/features/viz/lib/step-curves.js.map +7 -0
  167. package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
  168. package/dist/features/viz/lib/threshold-color-scale.js +59 -0
  169. package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
  170. package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
  171. package/dist/features/viz/lib/trading-time-mapping.js +89 -0
  172. package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
  173. package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
  174. package/dist/features/viz/lib/trading-time-scale.js +96 -0
  175. package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
  176. package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
  177. package/dist/features/viz/lib/trajectory-series.js +111 -0
  178. package/dist/features/viz/lib/trajectory-series.js.map +7 -0
  179. package/dist/features/viz/lib/types.d.ts +20 -4
  180. package/dist/features/viz/lib/use-continuous-scale.js +6 -1
  181. package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
  182. package/dist/features/viz/lib/volume-series.d.ts +59 -0
  183. package/dist/features/viz/lib/volume-series.js +117 -0
  184. package/dist/features/viz/lib/volume-series.js.map +7 -0
  185. package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
  186. package/dist/features/viz/lib/weighted-point-series.js +169 -0
  187. package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
  188. package/dist/filters/emboss-gpu.d.ts +4 -0
  189. package/dist/filters/emboss-gpu.js +39 -0
  190. package/dist/filters/emboss-gpu.js.map +7 -0
  191. package/dist/filters/emboss.d.ts +32 -0
  192. package/dist/filters/emboss.js +106 -0
  193. package/dist/filters/emboss.js.map +7 -0
  194. package/dist/filters/reflection-gpu.d.ts +3 -1
  195. package/dist/filters/reflection-gpu.js +5 -2
  196. package/dist/filters/reflection-gpu.js.map +2 -2
  197. package/dist/filters/render-emboss-boundary.d.ts +13 -0
  198. package/dist/filters/render-emboss-boundary.js +131 -0
  199. package/dist/filters/render-emboss-boundary.js.map +7 -0
  200. package/dist/filters.d.ts +2 -0
  201. package/dist/filters.js +2 -0
  202. package/dist/filters.js.map +2 -2
  203. package/dist/index.d.ts +2 -0
  204. package/dist/index.js +3 -0
  205. package/dist/index.js.map +2 -2
  206. package/dist/internal.d.ts +2 -0
  207. package/dist/internal.js +4 -0
  208. package/dist/internal.js.map +2 -2
  209. package/dist/lib/events/event-facade.d.ts +13 -0
  210. package/dist/lib/events/event-facade.js +23 -0
  211. package/dist/lib/events/event-facade.js.map +2 -2
  212. package/dist/lib/events/propagation.js +19 -14
  213. package/dist/lib/events/propagation.js.map +2 -2
  214. package/dist/lib/execute-render.js +13 -0
  215. package/dist/lib/execute-render.js.map +2 -2
  216. package/dist/lib/recording/recording.d.ts +43 -0
  217. package/dist/lib/recording/recording.js +555 -0
  218. package/dist/lib/recording/recording.js.map +7 -0
  219. package/dist/lib/recording/types.d.ts +118 -0
  220. package/dist/lib/recording/wasm-bytes.d.ts +1 -0
  221. package/dist/lib/recording/wasm-bytes.js +5 -0
  222. package/dist/lib/recording/wasm-bytes.js.map +7 -0
  223. package/dist/lib/recording/worker-source.d.ts +1 -0
  224. package/dist/lib/recording/worker-source.js +5 -0
  225. package/dist/lib/recording/worker-source.js.map +7 -0
  226. package/dist/lib/render-transaction.d.ts +5 -2
  227. package/dist/lib/render-transaction.js +23 -1
  228. package/dist/lib/render-transaction.js.map +2 -2
  229. package/dist/lib/series-inspection-frame.d.ts +18 -0
  230. package/dist/lib/series-inspection-frame.js +70 -0
  231. package/dist/lib/series-inspection-frame.js.map +7 -0
  232. package/dist/lib/types.d.ts +6 -0
  233. package/package.json +10 -2
@@ -0,0 +1,71 @@
1
+ import type { PibblEventHandlers, PibblEventParticipationOptions, SignalValue, StrokeStyle } from "@pibbl/core";
2
+ import type { SignalStyle } from "@pibbl/core/internal";
3
+ import type { LineAccessor, ScaleId, SeriesAccessor } from "./types.js";
4
+ /** Shared path appearance for {@link TrajectorySeries}. */
5
+ export interface TrajectorySeriesStyle {
6
+ /** Path paint. Defaults to `#2563eb`. */
7
+ readonly stroke?: StrokeStyle;
8
+ /** Visible path width in local units. Defaults to 2. */
9
+ readonly strokeWidth?: number;
10
+ /** Pointer targeting width. Defaults to `strokeWidth`. */
11
+ readonly lineInteractionWidth?: number;
12
+ /** Path opacity in [0, 1]. Defaults to 1. */
13
+ readonly opacity?: number;
14
+ /** Cursor while the batched path owns pointer presentation. */
15
+ readonly cursor?: string;
16
+ }
17
+ /**
18
+ * A participant or specimen identity property or callback.
19
+ *
20
+ * Nullish identities deliberately omit a row. Numeric identities must be finite.
21
+ * @param datum - Source observation.
22
+ * @param index - Zero-based source index.
23
+ * @param data - Complete source data array.
24
+ * @returns A finite numeric or string identity, or a nullish omitted identity.
25
+ * @see {@link TrajectorySeriesProps}
26
+ */
27
+ export type TrajectoryGroupAccessor<D> = {
28
+ [K in keyof D]-?: D[K] extends string | number | null | undefined ? K : never;
29
+ }[keyof D] | ((datum: D, index: number, data: readonly D[]) => string | number | null | undefined);
30
+ /**
31
+ * Authoring inputs for {@link TrajectorySeries}.
32
+ *
33
+ * Rows are connected in source encounter order within each group. The component
34
+ * neither sorts time values nor invents visits, summaries, or missing values.
35
+ */
36
+ export interface TrajectorySeriesProps<D> extends PibblEventHandlers, PibblEventParticipationOptions {
37
+ /** Source observations or a signal containing them. */
38
+ readonly data: SignalValue<readonly D[]>;
39
+ /** Stable participant or specimen identity. Nullish identities omit that row. */
40
+ readonly group: TrajectoryGroupAccessor<D>;
41
+ /** Encounter-time or scheduled-visit coordinate. */
42
+ readonly x: SeriesAccessor<D>;
43
+ /** Numeric observed outcome coordinate. */
44
+ readonly y: LineAccessor<D>;
45
+ /** Scale mapping encounter-time or visit coordinates. */
46
+ readonly xScale: ScaleId;
47
+ /** Numeric scale mapping outcomes. */
48
+ readonly yScale: ScaleId;
49
+ /**
50
+ * Ends that group's current run without reading coordinate accessors.
51
+ * @param datum - Candidate source datum.
52
+ * @param index - Zero-based source index.
53
+ * @param data - Complete source data array.
54
+ * @returns Whether this datum contributes a coordinate to its group.
55
+ */
56
+ readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;
57
+ /** Shared path style, including whole-object and shallow field signals. */
58
+ readonly style?: SignalValue<SignalStyle<TrajectorySeriesStyle>>;
59
+ }
60
+ /**
61
+ * Draws one shared-style path connecting each participant or specimen trajectory.
62
+ *
63
+ * A missing, excluded, or non-finite coordinate ends only that group's current
64
+ * run. Interleaved groups retain their source encounter order; trajectories are
65
+ * never sorted by either actual or scheduled time.
66
+ *
67
+ * @param props - Observations, identities, coordinates, scales, and shared path paint.
68
+ * @returns One batched ordinary Pibbl path containing source-ordered trajectory segments.
69
+ * @see {@link TrajectorySeriesProps}
70
+ */
71
+ export declare function TrajectorySeries<D>({ data: input, group: groupInput, x: xInput, y: yInput, xScale: xId, yScale: yId, defined, style: styleInput, ...events }: TrajectorySeriesProps<D>): import("../../../jsx-runtime.js").JSX.Element;
@@ -0,0 +1,111 @@
1
+ import { jsx } from "@pibbl/core/jsx-runtime";
2
+ import { Path, resolveSignalValue } from "@pibbl/core";
3
+ import { withHooksForbidden } from "@pibbl/core/internal";
4
+ import { opacity, width } from "./paint.js";
5
+ import { pointAccessor, pointData } from "./point-data.js";
6
+ import {
7
+ mapSeriesPosition,
8
+ seriesAccessor,
9
+ useNumericPosition,
10
+ useSeriesPosition
11
+ } from "./series-position.js";
12
+ function style(input) {
13
+ if (input === null || typeof input !== "object" || Array.isArray(input))
14
+ throw new TypeError("TrajectorySeries: style must be an object.");
15
+ const value = input;
16
+ for (const field of Object.keys(value))
17
+ if (![
18
+ "stroke",
19
+ "strokeWidth",
20
+ "lineInteractionWidth",
21
+ "opacity",
22
+ "cursor"
23
+ ].includes(field))
24
+ throw new TypeError(
25
+ `TrajectorySeries: unsupported style field ${field}.`
26
+ );
27
+ const stroke = resolveSignalValue(value.stroke) ?? "#2563eb";
28
+ const strokeWidth = width(
29
+ resolveSignalValue(value.strokeWidth) ?? 2,
30
+ "TrajectorySeries strokeWidth"
31
+ );
32
+ const lineInteractionWidth = width(
33
+ resolveSignalValue(value.lineInteractionWidth) ?? strokeWidth,
34
+ "TrajectorySeries lineInteractionWidth"
35
+ );
36
+ const cursor = resolveSignalValue(value.cursor);
37
+ if (cursor !== void 0 && typeof cursor !== "string")
38
+ throw new TypeError("TrajectorySeries: cursor must be a string.");
39
+ return {
40
+ stroke,
41
+ strokeWidth,
42
+ lineInteractionWidth,
43
+ opacity: opacity(
44
+ resolveSignalValue(value.opacity) ?? 1,
45
+ "TrajectorySeries opacity"
46
+ ),
47
+ cursor
48
+ };
49
+ }
50
+ function TrajectorySeries({
51
+ data: input,
52
+ group: groupInput,
53
+ x: xInput,
54
+ y: yInput,
55
+ xScale: xId,
56
+ yScale: yId,
57
+ defined,
58
+ style: styleInput,
59
+ ...events
60
+ }) {
61
+ const xs = useSeriesPosition(xId);
62
+ const ys = useNumericPosition(yId);
63
+ const data = pointData(resolveSignalValue(input), "TrajectorySeries");
64
+ const x = seriesAccessor(xInput);
65
+ const y = pointAccessor(yInput);
66
+ const group = typeof groupInput === "function" ? groupInput : (datum) => datum[groupInput];
67
+ const resolved = style(resolveSignalValue(styleInput) ?? {});
68
+ const last = /* @__PURE__ */ new Map();
69
+ const path = new Path2D();
70
+ for (let i = 0; i < data.length; i++) {
71
+ const datum = data[i];
72
+ const row = withHooksForbidden(
73
+ "TrajectorySeries: accessors cannot call hooks.",
74
+ () => {
75
+ const identity = group(datum, i, data);
76
+ if (defined && !defined(datum, i, data)) return { group: identity };
77
+ return {
78
+ group: identity,
79
+ x: x(datum, i, data),
80
+ y: y(datum, i, data)
81
+ };
82
+ }
83
+ );
84
+ if (!row || row.group == null) continue;
85
+ if (typeof row.group !== "string" && typeof row.group !== "number" || typeof row.group === "number" && !Number.isFinite(row.group))
86
+ throw new TypeError(
87
+ "TrajectorySeries: group must be a string or number."
88
+ );
89
+ if (!("x" in row) || !("y" in row)) {
90
+ last.delete(row.group);
91
+ continue;
92
+ }
93
+ const px = mapSeriesPosition(xs, row.x);
94
+ const py = mapSeriesPosition(ys, row.y);
95
+ if (px === void 0 || py === void 0) {
96
+ last.delete(row.group);
97
+ continue;
98
+ }
99
+ const prior = last.get(row.group);
100
+ if (prior) {
101
+ path.moveTo(prior[0], prior[1]);
102
+ path.lineTo(px, py);
103
+ }
104
+ last.set(row.group, [px, py]);
105
+ }
106
+ return /* @__PURE__ */ jsx(Path, { ...events, style: { d: path, ...resolved } });
107
+ }
108
+ export {
109
+ TrajectorySeries
110
+ };
111
+ //# sourceMappingURL=trajectory-series.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/trajectory-series.tsx"],
4
+ "sourcesContent": ["import { Path, resolveSignalValue } from \"@pibbl/core\";\nimport type {\n PibblEventHandlers,\n PibblEventParticipationOptions,\n SignalValue,\n StrokeStyle,\n} from \"@pibbl/core\";\nimport { withHooksForbidden } from \"@pibbl/core/internal\";\nimport type { SignalStyle } from \"@pibbl/core/internal\";\nimport type { LineAccessor, ScaleId, SeriesAccessor } from \"./types.js\";\nimport { opacity, width } from \"./paint.js\";\nimport { pointAccessor, pointData } from \"./point-data.js\";\nimport {\n mapSeriesPosition,\n seriesAccessor,\n useNumericPosition,\n useSeriesPosition,\n} from \"./series-position.js\";\n\n/** Shared path appearance for {@link TrajectorySeries}. */\nexport interface TrajectorySeriesStyle {\n /** Path paint. Defaults to `#2563eb`. */\n readonly stroke?: StrokeStyle;\n /** Visible path width in local units. Defaults to 2. */\n readonly strokeWidth?: number;\n /** Pointer targeting width. Defaults to `strokeWidth`. */\n readonly lineInteractionWidth?: number;\n /** Path opacity in [0, 1]. Defaults to 1. */\n readonly opacity?: number;\n /** Cursor while the batched path owns pointer presentation. */\n readonly cursor?: string;\n}\n\n/**\n * A participant or specimen identity property or callback.\n *\n * Nullish identities deliberately omit a row. Numeric identities must be finite.\n * @param datum - Source observation.\n * @param index - Zero-based source index.\n * @param data - Complete source data array.\n * @returns A finite numeric or string identity, or a nullish omitted identity.\n * @see {@link TrajectorySeriesProps}\n */\nexport type TrajectoryGroupAccessor<D> =\n | {\n [K in keyof D]-?: D[K] extends string | number | null | undefined\n ? K\n : never;\n }[keyof D]\n | ((\n datum: D,\n index: number,\n data: readonly D[],\n ) => string | number | null | undefined);\n\n/**\n * Authoring inputs for {@link TrajectorySeries}.\n *\n * Rows are connected in source encounter order within each group. The component\n * neither sorts time values nor invents visits, summaries, or missing values.\n */\nexport interface TrajectorySeriesProps<D>\n extends PibblEventHandlers, PibblEventParticipationOptions {\n /** Source observations or a signal containing them. */\n readonly data: SignalValue<readonly D[]>;\n /** Stable participant or specimen identity. Nullish identities omit that row. */\n readonly group: TrajectoryGroupAccessor<D>;\n /** Encounter-time or scheduled-visit coordinate. */\n readonly x: SeriesAccessor<D>;\n /** Numeric observed outcome coordinate. */\n readonly y: LineAccessor<D>;\n /** Scale mapping encounter-time or visit coordinates. */\n readonly xScale: ScaleId;\n /** Numeric scale mapping outcomes. */\n readonly yScale: ScaleId;\n /**\n * Ends that group's current run without reading coordinate accessors.\n * @param datum - Candidate source datum.\n * @param index - Zero-based source index.\n * @param data - Complete source data array.\n * @returns Whether this datum contributes a coordinate to its group.\n */\n readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;\n /** Shared path style, including whole-object and shallow field signals. */\n readonly style?: SignalValue<SignalStyle<TrajectorySeriesStyle>>;\n}\n\ninterface ResolvedTrajectoryStyle {\n readonly stroke: StrokeStyle;\n readonly strokeWidth: number;\n readonly lineInteractionWidth: number;\n readonly opacity: number;\n readonly cursor?: string;\n}\n\nfunction style(input: unknown): ResolvedTrajectoryStyle {\n if (input === null || typeof input !== \"object\" || Array.isArray(input))\n throw new TypeError(\"TrajectorySeries: style must be an object.\");\n const value = input as Record<string, unknown>;\n for (const field of Object.keys(value))\n if (\n ![\n \"stroke\",\n \"strokeWidth\",\n \"lineInteractionWidth\",\n \"opacity\",\n \"cursor\",\n ].includes(field)\n )\n throw new TypeError(\n `TrajectorySeries: unsupported style field ${field}.`,\n );\n const stroke = resolveSignalValue(value.stroke) ?? \"#2563eb\";\n const strokeWidth = width(\n (resolveSignalValue(value.strokeWidth) ?? 2) as number,\n \"TrajectorySeries strokeWidth\",\n );\n const lineInteractionWidth = width(\n (resolveSignalValue(value.lineInteractionWidth) ?? strokeWidth) as number,\n \"TrajectorySeries lineInteractionWidth\",\n );\n const cursor = resolveSignalValue(value.cursor);\n if (cursor !== undefined && typeof cursor !== \"string\")\n throw new TypeError(\"TrajectorySeries: cursor must be a string.\");\n return {\n stroke: stroke as StrokeStyle,\n strokeWidth,\n lineInteractionWidth,\n opacity: opacity(\n (resolveSignalValue(value.opacity) ?? 1) as number,\n \"TrajectorySeries opacity\",\n ),\n cursor,\n };\n}\n\n/**\n * Draws one shared-style path connecting each participant or specimen trajectory.\n *\n * A missing, excluded, or non-finite coordinate ends only that group's current\n * run. Interleaved groups retain their source encounter order; trajectories are\n * never sorted by either actual or scheduled time.\n *\n * @param props - Observations, identities, coordinates, scales, and shared path paint.\n * @returns One batched ordinary Pibbl path containing source-ordered trajectory segments.\n * @see {@link TrajectorySeriesProps}\n */\nexport function TrajectorySeries<D>({\n data: input,\n group: groupInput,\n x: xInput,\n y: yInput,\n xScale: xId,\n yScale: yId,\n defined,\n style: styleInput,\n ...events\n}: TrajectorySeriesProps<D>) {\n const xs = useSeriesPosition(xId);\n const ys = useNumericPosition(yId);\n const data = pointData(resolveSignalValue(input), \"TrajectorySeries\");\n const x = seriesAccessor(xInput);\n const y = pointAccessor(yInput);\n const group =\n typeof groupInput === \"function\"\n ? groupInput\n : (datum: D) => datum[groupInput] as string | number | null | undefined;\n const resolved = style(resolveSignalValue(styleInput) ?? {});\n const last = new Map<string | number, readonly [number, number]>();\n const path = new Path2D();\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n const row = withHooksForbidden(\n \"TrajectorySeries: accessors cannot call hooks.\",\n () => {\n const identity = group(datum, i, data);\n if (defined && !defined(datum, i, data)) return { group: identity };\n return {\n group: identity,\n x: x(datum, i, data),\n y: y(datum, i, data),\n };\n },\n );\n if (!row || row.group == null) continue;\n if (\n (typeof row.group !== \"string\" && typeof row.group !== \"number\") ||\n (typeof row.group === \"number\" && !Number.isFinite(row.group))\n )\n throw new TypeError(\n \"TrajectorySeries: group must be a string or number.\",\n );\n if (!(\"x\" in row) || !(\"y\" in row)) {\n last.delete(row.group);\n continue;\n }\n const px = mapSeriesPosition(xs, row.x);\n const py = mapSeriesPosition(ys, row.y);\n if (px === undefined || py === undefined) {\n last.delete(row.group);\n continue;\n }\n const prior = last.get(row.group);\n if (prior) {\n path.moveTo(prior[0], prior[1]);\n path.lineTo(px, py);\n }\n last.set(row.group, [px, py]);\n }\n return <Path {...events} style={{ d: path, ...resolved }} />;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -7,6 +7,7 @@ import type { PointAccessor } from "./point-types.js";
7
7
  import type { ScaleAdjust } from "./scale-adjust.js";
8
8
  import type { BoxStyle, PibblNode, LayoutItemStyle, LayoutBox, SignalValue } from "@pibbl/core";
9
9
  import type { SignalStyle } from "@pibbl/core/internal";
10
+ import type { SeriesCurve } from "./curve-definition.js";
10
11
  /**
11
12
  * A string or symbol identifying a scale within visualization context.
12
13
  *
@@ -236,7 +237,7 @@ export interface ResolvedLogScale extends Omit<ResolvedLinearScale, "type"> {
236
237
  readonly base: number;
237
238
  }
238
239
  /** A numeric or categorical mapping snapshot. See {@link ResolvedContinuousScale}. */
239
- export type ResolvedScale = ResolvedContinuousScale | ResolvedBandScale | ResolvedPointScale;
240
+ export type ResolvedScale = ResolvedContinuousScale | ResolvedBandScale | ResolvedPointScale | import("./trading-time-scale.js").ResolvedTradingTimeScale;
240
241
  /** Signed logarithmic scale inputs. See {@link LinearScaleProps}. */
241
242
  export interface SymlogScaleProps extends LinearScaleProps {
242
243
  /** Positive linear-to-log transition constant in domain units, default 1. */
@@ -369,12 +370,25 @@ export type LineCoordinate = number | null | undefined;
369
370
  export type LineAccessor<D> = {
370
371
  [K in keyof D]-?: D[K] extends LineCoordinate ? K : never;
371
372
  }[keyof D] | ((datum: D, index: number, data: readonly D[]) => LineCoordinate);
373
+ /** A numeric or categorical position, or a missing value. @see {@link SeriesAccessor} */
374
+ export type SeriesCoordinate = number | string | null | undefined;
375
+ /**
376
+ * Extracts one position for a line, point, or custom mark.
377
+ * @param datum - Original record.
378
+ * @param index - Original record index.
379
+ * @param data - Complete source records.
380
+ * @returns A numeric or categorical position. See {@link SeriesCoordinate}.
381
+ * @see {@link LineSeriesProps}
382
+ */
383
+ export type SeriesAccessor<D> = {
384
+ [K in keyof D]-?: D[K] extends SeriesCoordinate ? K : never;
385
+ }[keyof D] | ((datum: D, index: number, data: readonly D[]) => SeriesCoordinate);
372
386
  /**
373
387
  * The supported interpolation mode for a line series.
374
388
  *
375
389
  * @see {@link LineSeriesProps}
376
390
  */
377
- export type LineCurve = "linear";
391
+ export type LineCurve = "linear" | SeriesCurve;
378
392
  /**
379
393
  * Supported geometry and presentation properties for LineSeries.
380
394
  *
@@ -413,10 +427,12 @@ export interface LineSeriesProps<D> extends PibblEventHandlers, PibblEventPartic
413
427
  * Application data supplied to the component or reported by the event. See {@link SignalValue}.
414
428
  */
415
429
  readonly data: SignalValue<readonly D[]>;
430
+ /** Optional committed numeric observation capture; no query execution during paint. */
431
+ readonly inspection?: import("../inspection/capture-types.js").NumericInspectionRef<D>;
416
432
  /** Property key or callback extracting the horizontal domain coordinate. See {@link LineAccessor}. */
417
- readonly x: LineAccessor<D>;
433
+ readonly x: SeriesAccessor<D>;
418
434
  /** Property key or callback extracting the vertical domain coordinate. See {@link LineAccessor}. */
419
- readonly y: LineAccessor<D>;
435
+ readonly y: SeriesAccessor<D>;
420
436
  /** The scale used to map horizontal data coordinates. See {@link ScaleId}. */
421
437
  readonly xScale: ScaleId;
422
438
  /** The scale used to map vertical data coordinates. See {@link ScaleId}. */
@@ -1,7 +1,12 @@
1
1
  import { scaleView } from "./scale-view.js";
2
2
  const views = /* @__PURE__ */ new WeakMap();
3
3
  function useContinuousScale(id) {
4
- return scaleView(views, id, "useContinuousScale", (kind) => kind !== "band" && kind !== "point");
4
+ return scaleView(
5
+ views,
6
+ id,
7
+ "useContinuousScale",
8
+ (kind) => kind !== "band" && kind !== "point" && kind !== "trading-time"
9
+ );
5
10
  }
6
11
  export {
7
12
  useContinuousScale
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/features/viz/lib/use-continuous-scale.ts"],
4
- "sourcesContent": ["import type { Signal } from \"@pibbl/core\";\nimport type { ResolvedContinuousScale, ResolvedScale, ScaleId } from \"./types.js\";\nimport { scaleView } from \"./scale-view.js\";\nconst views = new WeakMap<Signal<ResolvedScale>, Signal<ResolvedContinuousScale>>();\n/**\n * Reads an ancestor continuous scale as a stable, shared readonly signal.\n * @param id - Ancestor scale identity. See {@link ScaleId}.\n * @returns The reactive mapping. See {@link ResolvedContinuousScale} and {@link Signal}.\n */\nexport function useContinuousScale(id: ScaleId): Signal<ResolvedContinuousScale> {\n return scaleView(views, id, \"useContinuousScale\", (kind) => kind !== \"band\" && kind !== \"point\");\n}\n"],
5
- "mappings": "AAEA,SAAS,iBAAiB;AAC1B,MAAM,QAAQ,oBAAI,QAAgE;AAM3E,SAAS,mBAAmB,IAA8C;AAC/E,SAAO,UAAU,OAAO,IAAI,sBAAsB,CAAC,SAAS,SAAS,UAAU,SAAS,OAAO;AACjG;",
4
+ "sourcesContent": ["import type { Signal } from \"@pibbl/core\";\nimport type {\n ResolvedContinuousScale,\n ResolvedScale,\n ScaleId,\n} from \"./types.js\";\nimport { scaleView } from \"./scale-view.js\";\nconst views = new WeakMap<\n Signal<ResolvedScale>,\n Signal<ResolvedContinuousScale>\n>();\n/**\n * Reads an ancestor continuous scale as a stable, shared readonly signal.\n * @param id - Ancestor scale identity. See {@link ScaleId}.\n * @returns The reactive mapping. See {@link ResolvedContinuousScale} and {@link Signal}.\n */\nexport function useContinuousScale(\n id: ScaleId,\n): Signal<ResolvedContinuousScale> {\n return scaleView(\n views,\n id,\n \"useContinuousScale\",\n (kind) => kind !== \"band\" && kind !== \"point\" && kind !== \"trading-time\",\n );\n}\n"],
5
+ "mappings": "AAMA,SAAS,iBAAiB;AAC1B,MAAM,QAAQ,oBAAI,QAGhB;AAMK,SAAS,mBACd,IACiC;AACjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC,SAAS,SAAS,UAAU,SAAS,WAAW,SAAS;AAAA,EAC5D;AACF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,59 @@
1
+ import { type FillStyle, type StrokeStyle, type SignalValue, type PibblEventHandlers, type PibblEventParticipationOptions, type PibblNode } from "@pibbl/core";
2
+ import type { LineAccessor, ScaleId } from "./types.js";
3
+ import type { VolumeInspectionRef } from "../inspection/volume.js";
4
+ /** Local column presentation; color meaning is supplied by the application.
5
+ * @see {@link VolumeSeries}
6
+ */
7
+ export interface VolumeSeriesStyle {
8
+ /** Positive column width in local logical units; default 70% spacing capped at 12. */
9
+ readonly width?: number;
10
+ /** Interior paint; defaults to teal. */
11
+ readonly fill?: FillStyle;
12
+ /** Optional column outline paint. */
13
+ readonly stroke?: StrokeStyle;
14
+ /** Nonnegative outline width in local units; default 1. */
15
+ readonly strokeWidth?: number;
16
+ /** Paint opacity from zero through one; default 1. */
17
+ readonly opacity?: number;
18
+ /** Cursor when the series owns coordinate targeting. */
19
+ readonly cursor?: string;
20
+ }
21
+ /** Time-aligned volume columns with an independent numeric y-scale.
22
+ * @see {@link VolumeSeries}
23
+ */
24
+ export interface VolumeSeriesProps<D> extends PibblEventHandlers, PibblEventParticipationOptions {
25
+ /** Original records or a signal of records; never sorted or mutated. */
26
+ readonly data: SignalValue<readonly D[]>;
27
+ /** UTC-millisecond property or callback; missing/nonfinite values skip the row. */
28
+ readonly time: LineAccessor<D>;
29
+ /** Nonnegative volume property or callback; missing/nonfinite values skip the row. */
30
+ readonly volume: LineAccessor<D>;
31
+ /** Selects source records before evaluating accessors.
32
+ * @param datum - Original record.
33
+ * @param index - Original source index.
34
+ * @param data - Complete source array.
35
+ * @returns Whether the row participates.
36
+ */
37
+ readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;
38
+ /** Numeric time scale identity. */
39
+ readonly xScale: ScaleId;
40
+ /** Independent numeric volume scale identity; the baseline is zero. */
41
+ readonly yScale: ScaleId;
42
+ /** Constant presentation or a hook-free per-record resolver.
43
+ * @param datum - Original record.
44
+ * @param index - Original source index.
45
+ * @param data - Complete source array.
46
+ * @returns Column presentation.
47
+ */
48
+ readonly style?: SignalValue<VolumeSeriesStyle> | ((datum: D, index: number, data: readonly D[]) => VolumeSeriesStyle);
49
+ /** Optional committed capture; importing the renderer does not import inspection queries. */
50
+ readonly inspection?: VolumeInspectionRef<D>;
51
+ }
52
+ /**
53
+ * Paints source-ordered time-aligned volume columns, batching adjacent equal styles.
54
+ * Zero volume is recorded but has no painted coverage. Finite negative volume rejects.
55
+ * @param props - Original records, numeric scales, accessors and optional capture.
56
+ * @returns Ordinary Pibbl paint/event composition.
57
+ * @see {@link VolumeSeriesProps}
58
+ */
59
+ export declare function VolumeSeries<D>({ data: input, time: timeInput, volume: volumeInput, xScale, yScale, defined, style: styleInput, inspection, pointerEvents, ...events }: VolumeSeriesProps<D>): PibblNode;
@@ -0,0 +1,117 @@
1
+ import { jsx } from "@pibbl/core/jsx-runtime";
2
+ import { useNumericPosition } from "./series-position.js";
3
+ import {
4
+ Group,
5
+ Path,
6
+ resolveSignalValue
7
+ } from "@pibbl/core";
8
+ import { withHooksForbidden } from "@pibbl/core/internal";
9
+ import { useContinuousScale } from "./use-continuous-scale.js";
10
+ import { pointAccessor, pointData, finiteCoordinate } from "./point-data.js";
11
+ import { financialMarkWidth, volumeGeometry } from "./financial-geometry.js";
12
+ import { opacity, width } from "./paint.js";
13
+ function VolumeSeries({
14
+ data: input,
15
+ time: timeInput,
16
+ volume: volumeInput,
17
+ xScale,
18
+ yScale,
19
+ defined,
20
+ style: styleInput,
21
+ inspection,
22
+ pointerEvents,
23
+ ...events
24
+ }) {
25
+ const xs = useNumericPosition(xScale), ys = useContinuousScale(yScale).get();
26
+ const data = pointData(resolveSignalValue(input), "VolumeSeries");
27
+ const time = pointAccessor(timeInput), volume = pointAccessor(volumeInput);
28
+ const rows = [];
29
+ for (let i = 0; i < data.length; i++) {
30
+ const datum = data[i];
31
+ if (defined && !defined(datum, i, data)) continue;
32
+ const t = time(datum, i, data), v = volume(datum, i, data);
33
+ if (!finiteCoordinate(t) || !finiteCoordinate(v)) continue;
34
+ if (v < 0)
35
+ throw new RangeError(
36
+ `VolumeSeries: negative volume at source index ${i}.`
37
+ );
38
+ rows.push({
39
+ datum,
40
+ sourceIndex: i,
41
+ time: t,
42
+ volume: v,
43
+ x: xs.map(t),
44
+ y: ys.map(v)
45
+ });
46
+ }
47
+ const positions = rows.map((row) => row.x), baselineY = ys.map(0), defaultWidth = financialMarkWidth(positions);
48
+ const specified = typeof styleInput === "function" ? styleInput : resolveSignalValue(styleInput);
49
+ const marks = inspection ? [] : void 0;
50
+ const batches = [];
51
+ for (const row of rows) {
52
+ const style = typeof specified === "function" ? withHooksForbidden(
53
+ "VolumeSeries style callback",
54
+ () => specified(row.datum, row.sourceIndex, data)
55
+ ) : specified ?? {};
56
+ const markWidth = style.width === void 0 ? defaultWidth : financialMarkWidth([], { width: style.width });
57
+ const b = volumeGeometry({
58
+ centerX: row.x,
59
+ valueY: row.y,
60
+ baselineY,
61
+ width: markWidth
62
+ });
63
+ const fill = style.fill ?? "#087f8c", stroke = style.stroke, strokeWidth = width(style.strokeWidth ?? 1, "VolumeSeries"), alpha = opacity(style.opacity ?? 1, "VolumeSeries");
64
+ marks?.push(
65
+ Object.freeze({
66
+ datum: row.datum,
67
+ sourceIndex: row.sourceIndex,
68
+ time: row.time,
69
+ volume: row.volume,
70
+ baseline: 0,
71
+ anchorLocal: Object.freeze({ x: row.x, y: row.y }),
72
+ boundsLocal: b,
73
+ fill: !!fill && alpha > 0,
74
+ strokeWidthLocal: stroke && alpha > 0 ? strokeWidth : 0
75
+ })
76
+ );
77
+ if (b.height === 0 || alpha === 0) continue;
78
+ let batch = batches.at(-1);
79
+ const half = stroke ? strokeWidth / 2 : 0, minX = b.x - half, maxX = b.x + b.width + half;
80
+ if (!batch || minX < batch.maxX && maxX > batch.minX || batch.fill !== fill || batch.stroke !== stroke || batch.strokeWidth !== strokeWidth || batch.opacity !== alpha || batch.cursor !== style.cursor) {
81
+ batch = {
82
+ path: new Path2D(),
83
+ fill,
84
+ stroke,
85
+ strokeWidth,
86
+ opacity: alpha,
87
+ cursor: style.cursor,
88
+ minX,
89
+ maxX
90
+ };
91
+ batches.push(batch);
92
+ }
93
+ batch.minX = Math.min(batch.minX, minX);
94
+ batch.maxX = Math.max(batch.maxX, maxX);
95
+ batch.path.rect(b.x, b.y, b.width, b.height);
96
+ }
97
+ inspection?.capture({ marks, xScale: xs, yScale: ys });
98
+ return /* @__PURE__ */ jsx(Group, { ...events, children: batches.map((batch, index) => /* @__PURE__ */ jsx(
99
+ Path,
100
+ {
101
+ pointerEvents,
102
+ style: {
103
+ d: batch.path,
104
+ fill: batch.fill,
105
+ stroke: batch.stroke,
106
+ strokeWidth: batch.strokeWidth,
107
+ opacity: batch.opacity,
108
+ cursor: batch.cursor
109
+ }
110
+ },
111
+ index
112
+ )) });
113
+ }
114
+ export {
115
+ VolumeSeries
116
+ };
117
+ //# sourceMappingURL=volume-series.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/volume-series.tsx"],
4
+ "sourcesContent": ["import { useNumericPosition } from \"./series-position.js\";\nimport {\n Group,\n Path,\n resolveSignalValue,\n type FillStyle,\n type StrokeStyle,\n type SignalValue,\n type PibblEventHandlers,\n type PibblEventParticipationOptions,\n type PibblNode,\n} from \"@pibbl/core\";\nimport { withHooksForbidden } from \"@pibbl/core/internal\";\nimport type { LineAccessor, ScaleId } from \"./types.js\";\nimport type {\n VolumeInspectionRef,\n CapturedVolumeMark,\n} from \"../inspection/volume.js\";\nimport { useContinuousScale } from \"./use-continuous-scale.js\";\nimport { pointAccessor, pointData, finiteCoordinate } from \"./point-data.js\";\nimport { financialMarkWidth, volumeGeometry } from \"./financial-geometry.js\";\nimport { opacity, width } from \"./paint.js\";\n\n/** Local column presentation; color meaning is supplied by the application.\n * @see {@link VolumeSeries}\n */\nexport interface VolumeSeriesStyle {\n /** Positive column width in local logical units; default 70% spacing capped at 12. */\n readonly width?: number;\n /** Interior paint; defaults to teal. */\n readonly fill?: FillStyle;\n /** Optional column outline paint. */\n readonly stroke?: StrokeStyle;\n /** Nonnegative outline width in local units; default 1. */\n readonly strokeWidth?: number;\n /** Paint opacity from zero through one; default 1. */\n readonly opacity?: number;\n /** Cursor when the series owns coordinate targeting. */\n readonly cursor?: string;\n}\n/** Time-aligned volume columns with an independent numeric y-scale.\n * @see {@link VolumeSeries}\n */\nexport interface VolumeSeriesProps<D>\n extends PibblEventHandlers, PibblEventParticipationOptions {\n /** Original records or a signal of records; never sorted or mutated. */\n readonly data: SignalValue<readonly D[]>;\n /** UTC-millisecond property or callback; missing/nonfinite values skip the row. */\n readonly time: LineAccessor<D>;\n /** Nonnegative volume property or callback; missing/nonfinite values skip the row. */\n readonly volume: LineAccessor<D>;\n /** Selects source records before evaluating accessors.\n * @param datum - Original record.\n * @param index - Original source index.\n * @param data - Complete source array.\n * @returns Whether the row participates.\n */\n readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;\n /** Numeric time scale identity. */\n readonly xScale: ScaleId;\n /** Independent numeric volume scale identity; the baseline is zero. */\n readonly yScale: ScaleId;\n /** Constant presentation or a hook-free per-record resolver.\n * @param datum - Original record.\n * @param index - Original source index.\n * @param data - Complete source array.\n * @returns Column presentation.\n */\n readonly style?:\n | SignalValue<VolumeSeriesStyle>\n | ((datum: D, index: number, data: readonly D[]) => VolumeSeriesStyle);\n /** Optional committed capture; importing the renderer does not import inspection queries. */\n readonly inspection?: VolumeInspectionRef<D>;\n}\n/**\n * Paints source-ordered time-aligned volume columns, batching adjacent equal styles.\n * Zero volume is recorded but has no painted coverage. Finite negative volume rejects.\n * @param props - Original records, numeric scales, accessors and optional capture.\n * @returns Ordinary Pibbl paint/event composition.\n * @see {@link VolumeSeriesProps}\n */\nexport function VolumeSeries<D>({\n data: input,\n time: timeInput,\n volume: volumeInput,\n xScale,\n yScale,\n defined,\n style: styleInput,\n inspection,\n pointerEvents,\n ...events\n}: VolumeSeriesProps<D>): PibblNode {\n const xs = useNumericPosition(xScale),\n ys = useContinuousScale(yScale).get();\n const data = pointData(resolveSignalValue(input), \"VolumeSeries\");\n const time = pointAccessor(timeInput),\n volume = pointAccessor(volumeInput);\n const rows: {\n datum: D;\n sourceIndex: number;\n time: number;\n volume: number;\n x: number;\n y: number;\n }[] = [];\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n if (defined && !defined(datum, i, data)) continue;\n const t = time(datum, i, data),\n v = volume(datum, i, data);\n if (!finiteCoordinate(t) || !finiteCoordinate(v)) continue;\n if (v < 0)\n throw new RangeError(\n `VolumeSeries: negative volume at source index ${i}.`,\n );\n rows.push({\n datum,\n sourceIndex: i,\n time: t,\n volume: v,\n x: xs.map(t),\n y: ys.map(v),\n });\n }\n const positions = rows.map((row) => row.x),\n baselineY = ys.map(0),\n defaultWidth = financialMarkWidth(positions);\n const specified =\n typeof styleInput === \"function\"\n ? styleInput\n : resolveSignalValue(styleInput);\n const marks: CapturedVolumeMark<D>[] | undefined = inspection\n ? []\n : undefined;\n const batches: {\n path: Path2D;\n fill: FillStyle;\n stroke: StrokeStyle | undefined;\n strokeWidth: number;\n opacity: number;\n cursor: string | undefined;\n minX: number;\n maxX: number;\n }[] = [];\n for (const row of rows) {\n const style =\n typeof specified === \"function\"\n ? withHooksForbidden(\"VolumeSeries style callback\", () =>\n specified(row.datum, row.sourceIndex, data),\n )\n : (specified ?? {});\n const markWidth =\n style.width === undefined\n ? defaultWidth\n : financialMarkWidth([], { width: style.width });\n const b = volumeGeometry({\n centerX: row.x,\n valueY: row.y,\n baselineY,\n width: markWidth,\n });\n const fill = style.fill ?? \"#087f8c\",\n stroke = style.stroke,\n strokeWidth = width(style.strokeWidth ?? 1, \"VolumeSeries\"),\n alpha = opacity(style.opacity ?? 1, \"VolumeSeries\");\n marks?.push(\n Object.freeze({\n datum: row.datum,\n sourceIndex: row.sourceIndex,\n time: row.time,\n volume: row.volume,\n baseline: 0,\n anchorLocal: Object.freeze({ x: row.x, y: row.y }),\n boundsLocal: b,\n fill: !!fill && alpha > 0,\n strokeWidthLocal: stroke && alpha > 0 ? strokeWidth : 0,\n }),\n );\n if (b.height === 0 || alpha === 0) continue;\n let batch = batches.at(-1);\n const half = stroke ? strokeWidth / 2 : 0,\n minX = b.x - half,\n maxX = b.x + b.width + half;\n if (\n !batch ||\n (minX < batch.maxX && maxX > batch.minX) ||\n batch.fill !== fill ||\n batch.stroke !== stroke ||\n batch.strokeWidth !== strokeWidth ||\n batch.opacity !== alpha ||\n batch.cursor !== style.cursor\n ) {\n batch = {\n path: new Path2D(),\n fill,\n stroke,\n strokeWidth,\n opacity: alpha,\n cursor: style.cursor,\n minX,\n maxX,\n };\n batches.push(batch);\n }\n batch.minX = Math.min(batch.minX, minX);\n batch.maxX = Math.max(batch.maxX, maxX);\n batch.path.rect(b.x, b.y, b.width, b.height);\n }\n inspection?.capture({ marks: marks!, xScale: xs, yScale: ys });\n return (\n <Group {...events}>\n {batches.map((batch, index) => (\n <Path\n key={index}\n pointerEvents={pointerEvents}\n style={{\n d: batch.path,\n fill: batch.fill,\n stroke: batch.stroke,\n strokeWidth: batch.strokeWidth,\n opacity: batch.opacity,\n cursor: batch.cursor,\n }}\n />\n ))}\n </Group>\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ import type { FillStyle, PibblEventHandlers, PibblEventParticipationOptions, SignalValue, StrokeStyle } from "@pibbl/core";
2
+ import type { SignalStyle } from "@pibbl/core/internal";
3
+ import type { LineAccessor, ScaleId, SeriesAccessor } from "./types.js";
4
+ /**
5
+ * A data property or callback extracting a nonnegative research weight.
6
+ *
7
+ * @see {@link WeightedPointSeriesProps}
8
+ */
9
+ export type WeightAccessor<D> = LineAccessor<D>;
10
+ /** Shared presentation for {@link WeightedPointSeries}. */
11
+ export interface WeightedPointSeriesStyle {
12
+ /** Paint used for point interiors. Defaults to `#087f8c`. */
13
+ readonly fill?: FillStyle;
14
+ /** Paint used for point outlines. Defaults to no outline. */
15
+ readonly stroke?: StrokeStyle;
16
+ /** Outline width in local coordinate units. Defaults to 1. */
17
+ readonly strokeWidth?: number;
18
+ /** Opacity in the inclusive range [0, 1]. Defaults to 1. */
19
+ readonly opacity?: number;
20
+ /** Pointer cursor while the series owns a target. */
21
+ readonly cursor?: string;
22
+ }
23
+ /**
24
+ * Authored inputs for {@link WeightedPointSeries}.
25
+ *
26
+ * Weights are supplied data, not calculated precision, sample size, or evidence.
27
+ * The zero baseline and squared-radius interpolation make displayed area linear in
28
+ * the supplied weight.
29
+ */
30
+ export interface WeightedPointSeriesProps<D> extends PibblEventHandlers, PibblEventParticipationOptions {
31
+ /** Readonly data or a signal containing it. */
32
+ readonly data: SignalValue<readonly D[]>;
33
+ /** Horizontal coordinate property or synchronous accessor. */
34
+ readonly x: SeriesAccessor<D>;
35
+ /** Vertical coordinate property or synchronous accessor. */
36
+ readonly y: SeriesAccessor<D>;
37
+ /** Nonnegative supplied weight property or synchronous accessor. */
38
+ readonly weight: WeightAccessor<D>;
39
+ /** Scale used to map x coordinates. */
40
+ readonly xScale: ScaleId;
41
+ /** Scale used to map y coordinates. */
42
+ readonly yScale: ScaleId;
43
+ /** Supplied inclusive weight extent. The lower bound must be zero. */
44
+ readonly weightDomain: readonly [0, number];
45
+ /** Radius extent `[0, maximumRadius]`; defaults to `[0, 6]`. */
46
+ readonly radiusRange?: readonly [0, number];
47
+ /**
48
+ * Excludes a datum before coordinate and weight accessors run.
49
+ * @param datum - Candidate source datum.
50
+ * @param index - Zero-based source index.
51
+ * @param data - Complete source data array.
52
+ * @returns Whether this datum contributes a mark.
53
+ */
54
+ readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;
55
+ /** Shared presentation. Whole-object and shallow field signals are supported. */
56
+ readonly style?: SignalValue<SignalStyle<WeightedPointSeriesStyle>>;
57
+ }
58
+ /**
59
+ * Draws batched circles whose visible area is proportional to supplied weights.
60
+ *
61
+ * Nullish weights and zero weights omit their marks. Finite positive weights must
62
+ * fall inside `weightDomain`; the component never clamps or infers weights.
63
+ * `data` and shared style signals schedule ordinary Pibbl updates. The component
64
+ * owns no retained resources and returns one ordinary Pibbl pointer target.
65
+ *
66
+ * @param props - Supplied observations, coordinate and weight accessors, scales, and paint.
67
+ * See {@link WeightedPointSeriesProps}.
68
+ * @returns One batched Pibbl Path whose mark area is proportional to each supplied weight.
69
+ * @see {@link WeightedPointSeriesProps}
70
+ */
71
+ export declare function WeightedPointSeries<D>({ data: input, x: xInput, y: yInput, weight: weightInput, xScale: xId, yScale: yId, weightDomain, radiusRange, defined, style: styleInput, ...events }: WeightedPointSeriesProps<D>): import("../../../jsx-runtime.js").JSX.Element;