@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,156 @@
1
+ import type { LayoutBox } from "@pibbl/core";
2
+ import type { CandlestickSeriesProps } from "../lib/candlestick-series.js";
3
+ import { type NumericPositionScale } from "../lib/series-position.js";
4
+ import type { ResolvedContinuousScale } from "../lib/types.js";
5
+ import type { NumericRenderedSeries, RenderedSeriesPoint } from "./query-types.js";
6
+ /** One original candle with its evaluated OHLC values and committed local geometry.
7
+ * @see {@link CandleRenderedSeries}
8
+ */
9
+ export interface CandleObservation<D> {
10
+ /** Caller-owned original record. */
11
+ readonly datum: D;
12
+ /** Original source index, including skipped records. */
13
+ readonly sourceIndex: number;
14
+ /** Evaluated UTC-millisecond timestamp. */
15
+ readonly time: number;
16
+ /** Evaluated opening value. */
17
+ readonly open: number;
18
+ /** Evaluated high value. */
19
+ readonly high: number;
20
+ /** Evaluated low value. */
21
+ readonly low: number;
22
+ /** Evaluated closing value. */
23
+ readonly close: number;
24
+ /** Closing endpoint in series-local logical units. */
25
+ readonly anchorLocal: Readonly<RenderedSeriesPoint>;
26
+ /** Closing endpoint in root-logical units. */
27
+ readonly anchorRoot: Readonly<RenderedSeriesPoint>;
28
+ /** Body rectangle before world transforms. */
29
+ readonly bodyBoundsLocal: Readonly<LayoutBox>;
30
+ /** Wick center and endpoints before world transforms. */
31
+ readonly wickLocal: Readonly<{
32
+ /** Horizontal wick center in series-local logical units. */
33
+ x: number;
34
+ /** Mapped low endpoint in series-local logical units. */
35
+ lowY: number;
36
+ /** Mapped high endpoint in series-local logical units. */
37
+ highY: number;
38
+ }>;
39
+ }
40
+ /** A candle candidate whose closing endpoint can be tested against committed clips.
41
+ * @see {@link CandleObservation}
42
+ */
43
+ export interface CandleInspectionCandidate<D> extends CandleObservation<D> {
44
+ /**
45
+ * @returns Whether the close anchor lies inside every committed clip.
46
+ */
47
+ anchorInsideClips(): boolean;
48
+ }
49
+ /** Candle selected by nearest timestamp.
50
+ * @see {@link nearestRecordedCandleX}
51
+ */
52
+ export interface NearestCandleHit<D> extends CandleObservation<D> {
53
+ /** Absolute UTC-millisecond distance from the requested timestamp. */
54
+ readonly timeDelta: number;
55
+ }
56
+ /** Candle part whose actual painted geometry covers a root-logical query point.
57
+ * @see {@link paintedCandleAt}
58
+ */
59
+ export interface PaintedCandleHit<D> extends CandleObservation<D> {
60
+ /** Part selected in source paint order: body paints after wick. */
61
+ readonly part: "body" | "wick";
62
+ }
63
+ /** @internal Local candle geometry and paint flags committed by CandlestickSeries. */
64
+ export interface CapturedCandleMark<D> extends Omit<CandleObservation<D>, "anchorRoot"> {
65
+ /** Whether the body paints an interior. */
66
+ readonly bodyFill: boolean;
67
+ /** Local body outline width, zero when its outline is not painted. */
68
+ readonly bodyStrokeWidthLocal: number;
69
+ /** Local wick stroke width, zero when its wick is not painted. */
70
+ readonly wickStrokeWidthLocal: number;
71
+ }
72
+ /** Borrowed committed candle generation.
73
+ * @see {@link CandleInspectionRef}
74
+ */
75
+ export interface CandleRenderedSeries<D> {
76
+ /** Captured original records, values, and geometry in source order. */
77
+ readonly observations: readonly CandleObservation<D>[];
78
+ /** Throws after replacement or disposal. */
79
+ assertLive(): void;
80
+ /**
81
+ * Selects the supplied/nearest timestamp at a root-logical coordinate.
82
+ * @param pointRoot - Root-logical point to invert through the committed transform.
83
+ * @returns UTC milliseconds, or undefined for singular transforms or empty mappings.
84
+ */
85
+ timeAtRoot(pointRoot: Readonly<RenderedSeriesPoint>): number | undefined;
86
+ /**
87
+ * Tests local geometry against each committed clip.
88
+ * @param pointLocal - Series-local logical point.
89
+ * @returns Whether every committed clip contains the point.
90
+ */
91
+ anchorInsideClips(pointLocal: Readonly<RenderedSeriesPoint>): boolean;
92
+ /** @internal Captured paint flags in source paint order. */
93
+ readonly marks: readonly CapturedCandleMark<D>[];
94
+ /** @internal Numeric-query view based on close endpoints. */
95
+ readonly numeric: NumericRenderedSeries<D>;
96
+ /**
97
+ * @internal Converts root-logical points to local geometry.
98
+ * @param point - Root-logical point to convert.
99
+ * @returns Series-local point, or undefined when the transform is singular.
100
+ */
101
+ localAtRoot(point: Readonly<RenderedSeriesPoint>): Readonly<RenderedSeriesPoint> | undefined;
102
+ }
103
+ /** Mount-owned optional candle capture.
104
+ * @see {@link useCandleInspection}
105
+ */
106
+ export interface CandleInspectionRef<D> {
107
+ /**
108
+ * @returns The current borrowed generation, or undefined before paint and after disposal.
109
+ */
110
+ rendered(): CandleRenderedSeries<D> | undefined;
111
+ /**
112
+ * @internal Records a completed CandlestickSeries paint without executing queries.
113
+ * @param input - Source-ordered marks and the committed numeric mappings.
114
+ */
115
+ capture(input: {
116
+ /** Source-ordered local marks and paint flags. */
117
+ marks: readonly CapturedCandleMark<D>[];
118
+ /** Committed numeric or trading-time horizontal mapping. */
119
+ xScale: NumericPositionScale;
120
+ /** Committed continuous vertical mapping. */
121
+ yScale: ResolvedContinuousScale;
122
+ }): void;
123
+ }
124
+ /**
125
+ * Creates a stable optional candle receiver without reading data or subscribing.
126
+ *
127
+ * @param _inputs - Inputs retained only to infer the original datum type.
128
+ * @returns A ref for exactly one CandlestickSeries inspection prop.
129
+ * @see {@link CandleInspectionRef}
130
+ */
131
+ export declare function useCandleInspection<D>(_inputs: Pick<CandlestickSeriesProps<D>, "data" | "time" | "open" | "high" | "low" | "close">): CandleInspectionRef<D>;
132
+ /**
133
+ * Selects a captured candle nearest to a requested UTC timestamp.
134
+ *
135
+ * @param rendered - Borrowed committed candle generation.
136
+ * @param options - Timestamp and optional pure candidate filter.
137
+ * @returns The first source-order candle on a tie, or undefined when none qualifies.
138
+ * @see {@link NearestCandleHit}
139
+ */
140
+ export declare function nearestRecordedCandleX<D>(rendered: CandleRenderedSeries<D>, options: {
141
+ time: number;
142
+ filter?: (observation: CandleInspectionCandidate<D>) => boolean;
143
+ }): NearestCandleHit<D> | undefined;
144
+ /**
145
+ * Finds the last-painted candle body or wick covering a root-logical point.
146
+ *
147
+ * Body coverage is tested before wick coverage because a candle paints its body after its wick.
148
+ *
149
+ * @param rendered - Borrowed committed candle generation.
150
+ * @param options - Root-logical point; clips and singular transforms produce no result.
151
+ * @returns Captured candle and painted part, or undefined for gaps and unpainted geometry.
152
+ * @see {@link PaintedCandleHit}
153
+ */
154
+ export declare function paintedCandleAt<D>(rendered: CandleRenderedSeries<D>, options: {
155
+ rootPoint: Readonly<RenderedSeriesPoint>;
156
+ }): PaintedCandleHit<D> | undefined;
@@ -0,0 +1,120 @@
1
+ import {
2
+ invertNumericPosition
3
+ } from "../lib/series-position.js";
4
+ import { nearestRecordedX } from "./queries.js";
5
+ import { useRenderedRef } from "./owned-ref.js";
6
+ function useCandleInspection(_inputs) {
7
+ return useRenderedRef("candleInspection", (candidate, geometry) => {
8
+ const observations = Object.freeze(
9
+ candidate.marks.map(
10
+ (mark) => Object.freeze({
11
+ datum: mark.datum,
12
+ sourceIndex: mark.sourceIndex,
13
+ time: mark.time,
14
+ open: mark.open,
15
+ high: mark.high,
16
+ low: mark.low,
17
+ close: mark.close,
18
+ anchorLocal: mark.anchorLocal,
19
+ anchorRoot: geometry.rootAtLocal(mark.anchorLocal),
20
+ bodyBoundsLocal: mark.bodyBoundsLocal,
21
+ wickLocal: mark.wickLocal
22
+ })
23
+ )
24
+ );
25
+ const numeric = Object.freeze({
26
+ observations: Object.freeze(
27
+ observations.map(
28
+ (row) => Object.freeze({
29
+ ...row,
30
+ domainX: row.time,
31
+ domainY: row.close,
32
+ run: 0
33
+ })
34
+ )
35
+ ),
36
+ assertLive: geometry.assertLive,
37
+ domainXAtRoot(point) {
38
+ const local = geometry.localAtRoot(point);
39
+ return local ? invertNumericPosition(candidate.xScale, local.x) : void 0;
40
+ },
41
+ anchorInsideClips: geometry.anchorInsideClips,
42
+ anchorAtDomain(point) {
43
+ geometry.assertLive();
44
+ const anchorLocal = Object.freeze({
45
+ x: candidate.xScale.map(point.domainX),
46
+ y: candidate.yScale.map(point.domainY)
47
+ });
48
+ return Object.freeze({
49
+ anchorLocal,
50
+ anchorRoot: geometry.rootAtLocal(anchorLocal)
51
+ });
52
+ }
53
+ });
54
+ return Object.freeze({
55
+ observations,
56
+ marks: Object.freeze(candidate.marks.slice()),
57
+ numeric,
58
+ assertLive: geometry.assertLive,
59
+ localAtRoot: geometry.localAtRoot,
60
+ anchorInsideClips: geometry.anchorInsideClips,
61
+ timeAtRoot: numeric.domainXAtRoot
62
+ });
63
+ });
64
+ }
65
+ function nearestRecordedCandleX(rendered, options) {
66
+ const hit = nearestRecordedX(rendered.numeric, {
67
+ domainX: options.time,
68
+ filter: options.filter ? (candidate) => options.filter(
69
+ candidate
70
+ ) : void 0
71
+ });
72
+ if (!hit) return void 0;
73
+ const row = rendered.observations.find(
74
+ (observation) => observation.sourceIndex === hit.sourceIndex
75
+ );
76
+ return Object.freeze({ ...row, timeDelta: hit.domainDelta });
77
+ }
78
+ function rectangleCovers(point, bounds, fill, strokeWidth) {
79
+ const half = strokeWidth / 2;
80
+ const inside = point.x >= bounds.x && point.x <= bounds.x + bounds.width && point.y >= bounds.y && point.y <= bounds.y + bounds.height;
81
+ const outline = half > 0 && point.x >= bounds.x - half && point.x <= bounds.x + bounds.width + half && point.y >= bounds.y - half && point.y <= bounds.y + bounds.height + half && !(point.x > bounds.x + half && point.x < bounds.x + bounds.width - half && point.y > bounds.y + half && point.y < bounds.y + bounds.height - half);
82
+ return fill && inside || outline;
83
+ }
84
+ function wickCovers(point, wick, strokeWidth) {
85
+ if (strokeWidth <= 0 || wick.lowY === wick.highY) return false;
86
+ const half = strokeWidth / 2;
87
+ return point.x >= wick.x - half && point.x <= wick.x + half && point.y >= Math.min(wick.lowY, wick.highY) && point.y <= Math.max(wick.lowY, wick.highY);
88
+ }
89
+ function paintedCandleAt(rendered, options) {
90
+ rendered.assertLive();
91
+ if (!Number.isFinite(options.rootPoint.x) || !Number.isFinite(options.rootPoint.y))
92
+ throw new RangeError("paintedCandleAt rootPoint must be finite.");
93
+ const point = rendered.localAtRoot(options.rootPoint);
94
+ if (!point || !rendered.anchorInsideClips(point)) return void 0;
95
+ for (let index = rendered.marks.length - 1; index >= 0; index--) {
96
+ const mark = rendered.marks[index];
97
+ if (rectangleCovers(
98
+ point,
99
+ mark.bodyBoundsLocal,
100
+ mark.bodyFill,
101
+ mark.bodyStrokeWidthLocal
102
+ ))
103
+ return Object.freeze({
104
+ ...rendered.observations[index],
105
+ part: "body"
106
+ });
107
+ if (wickCovers(point, mark.wickLocal, mark.wickStrokeWidthLocal))
108
+ return Object.freeze({
109
+ ...rendered.observations[index],
110
+ part: "wick"
111
+ });
112
+ }
113
+ return void 0;
114
+ }
115
+ export {
116
+ nearestRecordedCandleX,
117
+ paintedCandleAt,
118
+ useCandleInspection
119
+ };
120
+ //# sourceMappingURL=candle.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/inspection/candle.ts"],
4
+ "sourcesContent": ["import type { LayoutBox } from \"@pibbl/core\";\nimport type { CandlestickSeriesProps } from \"../lib/candlestick-series.js\";\nimport {\n invertNumericPosition,\n type NumericPositionScale,\n} from \"../lib/series-position.js\";\nimport type { ResolvedContinuousScale } from \"../lib/types.js\";\nimport type {\n NumericRenderedSeries,\n RenderedSeriesPoint,\n} from \"./query-types.js\";\nimport { nearestRecordedX } from \"./queries.js\";\nimport { useRenderedRef } from \"./owned-ref.js\";\n\n/** One original candle with its evaluated OHLC values and committed local geometry.\n * @see {@link CandleRenderedSeries}\n */\nexport interface CandleObservation<D> {\n /** Caller-owned original record. */\n readonly datum: D;\n /** Original source index, including skipped records. */\n readonly sourceIndex: number;\n /** Evaluated UTC-millisecond timestamp. */\n readonly time: number;\n /** Evaluated opening value. */\n readonly open: number;\n /** Evaluated high value. */\n readonly high: number;\n /** Evaluated low value. */\n readonly low: number;\n /** Evaluated closing value. */\n readonly close: number;\n /** Closing endpoint in series-local logical units. */\n readonly anchorLocal: Readonly<RenderedSeriesPoint>;\n /** Closing endpoint in root-logical units. */\n readonly anchorRoot: Readonly<RenderedSeriesPoint>;\n /** Body rectangle before world transforms. */\n readonly bodyBoundsLocal: Readonly<LayoutBox>;\n /** Wick center and endpoints before world transforms. */\n readonly wickLocal: Readonly<{\n /** Horizontal wick center in series-local logical units. */\n x: number;\n /** Mapped low endpoint in series-local logical units. */\n lowY: number;\n /** Mapped high endpoint in series-local logical units. */\n highY: number;\n }>;\n}\n\n/** A candle candidate whose closing endpoint can be tested against committed clips.\n * @see {@link CandleObservation}\n */\nexport interface CandleInspectionCandidate<D> extends CandleObservation<D> {\n /**\n * @returns Whether the close anchor lies inside every committed clip.\n */\n anchorInsideClips(): boolean;\n}\n\n/** Candle selected by nearest timestamp.\n * @see {@link nearestRecordedCandleX}\n */\nexport interface NearestCandleHit<D> extends CandleObservation<D> {\n /** Absolute UTC-millisecond distance from the requested timestamp. */\n readonly timeDelta: number;\n}\n\n/** Candle part whose actual painted geometry covers a root-logical query point.\n * @see {@link paintedCandleAt}\n */\nexport interface PaintedCandleHit<D> extends CandleObservation<D> {\n /** Part selected in source paint order: body paints after wick. */\n readonly part: \"body\" | \"wick\";\n}\n\n/** @internal Local candle geometry and paint flags committed by CandlestickSeries. */\nexport interface CapturedCandleMark<D> extends Omit<\n CandleObservation<D>,\n \"anchorRoot\"\n> {\n /** Whether the body paints an interior. */\n readonly bodyFill: boolean;\n /** Local body outline width, zero when its outline is not painted. */\n readonly bodyStrokeWidthLocal: number;\n /** Local wick stroke width, zero when its wick is not painted. */\n readonly wickStrokeWidthLocal: number;\n}\n\n/** Borrowed committed candle generation.\n * @see {@link CandleInspectionRef}\n */\nexport interface CandleRenderedSeries<D> {\n /** Captured original records, values, and geometry in source order. */\n readonly observations: readonly CandleObservation<D>[];\n /** Throws after replacement or disposal. */\n assertLive(): void;\n /**\n * Selects the supplied/nearest timestamp at a root-logical coordinate.\n * @param pointRoot - Root-logical point to invert through the committed transform.\n * @returns UTC milliseconds, or undefined for singular transforms or empty mappings.\n */\n timeAtRoot(pointRoot: Readonly<RenderedSeriesPoint>): number | undefined;\n /**\n * Tests local geometry against each committed clip.\n * @param pointLocal - Series-local logical point.\n * @returns Whether every committed clip contains the point.\n */\n anchorInsideClips(pointLocal: Readonly<RenderedSeriesPoint>): boolean;\n /** @internal Captured paint flags in source paint order. */\n readonly marks: readonly CapturedCandleMark<D>[];\n /** @internal Numeric-query view based on close endpoints. */\n readonly numeric: NumericRenderedSeries<D>;\n /**\n * @internal Converts root-logical points to local geometry.\n * @param point - Root-logical point to convert.\n * @returns Series-local point, or undefined when the transform is singular.\n */\n localAtRoot(\n point: Readonly<RenderedSeriesPoint>,\n ): Readonly<RenderedSeriesPoint> | undefined;\n}\n\n/** Mount-owned optional candle capture.\n * @see {@link useCandleInspection}\n */\nexport interface CandleInspectionRef<D> {\n /**\n * @returns The current borrowed generation, or undefined before paint and after disposal.\n */\n rendered(): CandleRenderedSeries<D> | undefined;\n /**\n * @internal Records a completed CandlestickSeries paint without executing queries.\n * @param input - Source-ordered marks and the committed numeric mappings.\n */\n capture(input: {\n /** Source-ordered local marks and paint flags. */\n marks: readonly CapturedCandleMark<D>[];\n /** Committed numeric or trading-time horizontal mapping. */\n xScale: NumericPositionScale;\n /** Committed continuous vertical mapping. */\n yScale: ResolvedContinuousScale;\n }): void;\n}\n\n/**\n * Creates a stable optional candle receiver without reading data or subscribing.\n *\n * @param _inputs - Inputs retained only to infer the original datum type.\n * @returns A ref for exactly one CandlestickSeries inspection prop.\n * @see {@link CandleInspectionRef}\n */\nexport function useCandleInspection<D>(\n _inputs: Pick<\n CandlestickSeriesProps<D>,\n \"data\" | \"time\" | \"open\" | \"high\" | \"low\" | \"close\"\n >,\n): CandleInspectionRef<D> {\n return useRenderedRef<\n {\n marks: readonly CapturedCandleMark<D>[];\n xScale: NumericPositionScale;\n yScale: ResolvedContinuousScale;\n },\n CandleRenderedSeries<D>\n >(\"candleInspection\", (candidate, geometry) => {\n const observations = Object.freeze(\n candidate.marks.map((mark) =>\n Object.freeze({\n datum: mark.datum,\n sourceIndex: mark.sourceIndex,\n time: mark.time,\n open: mark.open,\n high: mark.high,\n low: mark.low,\n close: mark.close,\n anchorLocal: mark.anchorLocal,\n anchorRoot: geometry.rootAtLocal(mark.anchorLocal),\n bodyBoundsLocal: mark.bodyBoundsLocal,\n wickLocal: mark.wickLocal,\n }),\n ),\n );\n const numeric: NumericRenderedSeries<D> = Object.freeze({\n observations: Object.freeze(\n observations.map((row) =>\n Object.freeze({\n ...row,\n domainX: row.time,\n domainY: row.close,\n run: 0,\n }),\n ),\n ),\n assertLive: geometry.assertLive,\n domainXAtRoot(point: Readonly<RenderedSeriesPoint>) {\n const local = geometry.localAtRoot(point);\n return local\n ? invertNumericPosition(candidate.xScale, local.x)\n : undefined;\n },\n anchorInsideClips: geometry.anchorInsideClips,\n anchorAtDomain(point: Readonly<{ domainX: number; domainY: number }>) {\n geometry.assertLive();\n const anchorLocal = Object.freeze({\n x: candidate.xScale.map(point.domainX),\n y: candidate.yScale.map(point.domainY),\n });\n return Object.freeze({\n anchorLocal,\n anchorRoot: geometry.rootAtLocal(anchorLocal),\n });\n },\n });\n return Object.freeze({\n observations,\n marks: Object.freeze(candidate.marks.slice()),\n numeric,\n assertLive: geometry.assertLive,\n localAtRoot: geometry.localAtRoot,\n anchorInsideClips: geometry.anchorInsideClips,\n timeAtRoot: numeric.domainXAtRoot,\n });\n });\n}\n\n/**\n * Selects a captured candle nearest to a requested UTC timestamp.\n *\n * @param rendered - Borrowed committed candle generation.\n * @param options - Timestamp and optional pure candidate filter.\n * @returns The first source-order candle on a tie, or undefined when none qualifies.\n * @see {@link NearestCandleHit}\n */\nexport function nearestRecordedCandleX<D>(\n rendered: CandleRenderedSeries<D>,\n options: {\n time: number;\n filter?: (observation: CandleInspectionCandidate<D>) => boolean;\n },\n): NearestCandleHit<D> | undefined {\n const hit = nearestRecordedX(rendered.numeric, {\n domainX: options.time,\n filter: options.filter\n ? (candidate) =>\n options.filter!(\n candidate as typeof candidate & CandleInspectionCandidate<D>,\n )\n : undefined,\n });\n if (!hit) return undefined;\n const row = rendered.observations.find(\n (observation) => observation.sourceIndex === hit.sourceIndex,\n )!;\n return Object.freeze({ ...row, timeDelta: hit.domainDelta });\n}\n\nfunction rectangleCovers(\n point: Readonly<RenderedSeriesPoint>,\n bounds: Readonly<LayoutBox>,\n fill: boolean,\n strokeWidth: number,\n): boolean {\n const half = strokeWidth / 2;\n const inside =\n point.x >= bounds.x &&\n point.x <= bounds.x + bounds.width &&\n point.y >= bounds.y &&\n point.y <= bounds.y + bounds.height;\n const outline =\n half > 0 &&\n point.x >= bounds.x - half &&\n point.x <= bounds.x + bounds.width + half &&\n point.y >= bounds.y - half &&\n point.y <= bounds.y + bounds.height + half &&\n !(\n point.x > bounds.x + half &&\n point.x < bounds.x + bounds.width - half &&\n point.y > bounds.y + half &&\n point.y < bounds.y + bounds.height - half\n );\n return (fill && inside) || outline;\n}\n\nfunction wickCovers(\n point: Readonly<RenderedSeriesPoint>,\n wick: Readonly<{ x: number; lowY: number; highY: number }>,\n strokeWidth: number,\n): boolean {\n if (strokeWidth <= 0 || wick.lowY === wick.highY) return false;\n const half = strokeWidth / 2;\n return (\n point.x >= wick.x - half &&\n point.x <= wick.x + half &&\n point.y >= Math.min(wick.lowY, wick.highY) &&\n point.y <= Math.max(wick.lowY, wick.highY)\n );\n}\n\n/**\n * Finds the last-painted candle body or wick covering a root-logical point.\n *\n * Body coverage is tested before wick coverage because a candle paints its body after its wick.\n *\n * @param rendered - Borrowed committed candle generation.\n * @param options - Root-logical point; clips and singular transforms produce no result.\n * @returns Captured candle and painted part, or undefined for gaps and unpainted geometry.\n * @see {@link PaintedCandleHit}\n */\nexport function paintedCandleAt<D>(\n rendered: CandleRenderedSeries<D>,\n options: { rootPoint: Readonly<RenderedSeriesPoint> },\n): PaintedCandleHit<D> | undefined {\n rendered.assertLive();\n if (\n !Number.isFinite(options.rootPoint.x) ||\n !Number.isFinite(options.rootPoint.y)\n )\n throw new RangeError(\"paintedCandleAt rootPoint must be finite.\");\n const point = rendered.localAtRoot(options.rootPoint);\n if (!point || !rendered.anchorInsideClips(point)) return undefined;\n for (let index = rendered.marks.length - 1; index >= 0; index--) {\n const mark = rendered.marks[index]!;\n if (\n rectangleCovers(\n point,\n mark.bodyBoundsLocal,\n mark.bodyFill,\n mark.bodyStrokeWidthLocal,\n )\n )\n return Object.freeze({\n ...rendered.observations[index]!,\n part: \"body\" as const,\n });\n if (wickCovers(point, mark.wickLocal, mark.wickStrokeWidthLocal))\n return Object.freeze({\n ...rendered.observations[index]!,\n part: \"wick\" as const,\n });\n }\n return undefined;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,65 @@
1
+ import type { NumericRenderedSeries, RenderedSeriesPoint } from "./query-types.js";
2
+ /** Values evaluated by a numeric series, before applying its world transform. */
3
+ export interface CapturedNumericObservation<D> {
4
+ /** Original caller-owned record. */
5
+ readonly datum: D;
6
+ /** Original zero-based source position, including skipped rows. */
7
+ readonly sourceIndex: number;
8
+ /** Horizontal data-space value. */
9
+ readonly domainX: number;
10
+ /** Vertical data-space value. */
11
+ readonly domainY: number;
12
+ /** Local logical anchor before world transforms. */
13
+ readonly anchorLocal: Readonly<RenderedSeriesPoint>;
14
+ /** Contiguous valid run identity; interpolation cannot cross runs. */
15
+ readonly run: number;
16
+ /** Optional local circle radius captured for discrete point geometry. */
17
+ readonly radiusLocal?: number;
18
+ /** Whether the mark has geometric fill coverage. */
19
+ readonly fill?: boolean;
20
+ /** Local painted stroke width, zero when absent. */
21
+ readonly strokeWidthLocal?: number;
22
+ }
23
+ /** Structural capture input used by renderers; no query is executed by capture. */
24
+ export interface NumericSeriesCapture<D> {
25
+ /** Evaluated values and geometry owned by this candidate generation. */
26
+ readonly observations: readonly CapturedNumericObservation<D>[];
27
+ /** Captured numeric x mapping and inversion. */
28
+ readonly xScale: import("../lib/series-position.js").NumericPositionScale;
29
+ /** Captured numeric y mapping for explicit interpolation anchors. */
30
+ readonly yScale: import("../lib/series-position.js").NumericPositionScale;
31
+ }
32
+ /** Optional renderer sink and mount-owned access to the last successful paint.
33
+ * @see {@link NumericRenderedSeries}
34
+ */
35
+ export interface NumericInspectionRef<D> {
36
+ /** Returns borrowed rendered values.
37
+ * @returns Current committed generation, or undefined before paint/after disposal.
38
+ */
39
+ rendered(): NumericRenderedSeries<D> | undefined;
40
+ /** @internal Records a candidate; publishes only after successful root rendering.
41
+ * @param input - Values evaluated by the receiver in source order.
42
+ */
43
+ capture(input: NumericSeriesCapture<D>): void;
44
+ }
45
+ /** Rendered numeric points with committed circle/ring geometry.
46
+ * @see {@link NumericRenderedSeries}
47
+ */
48
+ export interface PointRenderedSeries<D> extends NumericRenderedSeries<D> {
49
+ /** @internal Borrowed geometry corresponding to observations in source order. */
50
+ readonly marks: readonly CapturedNumericObservation<D>[];
51
+ /** @internal Maps a root-logical point to this committed local frame.
52
+ * @param point - Root-logical Canvas coordinates.
53
+ * @returns Local coordinates, or undefined for a singular transform.
54
+ */
55
+ localAtRoot(point: Readonly<RenderedSeriesPoint>): Readonly<RenderedSeriesPoint> | undefined;
56
+ }
57
+ /** Mount-owned point capture; queries are imported independently.
58
+ * @see {@link PointRenderedSeries}
59
+ */
60
+ export interface PointInspectionRef<D> extends NumericInspectionRef<D> {
61
+ /** Returns borrowed point geometry.
62
+ * @returns Current point generation, or undefined before paint/after disposal.
63
+ */
64
+ rendered(): PointRenderedSeries<D> | undefined;
65
+ }
@@ -0,0 +1,16 @@
1
+ import type { HoverSeries } from "../lib/hover-types.js";
2
+ import type { NumericInspectionRef, PointInspectionRef } from "./capture-types.js";
3
+ /**
4
+ * Owns optional numeric capture without reading signals or executing queries.
5
+ * @param _series - Typed descriptor used for datum inference; not observed or registered.
6
+ * @returns A stable mount-owned capture ref; pass it to one numeric series' inspection prop.
7
+ * @see {@link NumericInspectionRef}
8
+ */
9
+ export declare function useNumericInspection<D>(_series: HoverSeries<D>): NumericInspectionRef<D>;
10
+ /**
11
+ * Owns optional circle/ring capture for one PointSeries; O(n) retained geometry when enabled.
12
+ * @param _series - Typed descriptor used for datum inference; not observed or registered.
13
+ * @returns A stable point inspection ref. Rendered records are borrowed until replacement/disposal.
14
+ * @see {@link PointInspectionRef}
15
+ */
16
+ export declare function usePointInspection<D>(_series: HoverSeries<D>): PointInspectionRef<D>;
@@ -0,0 +1,49 @@
1
+ import { invertNumericPosition } from "../lib/series-position.js";
2
+ import { useRenderedRef } from "./owned-ref.js";
3
+ function useCapture() {
4
+ return useRenderedRef(
5
+ "numericSeriesInspection",
6
+ (candidate, geometry) => {
7
+ const rows = candidate.observations.map(
8
+ (row) => Object.freeze({
9
+ ...row,
10
+ anchorLocal: Object.freeze({ ...row.anchorLocal }),
11
+ anchorRoot: geometry.rootAtLocal(row.anchorLocal)
12
+ })
13
+ );
14
+ return Object.freeze({
15
+ observations: Object.freeze(rows),
16
+ marks: Object.freeze(candidate.observations.slice()),
17
+ assertLive: geometry.assertLive,
18
+ localAtRoot: geometry.localAtRoot,
19
+ anchorInsideClips: geometry.anchorInsideClips,
20
+ domainXAtRoot(point) {
21
+ const local = geometry.localAtRoot(point);
22
+ return local ? invertNumericPosition(candidate.xScale, local.x) : void 0;
23
+ },
24
+ anchorAtDomain(point) {
25
+ geometry.assertLive();
26
+ const anchorLocal = Object.freeze({
27
+ x: candidate.xScale.map(point.domainX),
28
+ y: candidate.yScale.map(point.domainY)
29
+ });
30
+ return Object.freeze({
31
+ anchorLocal,
32
+ anchorRoot: geometry.rootAtLocal(anchorLocal)
33
+ });
34
+ }
35
+ });
36
+ }
37
+ );
38
+ }
39
+ function useNumericInspection(_series) {
40
+ return useCapture();
41
+ }
42
+ function usePointInspection(_series) {
43
+ return useCapture();
44
+ }
45
+ export {
46
+ useNumericInspection,
47
+ usePointInspection
48
+ };
49
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/inspection/capture.ts"],
4
+ "sourcesContent": ["import { invertNumericPosition } from \"../lib/series-position.js\";\nimport { useRenderedRef } from \"./owned-ref.js\";\nimport type { HoverSeries } from \"../lib/hover-types.js\";\nimport type {\n NumericSeriesCapture,\n NumericInspectionRef,\n PointInspectionRef,\n PointRenderedSeries,\n} from \"./capture-types.js\";\n\nfunction useCapture<D>(): PointInspectionRef<D> {\n return useRenderedRef<NumericSeriesCapture<D>, PointRenderedSeries<D>>(\n \"numericSeriesInspection\",\n (candidate, geometry) => {\n const rows = candidate.observations.map((row) =>\n Object.freeze({\n ...row,\n anchorLocal: Object.freeze({ ...row.anchorLocal }),\n anchorRoot: geometry.rootAtLocal(row.anchorLocal),\n }),\n );\n return Object.freeze({\n observations: Object.freeze(rows),\n marks: Object.freeze(candidate.observations.slice()),\n assertLive: geometry.assertLive,\n localAtRoot: geometry.localAtRoot,\n anchorInsideClips: geometry.anchorInsideClips,\n domainXAtRoot(point: Readonly<{ x: number; y: number }>) {\n const local = geometry.localAtRoot(point);\n return local\n ? invertNumericPosition(candidate.xScale, local.x)\n : undefined;\n },\n anchorAtDomain(point: Readonly<{ domainX: number; domainY: number }>) {\n geometry.assertLive();\n const anchorLocal = Object.freeze({\n x: candidate.xScale.map(point.domainX),\n y: candidate.yScale.map(point.domainY),\n });\n return Object.freeze({\n anchorLocal,\n anchorRoot: geometry.rootAtLocal(anchorLocal),\n });\n },\n });\n },\n );\n}\n\n/**\n * Owns optional numeric capture without reading signals or executing queries.\n * @param _series - Typed descriptor used for datum inference; not observed or registered.\n * @returns A stable mount-owned capture ref; pass it to one numeric series' inspection prop.\n * @see {@link NumericInspectionRef}\n */\nexport function useNumericInspection<D>(\n _series: HoverSeries<D>,\n): NumericInspectionRef<D> {\n return useCapture<D>();\n}\n\n/**\n * Owns optional circle/ring capture for one PointSeries; O(n) retained geometry when enabled.\n * @param _series - Typed descriptor used for datum inference; not observed or registered.\n * @returns A stable point inspection ref. Rendered records are borrowed until replacement/disposal.\n * @see {@link PointInspectionRef}\n */\nexport function usePointInspection<D>(\n _series: HoverSeries<D>,\n): PointInspectionRef<D> {\n return useCapture<D>();\n}\n"],
5
+ "mappings": "AAAA,SAAS,6BAA6B;AACtC,SAAS,sBAAsB;AAS/B,SAAS,aAAuC;AAC9C,SAAO;AAAA,IACL;AAAA,IACA,CAAC,WAAW,aAAa;AACvB,YAAM,OAAO,UAAU,aAAa;AAAA,QAAI,CAAC,QACvC,OAAO,OAAO;AAAA,UACZ,GAAG;AAAA,UACH,aAAa,OAAO,OAAO,EAAE,GAAG,IAAI,YAAY,CAAC;AAAA,UACjD,YAAY,SAAS,YAAY,IAAI,WAAW;AAAA,QAClD,CAAC;AAAA,MACH;AACA,aAAO,OAAO,OAAO;AAAA,QACnB,cAAc,OAAO,OAAO,IAAI;AAAA,QAChC,OAAO,OAAO,OAAO,UAAU,aAAa,MAAM,CAAC;AAAA,QACnD,YAAY,SAAS;AAAA,QACrB,aAAa,SAAS;AAAA,QACtB,mBAAmB,SAAS;AAAA,QAC5B,cAAc,OAA2C;AACvD,gBAAM,QAAQ,SAAS,YAAY,KAAK;AACxC,iBAAO,QACH,sBAAsB,UAAU,QAAQ,MAAM,CAAC,IAC/C;AAAA,QACN;AAAA,QACA,eAAe,OAAuD;AACpE,mBAAS,WAAW;AACpB,gBAAM,cAAc,OAAO,OAAO;AAAA,YAChC,GAAG,UAAU,OAAO,IAAI,MAAM,OAAO;AAAA,YACrC,GAAG,UAAU,OAAO,IAAI,MAAM,OAAO;AAAA,UACvC,CAAC;AACD,iBAAO,OAAO,OAAO;AAAA,YACnB;AAAA,YACA,YAAY,SAAS,YAAY,WAAW;AAAA,UAC9C,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAQO,SAAS,qBACd,SACyB;AACzB,SAAO,WAAc;AACvB;AAQO,SAAS,mBACd,SACuB;AACvB,SAAO,WAAc;AACvB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ import type { PibblEvent } from "@pibbl/core";
2
+ /** A mount-owned source of borrowed committed render records.
3
+ * @see {@link InspectionContext}
4
+ */
5
+ export interface InspectionRef<S> {
6
+ /** Returns the current committed record.
7
+ * @returns Borrowed record or undefined before paint/after disposal.
8
+ */
9
+ rendered(): S | undefined;
10
+ }
11
+ /** Lazy synchronous inspection; expires when its handler returns.
12
+ * @see {@link InspectionRef}
13
+ */
14
+ export interface InspectionContext {
15
+ /** Pins one receiver's committed generation for this logical dispatch.
16
+ * @param ref - Explicit ref identifying the mounted receiver.
17
+ * @returns Borrowed generation or undefined before paint/after disposal.
18
+ */
19
+ rendered<S>(ref: InspectionRef<S>): S | undefined;
20
+ /**
21
+ * Executes only on demand and memoizes equal requests, including no result.
22
+ * Options contain plain scalar fields, function identities and logical points.
23
+ * @param query - Pure synchronous query with a stable result contract.
24
+ * @param rendered - Committed generation pinned for this request.
25
+ * @param options - Named query parameters; functions compare by identity.
26
+ * @returns Query result, including undefined, reused for equal requests in dispatch.
27
+ */
28
+ request<S, A, R>(query: (rendered: S, options: A) => R, rendered: S, options: A): R;
29
+ }
30
+ /**
31
+ * Adapts an ordinary handler to lazy typed inspection without changing its event.
32
+ * @param handler - Synchronous callback receiving the unchanged event and an expiring context.
33
+ * @returns An ordinary event handler. Searches occur only on request; memo state releases at dispatch end.
34
+ * @see {@link InspectionContext}
35
+ */
36
+ export declare function withInspection<E extends PibblEvent>(handler: (event: E, context: InspectionContext) => void): (event: E) => void;
@@ -0,0 +1,91 @@
1
+ import {
2
+ borrowDispatchResource,
3
+ withHooksForbidden
4
+ } from "@pibbl/core/internal";
5
+ const dispatchKey = {};
6
+ function copyArguments(value, depth = 0) {
7
+ if (value === null || typeof value !== "object") return value;
8
+ if (depth > 2 || Object.getPrototypeOf(value) !== Object.prototype)
9
+ throw new TypeError(
10
+ "Inspection arguments must contain plain scalar options and logical points."
11
+ );
12
+ return Object.fromEntries(
13
+ Object.entries(value).map(([key, item]) => [
14
+ key,
15
+ copyArguments(item, depth + 1)
16
+ ])
17
+ );
18
+ }
19
+ function sameArguments(a, b) {
20
+ if (Object.is(a, b)) return true;
21
+ if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
22
+ const aa = a, bb = b;
23
+ const keys = Object.keys(aa);
24
+ return keys.length === Object.keys(bb).length && keys.every(
25
+ (key) => Object.hasOwn(bb, key) && sameArguments(aa[key], bb[key])
26
+ );
27
+ }
28
+ function withInspection(handler) {
29
+ return (event) => {
30
+ let live = true;
31
+ const borrow = () => {
32
+ if (!live)
33
+ throw new Error(
34
+ "Inspection context has expired; use it synchronously within dispatch."
35
+ );
36
+ return borrowDispatchResource(
37
+ event,
38
+ dispatchKey,
39
+ () => {
40
+ const value = {
41
+ live: true,
42
+ renders: /* @__PURE__ */ new Map(),
43
+ memo: []
44
+ };
45
+ return {
46
+ value,
47
+ dispose: () => {
48
+ value.live = false;
49
+ value.renders.clear();
50
+ value.memo.length = 0;
51
+ }
52
+ };
53
+ }
54
+ );
55
+ };
56
+ const context = Object.freeze({
57
+ rendered(ref) {
58
+ const state = borrow();
59
+ if (!state.renders.has(ref)) state.renders.set(ref, ref.rendered());
60
+ return state.renders.get(ref);
61
+ },
62
+ request(query, rendered, options) {
63
+ const state = borrow();
64
+ const args = copyArguments(options);
65
+ const cached = state.memo.find(
66
+ (memo) => memo.query === query && memo.rendered === rendered && sameArguments(memo.options, args)
67
+ );
68
+ if (cached) return cached.result;
69
+ const result = withHooksForbidden(
70
+ "Inspection queries must be pure synchronous functions.",
71
+ () => query(rendered, options)
72
+ );
73
+ if (result && typeof result.then === "function")
74
+ throw new TypeError("Inspection queries must be synchronous.");
75
+ state.memo.push({ query, rendered, options: args, result });
76
+ return result;
77
+ }
78
+ });
79
+ try {
80
+ const result = handler(event, context);
81
+ if (result && typeof result.then === "function")
82
+ throw new TypeError("Inspection handlers must be synchronous.");
83
+ } finally {
84
+ live = false;
85
+ }
86
+ };
87
+ }
88
+ export {
89
+ withInspection
90
+ };
91
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/inspection/handler.ts"],
4
+ "sourcesContent": ["import type { PibblEvent } from \"@pibbl/core\";\nimport {\n borrowDispatchResource,\n withHooksForbidden,\n} from \"@pibbl/core/internal\";\n\n/** A mount-owned source of borrowed committed render records.\n * @see {@link InspectionContext}\n */\nexport interface InspectionRef<S> {\n /** Returns the current committed record.\n * @returns Borrowed record or undefined before paint/after disposal.\n */\n rendered(): S | undefined;\n}\n\n/** Lazy synchronous inspection; expires when its handler returns.\n * @see {@link InspectionRef}\n */\nexport interface InspectionContext {\n /** Pins one receiver's committed generation for this logical dispatch.\n * @param ref - Explicit ref identifying the mounted receiver.\n * @returns Borrowed generation or undefined before paint/after disposal.\n */\n rendered<S>(ref: InspectionRef<S>): S | undefined;\n /**\n * Executes only on demand and memoizes equal requests, including no result.\n * Options contain plain scalar fields, function identities and logical points.\n * @param query - Pure synchronous query with a stable result contract.\n * @param rendered - Committed generation pinned for this request.\n * @param options - Named query parameters; functions compare by identity.\n * @returns Query result, including undefined, reused for equal requests in dispatch.\n */\n request<S, A, R>(\n query: (rendered: S, options: A) => R,\n rendered: S,\n options: A,\n ): R;\n}\n\nconst dispatchKey = {};\ninterface Memo {\n query: unknown;\n rendered: unknown;\n options: unknown;\n result: unknown;\n}\ninterface DispatchInspection {\n live: boolean;\n renders: Map<object, unknown>;\n memo: Memo[];\n}\n\nfunction copyArguments(value: unknown, depth = 0): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (depth > 2 || Object.getPrototypeOf(value) !== Object.prototype)\n throw new TypeError(\n \"Inspection arguments must contain plain scalar options and logical points.\",\n );\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [\n key,\n copyArguments(item, depth + 1),\n ]),\n );\n}\nfunction sameArguments(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (!a || !b || typeof a !== \"object\" || typeof b !== \"object\") return false;\n const aa = a as Record<string, unknown>,\n bb = b as Record<string, unknown>;\n const keys = Object.keys(aa);\n return (\n keys.length === Object.keys(bb).length &&\n keys.every(\n (key) => Object.hasOwn(bb, key) && sameArguments(aa[key], bb[key]),\n )\n );\n}\n\n/**\n * Adapts an ordinary handler to lazy typed inspection without changing its event.\n * @param handler - Synchronous callback receiving the unchanged event and an expiring context.\n * @returns An ordinary event handler. Searches occur only on request; memo state releases at dispatch end.\n * @see {@link InspectionContext}\n */\nexport function withInspection<E extends PibblEvent>(\n handler: (event: E, context: InspectionContext) => void,\n): (event: E) => void {\n return (event) => {\n let live = true;\n const borrow = () => {\n if (!live)\n throw new Error(\n \"Inspection context has expired; use it synchronously within dispatch.\",\n );\n return borrowDispatchResource<DispatchInspection>(\n event,\n dispatchKey,\n () => {\n const value: DispatchInspection = {\n live: true,\n renders: new Map(),\n memo: [],\n };\n return {\n value,\n dispose: () => {\n value.live = false;\n value.renders.clear();\n value.memo.length = 0;\n },\n };\n },\n );\n };\n const context: InspectionContext = Object.freeze({\n rendered<S>(ref: InspectionRef<S>): S | undefined {\n const state = borrow();\n if (!state.renders.has(ref)) state.renders.set(ref, ref.rendered());\n return state.renders.get(ref) as S | undefined;\n },\n request<S, A, R>(\n query: (rendered: S, options: A) => R,\n rendered: S,\n options: A,\n ): R {\n const state = borrow();\n const args = copyArguments(options);\n const cached = state.memo.find(\n (memo) =>\n memo.query === query &&\n memo.rendered === rendered &&\n sameArguments(memo.options, args),\n );\n if (cached) return cached.result as R;\n const result = withHooksForbidden(\n \"Inspection queries must be pure synchronous functions.\",\n () => query(rendered, options),\n );\n if (result && typeof (result as { then?: unknown }).then === \"function\")\n throw new TypeError(\"Inspection queries must be synchronous.\");\n state.memo.push({ query, rendered, options: args, result });\n return result;\n },\n });\n try {\n const result = handler(event, context) as unknown;\n if (result && typeof (result as { then?: unknown }).then === \"function\")\n throw new TypeError(\"Inspection handlers must be synchronous.\");\n } finally {\n live = false;\n }\n };\n}\n"],
5
+ "mappings": "AACA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAoCP,MAAM,cAAc,CAAC;AAarB,SAAS,cAAc,OAAgB,QAAQ,GAAY;AACzD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,QAAQ,KAAK,OAAO,eAAe,KAAK,MAAM,OAAO;AACvD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM;AAAA,MACzC;AAAA,MACA,cAAc,MAAM,QAAQ,CAAC;AAAA,IAC/B,CAAC;AAAA,EACH;AACF;AACA,SAAS,cAAc,GAAY,GAAqB;AACtD,MAAI,OAAO,GAAG,GAAG,CAAC,EAAG,QAAO;AAC5B,MAAI,CAAC,KAAK,CAAC,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO;AACvE,QAAM,KAAK,GACT,KAAK;AACP,QAAM,OAAO,OAAO,KAAK,EAAE;AAC3B,SACE,KAAK,WAAW,OAAO,KAAK,EAAE,EAAE,UAChC,KAAK;AAAA,IACH,CAAC,QAAQ,OAAO,OAAO,IAAI,GAAG,KAAK,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,EACnE;AAEJ;AAQO,SAAS,eACd,SACoB;AACpB,SAAO,CAAC,UAAU;AAChB,QAAI,OAAO;AACX,UAAM,SAAS,MAAM;AACnB,UAAI,CAAC;AACH,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AACF,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,MAAM;AACJ,gBAAM,QAA4B;AAAA,YAChC,MAAM;AAAA,YACN,SAAS,oBAAI,IAAI;AAAA,YACjB,MAAM,CAAC;AAAA,UACT;AACA,iBAAO;AAAA,YACL;AAAA,YACA,SAAS,MAAM;AACb,oBAAM,OAAO;AACb,oBAAM,QAAQ,MAAM;AACpB,oBAAM,KAAK,SAAS;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAA6B,OAAO,OAAO;AAAA,MAC/C,SAAY,KAAsC;AAChD,cAAM,QAAQ,OAAO;AACrB,YAAI,CAAC,MAAM,QAAQ,IAAI,GAAG,EAAG,OAAM,QAAQ,IAAI,KAAK,IAAI,SAAS,CAAC;AAClE,eAAO,MAAM,QAAQ,IAAI,GAAG;AAAA,MAC9B;AAAA,MACA,QACE,OACA,UACA,SACG;AACH,cAAM,QAAQ,OAAO;AACrB,cAAM,OAAO,cAAc,OAAO;AAClC,cAAM,SAAS,MAAM,KAAK;AAAA,UACxB,CAAC,SACC,KAAK,UAAU,SACf,KAAK,aAAa,YAClB,cAAc,KAAK,SAAS,IAAI;AAAA,QACpC;AACA,YAAI,OAAQ,QAAO,OAAO;AAC1B,cAAM,SAAS;AAAA,UACb;AAAA,UACA,MAAM,MAAM,UAAU,OAAO;AAAA,QAC/B;AACA,YAAI,UAAU,OAAQ,OAA8B,SAAS;AAC3D,gBAAM,IAAI,UAAU,yCAAyC;AAC/D,cAAM,KAAK,KAAK,EAAE,OAAO,UAAU,SAAS,MAAM,OAAO,CAAC;AAC1D,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AACD,QAAI;AACF,YAAM,SAAS,QAAQ,OAAO,OAAO;AACrC,UAAI,UAAU,OAAQ,OAA8B,SAAS;AAC3D,cAAM,IAAI,UAAU,0CAA0C;AAAA,IAClE,UAAE;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }