@pibbl/core 0.0.2 → 0.0.3-alpha.90.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 (285) 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 +68 -6
  30. package/dist/features/viz/index.js +164 -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/graph/bipartite.d.ts +14 -0
  120. package/dist/features/viz/lib/graph/bipartite.js +250 -0
  121. package/dist/features/viz/lib/graph/bipartite.js.map +7 -0
  122. package/dist/features/viz/lib/graph/chord.d.ts +44 -0
  123. package/dist/features/viz/lib/graph/chord.js +348 -0
  124. package/dist/features/viz/lib/graph/chord.js.map +7 -0
  125. package/dist/features/viz/lib/graph/dependency.d.ts +26 -0
  126. package/dist/features/viz/lib/graph/dependency.js +141 -0
  127. package/dist/features/viz/lib/graph/dependency.js.map +7 -0
  128. package/dist/features/viz/lib/graph/force.d.ts +28 -0
  129. package/dist/features/viz/lib/graph/force.js +580 -0
  130. package/dist/features/viz/lib/graph/force.js.map +7 -0
  131. package/dist/features/viz/lib/graph/hierarchy.d.ts +21 -0
  132. package/dist/features/viz/lib/graph/hierarchy.js +112 -0
  133. package/dist/features/viz/lib/graph/hierarchy.js.map +7 -0
  134. package/dist/features/viz/lib/graph/icicle.d.ts +16 -0
  135. package/dist/features/viz/lib/graph/icicle.js +153 -0
  136. package/dist/features/viz/lib/graph/icicle.js.map +7 -0
  137. package/dist/features/viz/lib/graph/matrix.d.ts +30 -0
  138. package/dist/features/viz/lib/graph/matrix.js +243 -0
  139. package/dist/features/viz/lib/graph/matrix.js.map +7 -0
  140. package/dist/features/viz/lib/graph/neighborhood.d.ts +11 -0
  141. package/dist/features/viz/lib/graph/neighborhood.js +281 -0
  142. package/dist/features/viz/lib/graph/neighborhood.js.map +7 -0
  143. package/dist/features/viz/lib/graph/routes.d.ts +35 -0
  144. package/dist/features/viz/lib/graph/routes.js +102 -0
  145. package/dist/features/viz/lib/graph/routes.js.map +7 -0
  146. package/dist/features/viz/lib/graph/sankey.d.ts +44 -0
  147. package/dist/features/viz/lib/graph/sankey.js +341 -0
  148. package/dist/features/viz/lib/graph/sankey.js.map +7 -0
  149. package/dist/features/viz/lib/graph/shared.d.ts +59 -0
  150. package/dist/features/viz/lib/graph/shared.js +296 -0
  151. package/dist/features/viz/lib/graph/shared.js.map +7 -0
  152. package/dist/features/viz/lib/graph/tree.d.ts +11 -0
  153. package/dist/features/viz/lib/graph/tree.js +232 -0
  154. package/dist/features/viz/lib/graph/tree.js.map +7 -0
  155. package/dist/features/viz/lib/graph/treemap.d.ts +20 -0
  156. package/dist/features/viz/lib/graph/treemap.js +227 -0
  157. package/dist/features/viz/lib/graph/treemap.js.map +7 -0
  158. package/dist/features/viz/lib/graph/types.d.ts +1097 -0
  159. package/dist/features/viz/lib/hover-data.d.ts +1 -1
  160. package/dist/features/viz/lib/hover-data.js +5 -2
  161. package/dist/features/viz/lib/hover-data.js.map +2 -2
  162. package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
  163. package/dist/features/viz/lib/interval-band-series.js +136 -0
  164. package/dist/features/viz/lib/interval-band-series.js.map +7 -0
  165. package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
  166. package/dist/features/viz/lib/interval-diamond-series.js +124 -0
  167. package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
  168. package/dist/features/viz/lib/interval-series.d.ts +79 -0
  169. package/dist/features/viz/lib/interval-series.js +158 -0
  170. package/dist/features/viz/lib/interval-series.js.map +7 -0
  171. package/dist/features/viz/lib/line-series.d.ts +1 -1
  172. package/dist/features/viz/lib/line-series.js +47 -28
  173. package/dist/features/viz/lib/line-series.js.map +2 -2
  174. package/dist/features/viz/lib/linear-scale.js +1 -1
  175. package/dist/features/viz/lib/linear-scale.js.map +2 -2
  176. package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
  177. package/dist/features/viz/lib/monotone-curve.js +63 -0
  178. package/dist/features/viz/lib/monotone-curve.js.map +7 -0
  179. package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
  180. package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
  181. package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
  182. package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
  183. package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
  184. package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
  185. package/dist/features/viz/lib/paired-series.d.ts +44 -0
  186. package/dist/features/viz/lib/paired-series.js +93 -0
  187. package/dist/features/viz/lib/paired-series.js.map +7 -0
  188. package/dist/features/viz/lib/plot-series.js +11 -6
  189. package/dist/features/viz/lib/plot-series.js.map +2 -2
  190. package/dist/features/viz/lib/plot-types.d.ts +4 -3
  191. package/dist/features/viz/lib/point-series.d.ts +1 -1
  192. package/dist/features/viz/lib/point-series.js +36 -9
  193. package/dist/features/viz/lib/point-series.js.map +2 -2
  194. package/dist/features/viz/lib/point-types.d.ts +5 -2
  195. package/dist/features/viz/lib/scale-context.d.ts +1 -1
  196. package/dist/features/viz/lib/scale-ticks.js +21 -6
  197. package/dist/features/viz/lib/scale-ticks.js.map +2 -2
  198. package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
  199. package/dist/features/viz/lib/sequential-color-scale.js +49 -0
  200. package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
  201. package/dist/features/viz/lib/series-position.d.ts +12 -0
  202. package/dist/features/viz/lib/series-position.js +44 -0
  203. package/dist/features/viz/lib/series-position.js.map +7 -0
  204. package/dist/features/viz/lib/step-curves.d.ts +19 -0
  205. package/dist/features/viz/lib/step-curves.js +53 -0
  206. package/dist/features/viz/lib/step-curves.js.map +7 -0
  207. package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
  208. package/dist/features/viz/lib/threshold-color-scale.js +59 -0
  209. package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
  210. package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
  211. package/dist/features/viz/lib/trading-time-mapping.js +89 -0
  212. package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
  213. package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
  214. package/dist/features/viz/lib/trading-time-scale.js +96 -0
  215. package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
  216. package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
  217. package/dist/features/viz/lib/trajectory-series.js +111 -0
  218. package/dist/features/viz/lib/trajectory-series.js.map +7 -0
  219. package/dist/features/viz/lib/types.d.ts +20 -4
  220. package/dist/features/viz/lib/use-continuous-scale.js +6 -1
  221. package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
  222. package/dist/features/viz/lib/volume-series.d.ts +59 -0
  223. package/dist/features/viz/lib/volume-series.js +117 -0
  224. package/dist/features/viz/lib/volume-series.js.map +7 -0
  225. package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
  226. package/dist/features/viz/lib/weighted-point-series.js +169 -0
  227. package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
  228. package/dist/filters/backdrop-contrast-gpu.d.ts +5 -0
  229. package/dist/filters/backdrop-contrast-gpu.js +33 -0
  230. package/dist/filters/backdrop-contrast-gpu.js.map +7 -0
  231. package/dist/filters/backdrop-contrast.d.ts +21 -0
  232. package/dist/filters/backdrop-contrast.js +61 -0
  233. package/dist/filters/backdrop-contrast.js.map +7 -0
  234. package/dist/filters/emboss-gpu.d.ts +4 -0
  235. package/dist/filters/emboss-gpu.js +39 -0
  236. package/dist/filters/emboss-gpu.js.map +7 -0
  237. package/dist/filters/emboss.d.ts +32 -0
  238. package/dist/filters/emboss.js +106 -0
  239. package/dist/filters/emboss.js.map +7 -0
  240. package/dist/filters/filter-executor.d.ts +11 -4
  241. package/dist/filters/filter-executor.js +104 -49
  242. package/dist/filters/filter-executor.js.map +2 -2
  243. package/dist/filters/reflection-gpu.d.ts +3 -1
  244. package/dist/filters/reflection-gpu.js +5 -2
  245. package/dist/filters/reflection-gpu.js.map +2 -2
  246. package/dist/filters/render-backdrop-contrast-boundary.d.ts +31 -0
  247. package/dist/filters/render-backdrop-contrast-boundary.js +116 -0
  248. package/dist/filters/render-backdrop-contrast-boundary.js.map +7 -0
  249. package/dist/filters/render-emboss-boundary.d.ts +13 -0
  250. package/dist/filters/render-emboss-boundary.js +131 -0
  251. package/dist/filters/render-emboss-boundary.js.map +7 -0
  252. package/dist/filters.d.ts +9 -5
  253. package/dist/filters.js +4 -0
  254. package/dist/filters.js.map +2 -2
  255. package/dist/index.d.ts +2 -0
  256. package/dist/index.js +3 -0
  257. package/dist/index.js.map +2 -2
  258. package/dist/internal.d.ts +2 -0
  259. package/dist/internal.js +4 -0
  260. package/dist/internal.js.map +2 -2
  261. package/dist/lib/events/event-facade.d.ts +13 -0
  262. package/dist/lib/events/event-facade.js +23 -0
  263. package/dist/lib/events/event-facade.js.map +2 -2
  264. package/dist/lib/events/propagation.js +19 -14
  265. package/dist/lib/events/propagation.js.map +2 -2
  266. package/dist/lib/execute-render.js +13 -0
  267. package/dist/lib/execute-render.js.map +2 -2
  268. package/dist/lib/recording/recording.d.ts +43 -0
  269. package/dist/lib/recording/recording.js +555 -0
  270. package/dist/lib/recording/recording.js.map +7 -0
  271. package/dist/lib/recording/types.d.ts +118 -0
  272. package/dist/lib/recording/wasm-bytes.d.ts +1 -0
  273. package/dist/lib/recording/wasm-bytes.js +5 -0
  274. package/dist/lib/recording/wasm-bytes.js.map +7 -0
  275. package/dist/lib/recording/worker-source.d.ts +1 -0
  276. package/dist/lib/recording/worker-source.js +5 -0
  277. package/dist/lib/recording/worker-source.js.map +7 -0
  278. package/dist/lib/render-transaction.d.ts +5 -2
  279. package/dist/lib/render-transaction.js +23 -1
  280. package/dist/lib/render-transaction.js.map +2 -2
  281. package/dist/lib/series-inspection-frame.d.ts +18 -0
  282. package/dist/lib/series-inspection-frame.js +70 -0
  283. package/dist/lib/series-inspection-frame.js.map +7 -0
  284. package/dist/lib/types.d.ts +6 -0
  285. package/package.json +10 -2
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/censored-point-series.tsx"],
4
+ "sourcesContent": ["import { Path, resolveSignalValue } from \"@pibbl/core\";\nimport type {\n FillStyle,\n PibblEventHandlers,\n PibblEventParticipationOptions,\n SignalValue,\n StrokeStyle,\n} from \"@pibbl/core\";\nimport type { SignalStyle } from \"@pibbl/core/internal\";\nimport { validateTexturePaint, withHooksForbidden } from \"@pibbl/core/internal\";\nimport type { LineAccessor, ScaleId } from \"./types.js\";\nimport { finiteCoordinate, pointAccessor, pointData } from \"./point-data.js\";\nimport { opacity, width } from \"./paint.js\";\nimport { useContinuousScale } from \"./use-continuous-scale.js\";\n\n/** A supplied assay reporting status. `below` and `above` retain the supplied reporting limit.\n * @see {@link CensoredPointSeriesProps}\n */\nexport type CensoringStatus = \"observed\" | \"below\" | \"above\";\n\n/** Extracts an observation's supplied reporting status.\n * @param datum - Original record being read.\n * @param index - Zero-based source index.\n * @param data - Complete supplied record array.\n * @returns The supplied status, or a nullish sentinel that omits the record.\n * @see {@link CensoringStatus}\n */\nexport type CensoringAccessor<D> =\n | {\n [K in keyof D]-?: D[K] extends CensoringStatus | null | undefined\n ? K\n : never;\n }[keyof D]\n | ((\n datum: D,\n index: number,\n data: readonly D[],\n ) => CensoringStatus | null | undefined);\n\n/** Shared mark paint and local-pixel geometry for {@link CensoredPointSeries}. */\nexport interface CensoredPointSeriesStyle {\n /** Circle and open censor marker radius in local pixels; defaults to 4. */\n readonly radius?: number;\n /** Fill for observed circles; defaults to #087f8c. Censor markers remain open. */\n readonly fill?: FillStyle;\n /** Outline for circles and open directional censor markers; defaults to #087f8c. */\n readonly stroke?: StrokeStyle;\n /** Outline width in local pixels; defaults to 1.5. */\n readonly strokeWidth?: number;\n /** Shared paint opacity from zero to one; defaults to 1. */\n readonly opacity?: number;\n /** Cursor for painted mark targets. */\n readonly cursor?: string;\n}\n\n/** Authored inputs for supplied observed and censored numeric observations.\n * @see {@link CensoredPointSeries}\n */\nexport interface CensoredPointSeriesProps<D>\n extends PibblEventHandlers, PibblEventParticipationOptions {\n /** Original records, or a signal of records. The series performs no imputation or inference. */\n readonly data: SignalValue<readonly D[]>;\n /** Property or callback supplying the numeric horizontal coordinate. */\n readonly x: LineAccessor<D>;\n /** Property or callback supplying the numeric vertical value or reporting limit. */\n readonly y: LineAccessor<D>;\n /** Property or callback yielding `observed`, `below`, or `above`. */\n readonly censoring: CensoringAccessor<D>;\n /** Ancestor continuous numeric scale mapping x. */\n readonly xScale: ScaleId;\n /** Ancestor continuous numeric scale mapping y and its reporting limit. */\n readonly yScale: ScaleId;\n /** Optional synchronous predicate; excluded rows contribute no mark.\n * @param datum - Original record being tested.\n * @param index - Zero-based source index.\n * @param data - Complete supplied record array.\n * @returns Whether this record contributes a mark.\n */\n readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;\n /** Shared style; whole-object and shallow field signals are observed by the series. */\n readonly style?: SignalValue<SignalStyle<CensoredPointSeriesStyle>>;\n}\n\nconst fields = [\"radius\", \"fill\", \"stroke\", \"strokeWidth\", \"opacity\", \"cursor\"];\n\nfunction paint(\n value: unknown,\n name: string,\n): FillStyle | StrokeStyle | undefined {\n if (\n value === undefined ||\n typeof value === \"string\" ||\n value instanceof CanvasGradient ||\n value instanceof CanvasPattern\n )\n return value;\n try {\n validateTexturePaint(value as never);\n return value as FillStyle | StrokeStyle;\n } catch {\n // Fall through to the local series error rather than leaking protocol detail.\n }\n throw new TypeError(`CensoredPointSeries: invalid ${name}.`);\n}\n\nfunction triangle(\n path: Path2D,\n x: number,\n y: number,\n radius: number,\n direction: number,\n) {\n path.moveTo(x, y + direction * radius);\n path.lineTo(x - radius * 0.78, y - direction * radius * 0.55);\n path.lineTo(x + radius * 0.78, y - direction * radius * 0.55);\n path.closePath();\n}\n\n/**\n * Draws supplied numeric observations as circles and below/above reporting limits as open arrows.\n *\n * `below` points toward decreasing y-domain values and `above` toward increasing y-domain values,\n * including when the y scale uses a reversed domain or range. The supplied `y` value remains the\n * reporting limit; this component never substitutes a measurement, imputes a value, or fits a model.\n *\n * @param props - Supplied observations, coordinates, reporting statuses, scales, and paint.\n * See {@link CensoredPointSeriesProps}.\n * @returns Two ordinary batched paths for observed and open censored marks.\n * @see {@link CensoredPointSeriesProps}\n */\nexport function CensoredPointSeries<D>({\n data: input,\n x: xInput,\n y: yInput,\n censoring: censoringInput,\n xScale: xId,\n yScale: yId,\n defined,\n style: styleInput,\n pointerEvents,\n ...events\n}: CensoredPointSeriesProps<D>) {\n const xScale = useContinuousScale(xId).get();\n const yScale = useContinuousScale(yId).get();\n const data = pointData(resolveSignalValue(input), \"CensoredPointSeries\");\n const x = pointAccessor(xInput),\n y = pointAccessor(yInput);\n const censoring =\n typeof censoringInput === \"function\"\n ? censoringInput\n : (datum: D) =>\n datum[censoringInput] as CensoringStatus | null | undefined;\n const specified = resolveSignalValue(styleInput) ?? {};\n if (\n specified === null ||\n typeof specified !== \"object\" ||\n Array.isArray(specified)\n )\n throw new TypeError(\"CensoredPointSeries: style must be an object.\");\n const style: Record<string, unknown> = {};\n for (const key of Object.keys(specified)) {\n if (!fields.includes(key))\n throw new TypeError(\n `CensoredPointSeries: unsupported style field ${key}.`,\n );\n style[key] = resolveSignalValue(\n (specified as Record<string, unknown>)[key],\n );\n }\n const resolved = style as CensoredPointSeriesStyle;\n const radius = width(resolved.radius ?? 4, \"CensoredPointSeries radius\");\n const strokeWidth = width(resolved.strokeWidth ?? 1.5, \"CensoredPointSeries\");\n const alpha = opacity(resolved.opacity ?? 1, \"CensoredPointSeries\");\n if (resolved.cursor !== undefined && typeof resolved.cursor !== \"string\")\n throw new TypeError(\"CensoredPointSeries: cursor must be a string.\");\n const fill = paint(resolved.fill ?? \"#087f8c\", \"fill\");\n const stroke = paint(resolved.stroke ?? \"#087f8c\", \"stroke\");\n const observed = new Path2D();\n const censored = new Path2D();\n // The sign is a property of the domain-to-range mapping, rather than canvas orientation.\n const increasingY = Math.sign(\n (yScale.domain[1] - yScale.domain[0]) * (yScale.range[1] - yScale.range[0]),\n );\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n const coordinates = withHooksForbidden(\n \"CensoredPointSeries: accessors cannot call hooks.\",\n () => {\n if (defined && !defined(datum, i, data)) return undefined;\n return {\n x: x(datum, i, data),\n y: y(datum, i, data),\n censoring: censoring(datum, i, data),\n };\n },\n );\n if (\n !coordinates ||\n !finiteCoordinate(coordinates.x) ||\n !finiteCoordinate(coordinates.y) ||\n coordinates.censoring == null\n )\n continue;\n if (\n !([\"observed\", \"below\", \"above\"] as const).includes(coordinates.censoring)\n )\n throw new TypeError(\n `CensoredPointSeries: unknown censoring status ${String(coordinates.censoring)} (row ${i}).`,\n );\n const px = xScale.map(coordinates.x),\n py = yScale.map(coordinates.y);\n if (!Number.isFinite(px) || !Number.isFinite(py))\n throw new RangeError(\n `CensoredPointSeries: mapped coordinates must be finite (row ${i}).`,\n );\n if (radius === 0) continue;\n if (coordinates.censoring === \"observed\") {\n observed.moveTo(px + radius, py);\n observed.arc(px, py, radius, 0, Math.PI * 2);\n observed.closePath();\n } else {\n const direction =\n coordinates.censoring === \"above\" ? increasingY : -increasingY;\n triangle(censored, px, py, radius, direction || 1);\n }\n }\n const common = {\n stroke,\n strokeWidth,\n opacity: alpha,\n cursor: resolved.cursor,\n };\n return (\n <>\n <Path\n {...events}\n pointerEvents={pointerEvents}\n style={{ d: observed, fill, ...common }}\n />\n <Path\n {...events}\n pointerEvents={pointerEvents}\n style={{ d: censored, fill: \"transparent\", ...common }}\n />\n </>\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,4 @@
1
+ import { type Signal } from "@pibbl/core";
2
+ import type { ScaleId } from "./types.js";
3
+ export declare function provideColor<T>(id: ScaleId, kind: string, resolve: () => T, deps: readonly unknown[]): void;
4
+ export declare function useColor<T>(id: ScaleId, kind: string): Signal<T>;
@@ -0,0 +1,41 @@
1
+ import { useComputed } from "@pibbl/core";
2
+ import {
3
+ getCurrentBackendHostCanvas,
4
+ setCurrentComponentAfterRender,
5
+ useInternalHookSlot
6
+ } from "@pibbl/core/internal";
7
+ let current;
8
+ function provideColor(id, kind, resolve, deps) {
9
+ if ((typeof id !== "string" || id.length === 0) && typeof id !== "symbol")
10
+ throw new TypeError("Color scale id requires a nonempty string or symbol.");
11
+ const value = useComputed(resolve, deps), parent = current;
12
+ current = { id, kind, value, canvas: getCurrentBackendHostCanvas(), parent };
13
+ const restore = () => {
14
+ current = parent;
15
+ };
16
+ try {
17
+ setCurrentComponentAfterRender(restore);
18
+ } catch (error) {
19
+ restore();
20
+ throw error;
21
+ }
22
+ }
23
+ function useColor(id, kind) {
24
+ useInternalHookSlot("vizColorScaleLookup", () => void 0);
25
+ for (let scope = current; scope; scope = scope.parent) {
26
+ if (scope.id !== id) continue;
27
+ if (scope.canvas !== getCurrentBackendHostCanvas())
28
+ throw new Error("Color scale cannot cross a Layer boundary.");
29
+ if (scope.kind !== kind)
30
+ throw new TypeError(`Expected ${kind} color scale; found ${scope.kind}.`);
31
+ return scope.value;
32
+ }
33
+ throw new Error(
34
+ `Unknown color scale ${String(id)}; add the matching ancestor provider.`
35
+ );
36
+ }
37
+ export {
38
+ provideColor,
39
+ useColor
40
+ };
41
+ //# sourceMappingURL=color-context.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/color-context.ts"],
4
+ "sourcesContent": ["import { useComputed, type Signal } from \"@pibbl/core\";\nimport {\n getCurrentBackendHostCanvas,\n setCurrentComponentAfterRender,\n useInternalHookSlot,\n} from \"@pibbl/core/internal\";\nimport type { ScaleId } from \"./types.js\";\ninterface Scope {\n id: ScaleId;\n kind: string;\n value: Signal<unknown>;\n canvas: ReturnType<typeof getCurrentBackendHostCanvas>;\n parent: Scope | undefined;\n}\nlet current: Scope | undefined;\nexport function provideColor<T>(\n id: ScaleId,\n kind: string,\n resolve: () => T,\n deps: readonly unknown[],\n): void {\n if ((typeof id !== \"string\" || id.length === 0) && typeof id !== \"symbol\")\n throw new TypeError(\"Color scale id requires a nonempty string or symbol.\");\n const value = useComputed(resolve, deps),\n parent = current;\n current = { id, kind, value, canvas: getCurrentBackendHostCanvas(), parent };\n const restore = () => {\n current = parent;\n };\n try {\n setCurrentComponentAfterRender(restore);\n } catch (error) {\n restore();\n throw error;\n }\n}\nexport function useColor<T>(id: ScaleId, kind: string): Signal<T> {\n useInternalHookSlot(\"vizColorScaleLookup\", () => undefined);\n for (let scope = current; scope; scope = scope.parent) {\n if (scope.id !== id) continue;\n if (scope.canvas !== getCurrentBackendHostCanvas())\n throw new Error(\"Color scale cannot cross a Layer boundary.\");\n if (scope.kind !== kind)\n throw new TypeError(`Expected ${kind} color scale; found ${scope.kind}.`);\n return scope.value as Signal<T>;\n }\n throw new Error(\n `Unknown color scale ${String(id)}; add the matching ancestor provider.`,\n );\n}\n"],
5
+ "mappings": "AAAA,SAAS,mBAAgC;AACzC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AASP,IAAI;AACG,SAAS,aACd,IACA,MACA,SACA,MACM;AACN,OAAK,OAAO,OAAO,YAAY,GAAG,WAAW,MAAM,OAAO,OAAO;AAC/D,UAAM,IAAI,UAAU,sDAAsD;AAC5E,QAAM,QAAQ,YAAY,SAAS,IAAI,GACrC,SAAS;AACX,YAAU,EAAE,IAAI,MAAM,OAAO,QAAQ,4BAA4B,GAAG,OAAO;AAC3E,QAAM,UAAU,MAAM;AACpB,cAAU;AAAA,EACZ;AACA,MAAI;AACF,mCAA+B,OAAO;AAAA,EACxC,SAAS,OAAO;AACd,YAAQ;AACR,UAAM;AAAA,EACR;AACF;AACO,SAAS,SAAY,IAAa,MAAyB;AAChE,sBAAoB,uBAAuB,MAAM,MAAS;AAC1D,WAAS,QAAQ,SAAS,OAAO,QAAQ,MAAM,QAAQ;AACrD,QAAI,MAAM,OAAO,GAAI;AACrB,QAAI,MAAM,WAAW,4BAA4B;AAC/C,YAAM,IAAI,MAAM,4CAA4C;AAC9D,QAAI,MAAM,SAAS;AACjB,YAAM,IAAI,UAAU,YAAY,IAAI,uBAAuB,MAAM,IAAI,GAAG;AAC1E,WAAO,MAAM;AAAA,EACf;AACA,QAAM,IAAI;AAAA,IACR,uBAAuB,OAAO,EAAE,CAAC;AAAA,EACnC;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,4 @@
1
+ export declare function finiteColorValue(value: number): number;
2
+ export declare function hexColor(color: string): string;
3
+ export declare function colorMix(a: string, b: string, t: number): string;
4
+ export declare function colorPosition(value: number, a: number, b: number): number;
@@ -0,0 +1,31 @@
1
+ function finiteColorValue(value) {
2
+ if (typeof value !== "number" || !Number.isFinite(value))
3
+ throw new RangeError("Color scale values must be finite numbers.");
4
+ return value;
5
+ }
6
+ function hexColor(color) {
7
+ if (typeof color !== "string" || !/^#[0-9a-f]{6}$/i.test(color))
8
+ throw new TypeError("Color scales require #RRGGBB colors.");
9
+ return color.toLowerCase();
10
+ }
11
+ function colorMix(a, b, t) {
12
+ return "#" + [1, 3, 5].map(
13
+ (i) => Math.round(
14
+ parseInt(a.slice(i, i + 2), 16) * (1 - t) + parseInt(b.slice(i, i + 2), 16) * t
15
+ ).toString(16).padStart(2, "0")
16
+ ).join("");
17
+ }
18
+ function colorPosition(value, a, b) {
19
+ if (a === b) return 0.5;
20
+ if (a < b && value <= a || a > b && value >= a) return 0;
21
+ if (a < b && value >= b || a > b && value <= b) return 1;
22
+ const span = b - a;
23
+ return Number.isFinite(span) ? (value - a) / span : (value / 2 - a / 2) / (b / 2 - a / 2);
24
+ }
25
+ export {
26
+ colorMix,
27
+ colorPosition,
28
+ finiteColorValue,
29
+ hexColor
30
+ };
31
+ //# sourceMappingURL=color-math.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/color-math.ts"],
4
+ "sourcesContent": ["export function finiteColorValue(value: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value))\n throw new RangeError(\"Color scale values must be finite numbers.\");\n return value;\n}\nexport function hexColor(color: string): string {\n if (typeof color !== \"string\" || !/^#[0-9a-f]{6}$/i.test(color))\n throw new TypeError(\"Color scales require #RRGGBB colors.\");\n return color.toLowerCase();\n}\nexport function colorMix(a: string, b: string, t: number): string {\n return (\n \"#\" +\n [1, 3, 5]\n .map((i) =>\n Math.round(\n parseInt(a.slice(i, i + 2), 16) * (1 - t) +\n parseInt(b.slice(i, i + 2), 16) * t,\n )\n .toString(16)\n .padStart(2, \"0\"),\n )\n .join(\"\")\n );\n}\nexport function colorPosition(value: number, a: number, b: number): number {\n if (a === b) return 0.5;\n if ((a < b && value <= a) || (a > b && value >= a)) return 0;\n if ((a < b && value >= b) || (a > b && value <= b)) return 1;\n const span = b - a;\n return Number.isFinite(span)\n ? (value - a) / span\n : (value / 2 - a / 2) / (b / 2 - a / 2);\n}\n"],
5
+ "mappings": "AAAO,SAAS,iBAAiB,OAAuB;AACtD,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK;AACrD,UAAM,IAAI,WAAW,4CAA4C;AACnE,SAAO;AACT;AACO,SAAS,SAAS,OAAuB;AAC9C,MAAI,OAAO,UAAU,YAAY,CAAC,kBAAkB,KAAK,KAAK;AAC5D,UAAM,IAAI,UAAU,sCAAsC;AAC5D,SAAO,MAAM,YAAY;AAC3B;AACO,SAAS,SAAS,GAAW,GAAW,GAAmB;AAChE,SACE,MACA,CAAC,GAAG,GAAG,CAAC,EACL;AAAA,IAAI,CAAC,MACJ,KAAK;AAAA,MACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,KACrC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI;AAAA,IACtC,EACG,SAAS,EAAE,EACX,SAAS,GAAG,GAAG;AAAA,EACpB,EACC,KAAK,EAAE;AAEd;AACO,SAAS,cAAc,OAAe,GAAW,GAAmB;AACzE,MAAI,MAAM,EAAG,QAAO;AACpB,MAAK,IAAI,KAAK,SAAS,KAAO,IAAI,KAAK,SAAS,EAAI,QAAO;AAC3D,MAAK,IAAI,KAAK,SAAS,KAAO,IAAI,KAAK,SAAS,EAAI,QAAO;AAC3D,QAAM,OAAO,IAAI;AACjB,SAAO,OAAO,SAAS,IAAI,KACtB,QAAQ,KAAK,QACb,QAAQ,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI;AACzC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,53 @@
1
+ import type { PibblNode, SignalValue } from "@pibbl/core";
2
+ import type { ScaleId } from "./types.js";
3
+ /** One authored domain/color association. @see {@link ResolvedSequentialColorScale} */
4
+ export interface ColorScaleStop {
5
+ /** Numeric data value at the color stop. */ readonly value: number;
6
+ /** Canonical lowercase six-digit hexadecimal sRGB color. */ readonly color: string;
7
+ }
8
+ /** Readonly continuous two-stop color mapping. @see {@link SequentialColorScaleProps} */
9
+ export interface ResolvedSequentialColorScale {
10
+ /** Authored finite endpoints, preserving ascending or descending order. */ readonly domain: readonly [
11
+ number,
12
+ number
13
+ ];
14
+ /** Canonical endpoint colors, in authored order. */ readonly colors: readonly [
15
+ string,
16
+ string
17
+ ];
18
+ /** Frozen endpoint/value pairs for scale-derived annotations. */ readonly stops: readonly ColorScaleStop[];
19
+ /** Maps finite data to a clamped color.
20
+ * @param value - Numeric input.
21
+ * @returns Canonical #rrggbb color. */ map(value: number): string;
22
+ }
23
+ /** Readonly continuous mapping with an explicit center. @see {@link DivergingColorScaleProps} */
24
+ export interface ResolvedDivergingColorScale {
25
+ /** Strictly monotonic finite endpoints and center, in authored order. */ readonly domain: readonly [
26
+ number,
27
+ number,
28
+ number
29
+ ];
30
+ /** Canonical endpoint and center colors. */ readonly colors: readonly [
31
+ string,
32
+ string,
33
+ string
34
+ ];
35
+ /** Frozen endpoint/center pairs for scale-derived annotations. */ readonly stops: readonly ColorScaleStop[];
36
+ /** Maps finite data through the authored center.
37
+ * @param value - Numeric input.
38
+ * @returns Canonical #rrggbb color. */ map(value: number): string;
39
+ }
40
+ /** Inputs for a dedicated sequential color provider. @see {@link ResolvedSequentialColorScale} */
41
+ export interface SequentialColorScaleProps {
42
+ /** Identity in the color-scale namespace. See {@link ScaleId}. */ readonly id: ScaleId;
43
+ /** Finite endpoints; equal endpoints map all finite inputs to the color midpoint. */ readonly domain: SignalValue<readonly [number, number]>;
44
+ /** Required #RRGGBB endpoint colors. No default palette is chosen. */ readonly colors: SignalValue<readonly [string, string]>;
45
+ /** Descendants consuming the mapping. See {@link PibblNode}. */ readonly children?: PibblNode;
46
+ }
47
+ /** Inputs for a dedicated diverging color provider. @see {@link ResolvedDivergingColorScale} */
48
+ export interface DivergingColorScaleProps {
49
+ /** Identity in the color-scale namespace. See {@link ScaleId}. */ readonly id: ScaleId;
50
+ /** Strictly increasing or decreasing finite endpoints and center. */ readonly domain: SignalValue<readonly [number, number, number]>;
51
+ /** Required #RRGGBB endpoint and center colors. */ readonly colors: SignalValue<readonly [string, string, string]>;
52
+ /** Descendants consuming the mapping. See {@link PibblNode}. */ readonly children?: PibblNode;
53
+ }
@@ -0,0 +1,49 @@
1
+ import type { LineSeriesProps } from "./types.js";
2
+ /** A mapped Cartesian coordinate used by private series curve rendering. */
3
+ export type SeriesCurvePoint = readonly [number, number];
4
+ /**
5
+ * A private generated segment. Cubic controls reserve the representation needed by a later
6
+ * smooth-curve implementation; current step definitions generate straight segments only.
7
+ */
8
+ export interface SeriesCurveSegment {
9
+ /** Endpoint of this segment. */
10
+ readonly end: SeriesCurvePoint;
11
+ /** First cubic Bézier control point when the segment is cubic. */
12
+ readonly control1?: SeriesCurvePoint;
13
+ /** Second cubic Bézier control point when the segment is cubic. */
14
+ readonly control2?: SeriesCurvePoint;
15
+ }
16
+ /** A private immutable path beginning at one point and continuing through generated segments. */
17
+ export interface SeriesCurveGeometry {
18
+ /** Initial coordinate for the geometry. */
19
+ readonly start: SeriesCurvePoint;
20
+ /** Ordered segments after {@link SeriesCurveGeometry.start}. */
21
+ readonly segments: readonly SeriesCurveSegment[];
22
+ }
23
+ declare const seriesCurveBrand: unique symbol;
24
+ /**
25
+ * An opaque immutable definition controlling how a series connects adjacent observations.
26
+ *
27
+ * Obtain a definition from one of the named curve factories. Definitions intentionally expose
28
+ * no algorithm selector or custom callback surface.
29
+ *
30
+ * @see {@link LineSeriesProps}
31
+ */
32
+ export interface SeriesCurve {
33
+ /** Nominal marker that prevents callers from forging a recognized definition. */
34
+ readonly [seriesCurveBrand]: true;
35
+ }
36
+ type SeriesCurveBuilder = (points: readonly SeriesCurvePoint[]) => readonly SeriesCurveSegment[];
37
+ /** @internal Creates one module-recognized immutable curve definition. */
38
+ export declare function createSeriesCurve(builder: SeriesCurveBuilder): SeriesCurve;
39
+ /** @internal Rejects values that were not created by a named curve factory. */
40
+ export declare function resolveSeriesCurve(value: unknown): SeriesCurve | undefined;
41
+ /** @internal Builds the curve geometry for one already-valid contiguous run. */
42
+ export declare function curveGeometry(curve: SeriesCurve | undefined, points: readonly SeriesCurvePoint[]): SeriesCurveGeometry;
43
+ /** @internal Appends one generated geometry in its authored forward direction. */
44
+ export declare function appendCurveForward(path: Path2D, geometry: SeriesCurveGeometry): void;
45
+ /** @internal Appends one generated geometry in reverse without rebuilding its curve strategy. */
46
+ export declare function appendCurveReverse(path: Path2D, geometry: SeriesCurveGeometry): void;
47
+ /** @internal Rejects interval-band cubics whose paired boundaries cross between observations. */
48
+ export declare function validatePairedCurveGeometry(upper: SeriesCurveGeometry, lower: SeriesCurveGeometry): void;
49
+ export {};
@@ -0,0 +1,148 @@
1
+ const builders = /* @__PURE__ */ new WeakMap();
2
+ function createSeriesCurve(builder) {
3
+ const definition = Object.freeze({});
4
+ builders.set(definition, builder);
5
+ return definition;
6
+ }
7
+ function resolveSeriesCurve(value) {
8
+ if (value === void 0 || value === "linear") return void 0;
9
+ if (typeof value !== "object" || value === null || !builders.has(value))
10
+ throw new TypeError(
11
+ 'Series curve must be "linear" or a definition from a named factory.'
12
+ );
13
+ return value;
14
+ }
15
+ function curveGeometry(curve, points) {
16
+ const start = points[0];
17
+ return Object.freeze({
18
+ start,
19
+ segments: Object.freeze(
20
+ curve ? [...builders.get(curve)(points)] : points.slice(1).map((end) => Object.freeze({ end }))
21
+ )
22
+ });
23
+ }
24
+ function appendCurveForward(path, geometry) {
25
+ for (const segment of geometry.segments) {
26
+ if (segment.control1 && segment.control2)
27
+ path.bezierCurveTo(
28
+ segment.control1[0],
29
+ segment.control1[1],
30
+ segment.control2[0],
31
+ segment.control2[1],
32
+ segment.end[0],
33
+ segment.end[1]
34
+ );
35
+ else path.lineTo(segment.end[0], segment.end[1]);
36
+ }
37
+ }
38
+ function appendCurveReverse(path, geometry) {
39
+ const ends = geometry.segments.map((segment) => segment.end);
40
+ path.lineTo(
41
+ (ends.at(-1) ?? geometry.start)[0],
42
+ (ends.at(-1) ?? geometry.start)[1]
43
+ );
44
+ for (let i = geometry.segments.length - 1; i >= 0; i--) {
45
+ const segment = geometry.segments[i];
46
+ const start = i === 0 ? geometry.start : geometry.segments[i - 1].end;
47
+ if (segment.control1 && segment.control2)
48
+ path.bezierCurveTo(
49
+ segment.control2[0],
50
+ segment.control2[1],
51
+ segment.control1[0],
52
+ segment.control1[1],
53
+ start[0],
54
+ start[1]
55
+ );
56
+ else path.lineTo(start[0], start[1]);
57
+ }
58
+ }
59
+ function cubicValue(values, t) {
60
+ const [p0, p1, p2, p3] = values;
61
+ const inverse = 1 - t;
62
+ return inverse ** 3 * p0 + 3 * inverse ** 2 * t * p1 + 3 * inverse * t ** 2 * p2 + t ** 3 * p3;
63
+ }
64
+ function derivativeRoots(values) {
65
+ const [p0, p1, p2, p3] = values;
66
+ const a = -p0 + 3 * p1 - 3 * p2 + p3;
67
+ const b = 3 * p0 - 6 * p1 + 3 * p2;
68
+ const c = -3 * p0 + 3 * p1;
69
+ if (a === 0) {
70
+ if (b === 0) return [];
71
+ return [-c / (2 * b)];
72
+ }
73
+ const discriminant = 4 * b * b - 12 * a * c;
74
+ if (discriminant < 0) return [];
75
+ const root = Math.sqrt(discriminant);
76
+ const q = -b - (b >= 0 ? root / 2 : -root / 2);
77
+ return q === 0 ? [-b / (3 * a)] : [q / (3 * a), c / q];
78
+ }
79
+ function cubicY(start, segment) {
80
+ const end = segment.end;
81
+ const control1 = segment.control1 ?? [
82
+ start[0] + (end[0] - start[0]) / 3,
83
+ start[1] + (end[1] - start[1]) / 3
84
+ ];
85
+ const control2 = segment.control2 ?? [
86
+ start[0] + (end[0] - start[0]) * 2 / 3,
87
+ start[1] + (end[1] - start[1]) * 2 / 3
88
+ ];
89
+ return [start[1], control1[1], control2[1], end[1]];
90
+ }
91
+ function validatePairedCurveGeometry(upper, lower) {
92
+ if (upper.segments.length !== lower.segments.length)
93
+ throw new RangeError(
94
+ "IntervalBandSeries curve boundaries have incompatible geometry."
95
+ );
96
+ let upperStart = upper.start;
97
+ let lowerStart = lower.start;
98
+ let orientation = 0;
99
+ for (let i = 0; i < upper.segments.length && orientation === 0; i++) {
100
+ for (const value of [
101
+ upperStart[1] - lowerStart[1],
102
+ upper.segments[i].end[1] - lower.segments[i].end[1]
103
+ ]) {
104
+ if (value !== 0) {
105
+ orientation = Math.sign(value);
106
+ break;
107
+ }
108
+ }
109
+ upperStart = upper.segments[i].end;
110
+ lowerStart = lower.segments[i].end;
111
+ }
112
+ upperStart = upper.start;
113
+ lowerStart = lower.start;
114
+ for (let i = 0; i < upper.segments.length; i++) {
115
+ const upperSegment = upper.segments[i], lowerSegment = lower.segments[i];
116
+ const upperY = cubicY(upperStart, upperSegment);
117
+ const lowerY = cubicY(lowerStart, lowerSegment);
118
+ const difference = upperY.map((value, index) => value - lowerY[index]);
119
+ if (!difference.every(Number.isFinite))
120
+ throw new RangeError(
121
+ "IntervalBandSeries curve boundaries must be finite."
122
+ );
123
+ const magnitude = Math.max(...difference.map(Math.abs));
124
+ const normalized = difference.map(
125
+ (value) => magnitude === 0 ? 0 : value / magnitude
126
+ );
127
+ const candidates = [0, 1, ...derivativeRoots(normalized)].filter(
128
+ (value) => value >= 0 && value <= 1
129
+ );
130
+ for (const t of candidates) {
131
+ const value = cubicValue(normalized, t);
132
+ if (!Number.isFinite(value) || // Relative tolerance accounts only for floating-point evaluation at tangencies.
133
+ orientation !== 0 && value * orientation < -64 * Number.EPSILON)
134
+ throw new RangeError("IntervalBandSeries curve boundaries cross.");
135
+ }
136
+ upperStart = upperSegment.end;
137
+ lowerStart = lowerSegment.end;
138
+ }
139
+ }
140
+ export {
141
+ appendCurveForward,
142
+ appendCurveReverse,
143
+ createSeriesCurve,
144
+ curveGeometry,
145
+ resolveSeriesCurve,
146
+ validatePairedCurveGeometry
147
+ };
148
+ //# sourceMappingURL=curve-definition.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/curve-definition.ts"],
4
+ "sourcesContent": ["import type { LineSeriesProps } from \"./types.js\";\n/** A mapped Cartesian coordinate used by private series curve rendering. */\nexport type SeriesCurvePoint = readonly [number, number];\n\n/**\n * A private generated segment. Cubic controls reserve the representation needed by a later\n * smooth-curve implementation; current step definitions generate straight segments only.\n */\nexport interface SeriesCurveSegment {\n /** Endpoint of this segment. */\n readonly end: SeriesCurvePoint;\n /** First cubic B\u00E9zier control point when the segment is cubic. */\n readonly control1?: SeriesCurvePoint;\n /** Second cubic B\u00E9zier control point when the segment is cubic. */\n readonly control2?: SeriesCurvePoint;\n}\n\n/** A private immutable path beginning at one point and continuing through generated segments. */\nexport interface SeriesCurveGeometry {\n /** Initial coordinate for the geometry. */\n readonly start: SeriesCurvePoint;\n /** Ordered segments after {@link SeriesCurveGeometry.start}. */\n readonly segments: readonly SeriesCurveSegment[];\n}\n\ndeclare const seriesCurveBrand: unique symbol;\n\n/**\n * An opaque immutable definition controlling how a series connects adjacent observations.\n *\n * Obtain a definition from one of the named curve factories. Definitions intentionally expose\n * no algorithm selector or custom callback surface.\n *\n * @see {@link LineSeriesProps}\n */\nexport interface SeriesCurve {\n /** Nominal marker that prevents callers from forging a recognized definition. */\n readonly [seriesCurveBrand]: true;\n}\n\ntype SeriesCurveBuilder = (\n points: readonly SeriesCurvePoint[],\n) => readonly SeriesCurveSegment[];\n\nconst builders = new WeakMap<SeriesCurve, SeriesCurveBuilder>();\n\n/** @internal Creates one module-recognized immutable curve definition. */\nexport function createSeriesCurve(builder: SeriesCurveBuilder): SeriesCurve {\n const definition = Object.freeze({}) as unknown as SeriesCurve;\n builders.set(definition, builder);\n return definition;\n}\n\n/** @internal Rejects values that were not created by a named curve factory. */\nexport function resolveSeriesCurve(value: unknown): SeriesCurve | undefined {\n if (value === undefined || value === \"linear\") return undefined;\n if (\n typeof value !== \"object\" ||\n value === null ||\n !builders.has(value as SeriesCurve)\n )\n throw new TypeError(\n 'Series curve must be \"linear\" or a definition from a named factory.',\n );\n return value as SeriesCurve;\n}\n\n/** @internal Builds the curve geometry for one already-valid contiguous run. */\nexport function curveGeometry(\n curve: SeriesCurve | undefined,\n points: readonly SeriesCurvePoint[],\n): SeriesCurveGeometry {\n const start = points[0];\n return Object.freeze({\n start,\n segments: Object.freeze(\n curve\n ? [...builders.get(curve)!(points)]\n : points.slice(1).map((end) => Object.freeze({ end })),\n ),\n });\n}\n\n/** @internal Appends one generated geometry in its authored forward direction. */\nexport function appendCurveForward(\n path: Path2D,\n geometry: SeriesCurveGeometry,\n): void {\n for (const segment of geometry.segments) {\n if (segment.control1 && segment.control2)\n path.bezierCurveTo(\n segment.control1[0],\n segment.control1[1],\n segment.control2[0],\n segment.control2[1],\n segment.end[0],\n segment.end[1],\n );\n else path.lineTo(segment.end[0], segment.end[1]);\n }\n}\n\n/** @internal Appends one generated geometry in reverse without rebuilding its curve strategy. */\nexport function appendCurveReverse(\n path: Path2D,\n geometry: SeriesCurveGeometry,\n): void {\n const ends = geometry.segments.map((segment) => segment.end);\n path.lineTo(\n (ends.at(-1) ?? geometry.start)[0],\n (ends.at(-1) ?? geometry.start)[1],\n );\n for (let i = geometry.segments.length - 1; i >= 0; i--) {\n const segment = geometry.segments[i];\n const start = i === 0 ? geometry.start : geometry.segments[i - 1].end;\n if (segment.control1 && segment.control2)\n path.bezierCurveTo(\n segment.control2[0],\n segment.control2[1],\n segment.control1[0],\n segment.control1[1],\n start[0],\n start[1],\n );\n else path.lineTo(start[0], start[1]);\n }\n}\n\nfunction cubicValue(\n values: readonly [number, number, number, number],\n t: number,\n): number {\n const [p0, p1, p2, p3] = values;\n const inverse = 1 - t;\n return (\n inverse ** 3 * p0 +\n 3 * inverse ** 2 * t * p1 +\n 3 * inverse * t ** 2 * p2 +\n t ** 3 * p3\n );\n}\n\nfunction derivativeRoots(\n values: readonly [number, number, number, number],\n): readonly number[] {\n const [p0, p1, p2, p3] = values;\n const a = -p0 + 3 * p1 - 3 * p2 + p3;\n const b = 3 * p0 - 6 * p1 + 3 * p2;\n const c = -3 * p0 + 3 * p1;\n if (a === 0) {\n if (b === 0) return [];\n return [-c / (2 * b)];\n }\n const discriminant = 4 * b * b - 12 * a * c;\n if (discriminant < 0) return [];\n const root = Math.sqrt(discriminant);\n const q = -b - (b >= 0 ? root / 2 : -root / 2);\n return q === 0 ? [-b / (3 * a)] : [q / (3 * a), c / q];\n}\n\nfunction cubicY(\n start: SeriesCurvePoint,\n segment: SeriesCurveSegment,\n): readonly [number, number, number, number] {\n const end = segment.end;\n const control1 = segment.control1 ?? [\n start[0] + (end[0] - start[0]) / 3,\n start[1] + (end[1] - start[1]) / 3,\n ];\n const control2 = segment.control2 ?? [\n start[0] + ((end[0] - start[0]) * 2) / 3,\n start[1] + ((end[1] - start[1]) * 2) / 3,\n ];\n return [start[1], control1[1], control2[1], end[1]];\n}\n\n/** @internal Rejects interval-band cubics whose paired boundaries cross between observations. */\nexport function validatePairedCurveGeometry(\n upper: SeriesCurveGeometry,\n lower: SeriesCurveGeometry,\n): void {\n if (upper.segments.length !== lower.segments.length)\n throw new RangeError(\n \"IntervalBandSeries curve boundaries have incompatible geometry.\",\n );\n let upperStart = upper.start;\n let lowerStart = lower.start;\n let orientation = 0;\n for (let i = 0; i < upper.segments.length && orientation === 0; i++) {\n for (const value of [\n upperStart[1] - lowerStart[1],\n upper.segments[i].end[1] - lower.segments[i].end[1],\n ]) {\n if (value !== 0) {\n orientation = Math.sign(value);\n break;\n }\n }\n upperStart = upper.segments[i].end;\n lowerStart = lower.segments[i].end;\n }\n upperStart = upper.start;\n lowerStart = lower.start;\n for (let i = 0; i < upper.segments.length; i++) {\n const upperSegment = upper.segments[i],\n lowerSegment = lower.segments[i];\n const upperY = cubicY(upperStart, upperSegment);\n const lowerY = cubicY(lowerStart, lowerSegment);\n const difference = upperY.map((value, index) => value - lowerY[index]) as [\n number,\n number,\n number,\n number,\n ];\n if (!difference.every(Number.isFinite))\n throw new RangeError(\n \"IntervalBandSeries curve boundaries must be finite.\",\n );\n const magnitude = Math.max(...difference.map(Math.abs));\n const normalized = difference.map((value) =>\n magnitude === 0 ? 0 : value / magnitude,\n ) as [number, number, number, number];\n const candidates = [0, 1, ...derivativeRoots(normalized)].filter(\n (value) => value >= 0 && value <= 1,\n );\n for (const t of candidates) {\n const value = cubicValue(normalized, t);\n if (\n !Number.isFinite(value) ||\n // Relative tolerance accounts only for floating-point evaluation at tangencies.\n (orientation !== 0 && value * orientation < -64 * Number.EPSILON)\n )\n throw new RangeError(\"IntervalBandSeries curve boundaries cross.\");\n }\n upperStart = upperSegment.end;\n lowerStart = lowerSegment.end;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ import { type Signal } from "@pibbl/core";
2
+ import type { DivergingColorScaleProps, ResolvedDivergingColorScale } from "./color-types.js";
3
+ import type { ScaleId } from "./types.js";
4
+ /** Provides an allocation-independent color mapping with an authored center.
5
+ * @param props - Explicit domain, colors, identity, and children. See {@link DivergingColorScaleProps}.
6
+ * @returns Descendant content. */
7
+ export declare function DivergingColorScale(props: DivergingColorScaleProps): import("@pibbl/core").PibblNode;
8
+ /** Reads the dedicated ancestor diverging mapping.
9
+ * @param id - Color-scale identity. See {@link ScaleId}.
10
+ * @returns Shared readonly mapping signal. See {@link ResolvedDivergingColorScale}. */
11
+ export declare function useDivergingColorScale(id: ScaleId): Signal<ResolvedDivergingColorScale>;
@@ -0,0 +1,51 @@
1
+ import { resolveSignalValue } from "@pibbl/core";
2
+ import { provideColor, useColor } from "./color-context.js";
3
+ import {
4
+ colorMix,
5
+ colorPosition,
6
+ finiteColorValue,
7
+ hexColor
8
+ } from "./color-math.js";
9
+ function resolve(props) {
10
+ const input = resolveSignalValue(props.domain), paint = resolveSignalValue(props.colors);
11
+ if (!Array.isArray(input) || input.length !== 3 || !Array.isArray(paint) || paint.length !== 3)
12
+ throw new RangeError(
13
+ "Diverging color scales require three domain values and three colors."
14
+ );
15
+ const domain = Object.freeze(
16
+ Array.from(input, finiteColorValue)
17
+ ), colors = Object.freeze(Array.from(paint, hexColor));
18
+ const [a, m, b] = domain;
19
+ if (!(a < m && m < b || a > m && m > b))
20
+ throw new RangeError(
21
+ "Diverging color domain must be strictly monotonic around its center."
22
+ );
23
+ const stops = Object.freeze(
24
+ domain.map((value, i) => Object.freeze({ value, color: colors[i] }))
25
+ );
26
+ return Object.freeze({
27
+ domain,
28
+ colors,
29
+ stops,
30
+ map(value) {
31
+ finiteColorValue(value);
32
+ if (value === m) return colors[1];
33
+ return (a < m ? value < m : value > m) ? colorMix(colors[0], colors[1], colorPosition(value, a, m)) : colorMix(colors[1], colors[2], colorPosition(value, m, b));
34
+ }
35
+ });
36
+ }
37
+ function DivergingColorScale(props) {
38
+ provideColor(props.id, "diverging", () => resolve(props), [
39
+ props.domain,
40
+ props.colors
41
+ ]);
42
+ return props.children;
43
+ }
44
+ function useDivergingColorScale(id) {
45
+ return useColor(id, "diverging");
46
+ }
47
+ export {
48
+ DivergingColorScale,
49
+ useDivergingColorScale
50
+ };
51
+ //# sourceMappingURL=diverging-color-scale.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/diverging-color-scale.ts"],
4
+ "sourcesContent": ["import { resolveSignalValue, type Signal } from \"@pibbl/core\";\nimport type {\n DivergingColorScaleProps,\n ResolvedDivergingColorScale,\n} from \"./color-types.js\";\nimport type { ScaleId } from \"./types.js\";\nimport { provideColor, useColor } from \"./color-context.js\";\nimport {\n colorMix,\n colorPosition,\n finiteColorValue,\n hexColor,\n} from \"./color-math.js\";\nfunction resolve(props: DivergingColorScaleProps): ResolvedDivergingColorScale {\n const input = resolveSignalValue(props.domain),\n paint = resolveSignalValue(props.colors);\n if (\n !Array.isArray(input) ||\n input.length !== 3 ||\n !Array.isArray(paint) ||\n paint.length !== 3\n )\n throw new RangeError(\n \"Diverging color scales require three domain values and three colors.\",\n );\n const domain = Object.freeze(\n Array.from(input, finiteColorValue),\n ) as readonly [number, number, number],\n colors = Object.freeze(Array.from(paint, hexColor)) as readonly [\n string,\n string,\n string,\n ];\n const [a, m, b] = domain;\n if (!((a < m && m < b) || (a > m && m > b)))\n throw new RangeError(\n \"Diverging color domain must be strictly monotonic around its center.\",\n );\n const stops = Object.freeze(\n domain.map((value, i) => Object.freeze({ value, color: colors[i] })),\n );\n return Object.freeze({\n domain,\n colors,\n stops,\n map(value: number) {\n finiteColorValue(value);\n if (value === m) return colors[1];\n return (a < m ? value < m : value > m)\n ? colorMix(colors[0], colors[1], colorPosition(value, a, m))\n : colorMix(colors[1], colors[2], colorPosition(value, m, b));\n },\n });\n}\n/** Provides an allocation-independent color mapping with an authored center.\n * @param props - Explicit domain, colors, identity, and children. See {@link DivergingColorScaleProps}.\n * @returns Descendant content. */\nexport function DivergingColorScale(props: DivergingColorScaleProps) {\n provideColor(props.id, \"diverging\", () => resolve(props), [\n props.domain,\n props.colors,\n ]);\n return props.children;\n}\n/** Reads the dedicated ancestor diverging mapping.\n * @param id - Color-scale identity. See {@link ScaleId}.\n * @returns Shared readonly mapping signal. See {@link ResolvedDivergingColorScale}. */\nexport function useDivergingColorScale(\n id: ScaleId,\n): Signal<ResolvedDivergingColorScale> {\n return useColor(id, \"diverging\");\n}\n"],
5
+ "mappings": "AAAA,SAAS,0BAAuC;AAMhD,SAAS,cAAc,gBAAgB;AACvC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,QAAQ,OAA8D;AAC7E,QAAM,QAAQ,mBAAmB,MAAM,MAAM,GAC3C,QAAQ,mBAAmB,MAAM,MAAM;AACzC,MACE,CAAC,MAAM,QAAQ,KAAK,KACpB,MAAM,WAAW,KACjB,CAAC,MAAM,QAAQ,KAAK,KACpB,MAAM,WAAW;AAEjB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,QAAM,SAAS,OAAO;AAAA,IAClB,MAAM,KAAK,OAAO,gBAAgB;AAAA,EACpC,GACA,SAAS,OAAO,OAAO,MAAM,KAAK,OAAO,QAAQ,CAAC;AAKpD,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI;AAClB,MAAI,EAAG,IAAI,KAAK,IAAI,KAAO,IAAI,KAAK,IAAI;AACtC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,QAAM,QAAQ,OAAO;AAAA,IACnB,OAAO,IAAI,CAAC,OAAO,MAAM,OAAO,OAAO,EAAE,OAAO,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;AAAA,EACrE;AACA,SAAO,OAAO,OAAO;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI,OAAe;AACjB,uBAAiB,KAAK;AACtB,UAAI,UAAU,EAAG,QAAO,OAAO,CAAC;AAChC,cAAQ,IAAI,IAAI,QAAQ,IAAI,QAAQ,KAChC,SAAS,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,cAAc,OAAO,GAAG,CAAC,CAAC,IACzD,SAAS,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,cAAc,OAAO,GAAG,CAAC,CAAC;AAAA,IAC/D;AAAA,EACF,CAAC;AACH;AAIO,SAAS,oBAAoB,OAAiC;AACnE,eAAa,MAAM,IAAI,aAAa,MAAM,QAAQ,KAAK,GAAG;AAAA,IACxD,MAAM;AAAA,IACN,MAAM;AAAA,EACR,CAAC;AACD,SAAO,MAAM;AACf;AAIO,SAAS,uBACd,IACqC;AACrC,SAAO,SAAS,IAAI,WAAW;AACjC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,40 @@
1
+ import type { LinearDomain, ResolvedContinuousScale } from "./types.js";
2
+ /** Explicit hard bounds and minimum mapped extent for continuous-domain navigation. @see {@link panDomain} @see {@link zoomDomain} */
3
+ export interface DomainNavigationConstraints {
4
+ /** Finite hard domain endpoints, in either order, valid for the supplied scale. See {@link LinearDomain}. */
5
+ readonly bounds: LinearDomain;
6
+ /** Minimum span as a fraction of the mapped hard bounds, greater than zero through one. Defaults to 0.01. */
7
+ readonly minimumSpanRatio?: number;
8
+ }
9
+ /** Named pan settings with explicit navigation limits. @see {@link panDomain} */
10
+ export interface PanDomainOptions extends DomainNavigationConstraints {
11
+ /** Finite displacement in range units; positive shifts mapped values toward increasing range coordinates. */
12
+ readonly rangeDelta: number;
13
+ }
14
+ /** Named zoom settings with explicit navigation limits. @see {@link zoomDomain} */
15
+ export interface ZoomDomainOptions extends DomainNavigationConstraints {
16
+ /** Finite anchor in the scale's range coordinates, using the same units as its range. */
17
+ readonly rangeAnchor: number;
18
+ /** Finite positive magnification; greater than one zooms in. */
19
+ readonly factor: number;
20
+ }
21
+ /**
22
+ * Moves the visible continuous domain by a displacement expressed in range units.
23
+ * Positive displacement shifts mapped values toward increasing range coordinates; the returned domain moves oppositely.
24
+ * @param scale - Current resolved continuous mapping. See {@link ResolvedContinuousScale}.
25
+ * @param options - Displacement, bounds, and minimum span. See {@link PanDomainOptions}.
26
+ * @returns A new immutable domain pair. See {@link LinearDomain}.
27
+ * @throws When inputs, bounds, or the resulting extent are invalid or collapsed.
28
+ * @see {@link zoomDomain}
29
+ */
30
+ export declare function panDomain(scale: ResolvedContinuousScale, options: PanDomainOptions): LinearDomain;
31
+ /**
32
+ * Magnifies a continuous domain around an anchor in range coordinates.
33
+ * Factor greater than one zooms in; hard bounds and minimum span may limit anchor preservation.
34
+ * @param scale - Current resolved continuous mapping. See {@link ResolvedContinuousScale}.
35
+ * @param options - Anchor, magnification, bounds, and minimum span. See {@link ZoomDomainOptions}.
36
+ * @returns A new immutable domain pair. See {@link LinearDomain}.
37
+ * @throws When factor, mapping, bounds, or the resulting extent are invalid or collapsed.
38
+ * @see {@link panDomain}
39
+ */
40
+ export declare function zoomDomain(scale: ResolvedContinuousScale, options: ZoomDomainOptions): LinearDomain;
@@ -0,0 +1,77 @@
1
+ function finite(value, name) {
2
+ if (typeof value !== "number" || !Number.isFinite(value))
3
+ throw new RangeError(`${name} must be finite.`);
4
+ return value;
5
+ }
6
+ function navigate(scale, start, end, constraints, requestedSpan) {
7
+ const [r0, r1] = scale.range;
8
+ if (r0 === r1 || scale.domain[0] === scale.domain[1])
9
+ throw new RangeError(
10
+ "Domain navigation requires noncollapsed domain and range."
11
+ );
12
+ const { bounds, minimumSpanRatio = 0.01 } = constraints;
13
+ if (!Array.isArray(bounds) || bounds.length !== 2)
14
+ throw new RangeError("Navigation bounds require two endpoints.");
15
+ if (scale.type === "utc" && !bounds.every(Number.isSafeInteger))
16
+ throw new RangeError(
17
+ "UTC navigation bounds must be safe integer milliseconds."
18
+ );
19
+ const b0 = scale.map(finite(bounds[0], "Lower bound")), b1 = scale.map(finite(bounds[1], "Upper bound"));
20
+ const lo = Math.min(b0, b1), hi = Math.max(b0, b1), extent = hi - lo;
21
+ if (!Number.isFinite(extent) || extent <= 0)
22
+ throw new RangeError(
23
+ "Navigation bounds must have a finite nonzero mapped extent."
24
+ );
25
+ if (!Number.isFinite(minimumSpanRatio) || minimumSpanRatio <= 0 || minimumSpanRatio > 1)
26
+ throw new RangeError(
27
+ "minimumSpanRatio must be greater than zero and at most one."
28
+ );
29
+ finite(start, "Mapped start");
30
+ finite(end, "Mapped end");
31
+ const requested = requestedSpan ?? Math.abs(end - start);
32
+ if (!Number.isFinite(requested))
33
+ throw new RangeError("Navigation span must be finite.");
34
+ const span = Math.min(extent, Math.max(extent * minimumSpanRatio, requested));
35
+ const center = start / 2 + end / 2;
36
+ const low = Math.max(lo, Math.min(hi - span, center - span / 2)), high = low + span;
37
+ let a = scale.invert(r0 < r1 ? low : high), b = scale.invert(r0 < r1 ? high : low);
38
+ if (scale.type === "utc") {
39
+ a = Math.round(a);
40
+ b = Math.round(b);
41
+ }
42
+ finite(a, "Domain start");
43
+ finite(b, "Domain end");
44
+ if (a === b)
45
+ throw new RangeError(
46
+ "Navigation result collapses at the scale's numeric precision."
47
+ );
48
+ return Object.freeze([a, b]);
49
+ }
50
+ function panDomain(scale, options) {
51
+ const { rangeDelta } = options;
52
+ finite(rangeDelta, "Pan displacement");
53
+ return navigate(
54
+ scale,
55
+ scale.range[0] - rangeDelta,
56
+ scale.range[1] - rangeDelta,
57
+ options,
58
+ Math.abs(scale.range[1] - scale.range[0])
59
+ );
60
+ }
61
+ function zoomDomain(scale, options) {
62
+ const { rangeAnchor, factor } = options;
63
+ finite(rangeAnchor, "Zoom anchor");
64
+ finite(factor, "Zoom factor");
65
+ if (factor <= 0) throw new RangeError("Zoom factor must be positive.");
66
+ return navigate(
67
+ scale,
68
+ rangeAnchor + (scale.range[0] - rangeAnchor) / factor,
69
+ rangeAnchor + (scale.range[1] - rangeAnchor) / factor,
70
+ options
71
+ );
72
+ }
73
+ export {
74
+ panDomain,
75
+ zoomDomain
76
+ };
77
+ //# sourceMappingURL=domain-navigation.js.map