graphein 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/dist/animation/animate.d.ts +6 -1
  2. package/dist/animation/animate.d.ts.map +1 -1
  3. package/dist/animation/animate.js +2 -2
  4. package/dist/animation/animate.js.map +2 -2
  5. package/dist/animation/env.d.ts +5 -0
  6. package/dist/animation/env.d.ts.map +1 -1
  7. package/dist/animation/env.js +4 -0
  8. package/dist/animation/env.js.map +2 -2
  9. package/dist/animation/index.d.ts +1 -0
  10. package/dist/animation/index.d.ts.map +1 -1
  11. package/dist/animation/index.js +1 -0
  12. package/dist/animation/index.js.map +2 -2
  13. package/dist/animation/stagger.d.ts +13 -0
  14. package/dist/animation/stagger.d.ts.map +1 -0
  15. package/dist/animation/stagger.js +13 -0
  16. package/dist/animation/stagger.js.map +7 -0
  17. package/dist/axes/draw.d.ts +5 -1
  18. package/dist/axes/draw.d.ts.map +1 -1
  19. package/dist/axes/draw.js +13 -1
  20. package/dist/axes/draw.js.map +2 -2
  21. package/dist/axes/morph.d.ts +111 -0
  22. package/dist/axes/morph.d.ts.map +1 -0
  23. package/dist/axes/morph.js +207 -0
  24. package/dist/axes/morph.js.map +7 -0
  25. package/dist/axes/overlay.d.ts.map +1 -1
  26. package/dist/axes/overlay.js +88 -25
  27. package/dist/axes/overlay.js.map +2 -2
  28. package/dist/axes/text.d.ts +2 -0
  29. package/dist/axes/text.d.ts.map +1 -1
  30. package/dist/axes/text.js +1 -0
  31. package/dist/axes/text.js.map +2 -2
  32. package/dist/axes/tickLabels.d.ts +2 -0
  33. package/dist/axes/tickLabels.d.ts.map +1 -1
  34. package/dist/axes/tickLabels.js +2 -2
  35. package/dist/axes/tickLabels.js.map +2 -2
  36. package/dist/charts/annotations.d.ts +9 -3
  37. package/dist/charts/annotations.d.ts.map +1 -1
  38. package/dist/charts/annotations.js +82 -27
  39. package/dist/charts/annotations.js.map +2 -2
  40. package/dist/charts/area.d.ts +37 -1
  41. package/dist/charts/area.d.ts.map +1 -1
  42. package/dist/charts/area.js +35 -17
  43. package/dist/charts/area.js.map +2 -2
  44. package/dist/charts/bar.d.ts +53 -0
  45. package/dist/charts/bar.d.ts.map +1 -1
  46. package/dist/charts/bar.js +117 -83
  47. package/dist/charts/bar.js.map +2 -2
  48. package/dist/charts/box.d.ts +31 -0
  49. package/dist/charts/box.d.ts.map +1 -1
  50. package/dist/charts/box.js +93 -70
  51. package/dist/charts/box.js.map +2 -2
  52. package/dist/charts/bubbleMap.d.ts +20 -0
  53. package/dist/charts/bubbleMap.d.ts.map +1 -0
  54. package/dist/charts/bubbleMap.js +951 -0
  55. package/dist/charts/bubbleMap.js.map +7 -0
  56. package/dist/charts/bullet.d.ts.map +1 -1
  57. package/dist/charts/bullet.js +69 -51
  58. package/dist/charts/bullet.js.map +2 -2
  59. package/dist/charts/calendarHeatmap.d.ts.map +1 -1
  60. package/dist/charts/calendarHeatmap.js +56 -19
  61. package/dist/charts/calendarHeatmap.js.map +2 -2
  62. package/dist/charts/candlestick.d.ts +40 -0
  63. package/dist/charts/candlestick.d.ts.map +1 -0
  64. package/dist/charts/candlestick.js +325 -0
  65. package/dist/charts/candlestick.js.map +7 -0
  66. package/dist/charts/choropleth.d.ts.map +1 -1
  67. package/dist/charts/choropleth.js +46 -67
  68. package/dist/charts/choropleth.js.map +2 -2
  69. package/dist/charts/combo.d.ts.map +1 -1
  70. package/dist/charts/combo.js +127 -27
  71. package/dist/charts/combo.js.map +3 -3
  72. package/dist/charts/dumbbell.d.ts.map +1 -1
  73. package/dist/charts/dumbbell.js +100 -31
  74. package/dist/charts/dumbbell.js.map +2 -2
  75. package/dist/charts/funnel.d.ts.map +1 -1
  76. package/dist/charts/funnel.js +93 -28
  77. package/dist/charts/funnel.js.map +3 -3
  78. package/dist/charts/gantt.d.ts +22 -0
  79. package/dist/charts/gantt.d.ts.map +1 -0
  80. package/dist/charts/gantt.js +564 -0
  81. package/dist/charts/gantt.js.map +7 -0
  82. package/dist/charts/gauge.d.ts.map +1 -1
  83. package/dist/charts/gauge.js +30 -4
  84. package/dist/charts/gauge.js.map +2 -2
  85. package/dist/charts/geo.d.ts +87 -0
  86. package/dist/charts/geo.d.ts.map +1 -0
  87. package/dist/charts/geo.js +140 -0
  88. package/dist/charts/geo.js.map +7 -0
  89. package/dist/charts/geometry.d.ts +20 -0
  90. package/dist/charts/geometry.d.ts.map +1 -0
  91. package/dist/charts/geometry.js +25 -0
  92. package/dist/charts/geometry.js.map +7 -0
  93. package/dist/charts/heatmap.d.ts.map +1 -1
  94. package/dist/charts/heatmap.js +58 -49
  95. package/dist/charts/heatmap.js.map +2 -2
  96. package/dist/charts/histogram.d.ts +1 -1
  97. package/dist/charts/histogram.d.ts.map +1 -1
  98. package/dist/charts/histogram.js +49 -31
  99. package/dist/charts/histogram.js.map +2 -2
  100. package/dist/charts/index.d.ts +35 -1
  101. package/dist/charts/index.d.ts.map +1 -1
  102. package/dist/charts/index.js +12 -0
  103. package/dist/charts/index.js.map +2 -2
  104. package/dist/charts/legibility.d.ts +38 -0
  105. package/dist/charts/legibility.d.ts.map +1 -0
  106. package/dist/charts/legibility.js +72 -0
  107. package/dist/charts/legibility.js.map +7 -0
  108. package/dist/charts/line.d.ts +39 -1
  109. package/dist/charts/line.d.ts.map +1 -1
  110. package/dist/charts/line.js +48 -16
  111. package/dist/charts/line.js.map +2 -2
  112. package/dist/charts/matrix.d.ts +2 -1
  113. package/dist/charts/matrix.d.ts.map +1 -1
  114. package/dist/charts/matrix.js +481 -319
  115. package/dist/charts/matrix.js.map +3 -3
  116. package/dist/charts/morphFrame.d.ts +83 -0
  117. package/dist/charts/morphFrame.d.ts.map +1 -0
  118. package/dist/charts/morphFrame.js +128 -0
  119. package/dist/charts/morphFrame.js.map +7 -0
  120. package/dist/charts/pie.d.ts.map +1 -1
  121. package/dist/charts/pie.js +89 -26
  122. package/dist/charts/pie.js.map +2 -2
  123. package/dist/charts/pieState.d.ts +27 -0
  124. package/dist/charts/pieState.d.ts.map +1 -0
  125. package/dist/charts/pieState.js +55 -0
  126. package/dist/charts/pieState.js.map +7 -0
  127. package/dist/charts/radar.d.ts +62 -0
  128. package/dist/charts/radar.d.ts.map +1 -0
  129. package/dist/charts/radar.js +912 -0
  130. package/dist/charts/radar.js.map +7 -0
  131. package/dist/charts/radialBar.d.ts +60 -0
  132. package/dist/charts/radialBar.d.ts.map +1 -0
  133. package/dist/charts/radialBar.js +708 -0
  134. package/dist/charts/radialBar.js.map +7 -0
  135. package/dist/charts/sankey.d.ts.map +1 -1
  136. package/dist/charts/sankey.js +223 -57
  137. package/dist/charts/sankey.js.map +3 -3
  138. package/dist/charts/scatter.d.ts +31 -0
  139. package/dist/charts/scatter.d.ts.map +1 -1
  140. package/dist/charts/scatter.js +48 -12
  141. package/dist/charts/scatter.js.map +2 -2
  142. package/dist/charts/slope.d.ts.map +1 -1
  143. package/dist/charts/slope.js +55 -3
  144. package/dist/charts/slope.js.map +2 -2
  145. package/dist/charts/sunburst.d.ts +14 -0
  146. package/dist/charts/sunburst.d.ts.map +1 -0
  147. package/dist/charts/sunburst.js +885 -0
  148. package/dist/charts/sunburst.js.map +7 -0
  149. package/dist/charts/table.d.ts +2 -1
  150. package/dist/charts/table.d.ts.map +1 -1
  151. package/dist/charts/table.js +214 -224
  152. package/dist/charts/table.js.map +3 -3
  153. package/dist/charts/tableView/canvas.d.ts +16 -1
  154. package/dist/charts/tableView/canvas.d.ts.map +1 -1
  155. package/dist/charts/tableView/canvas.js +361 -252
  156. package/dist/charts/tableView/canvas.js.map +3 -3
  157. package/dist/charts/tableView/conditional.d.ts +66 -40
  158. package/dist/charts/tableView/conditional.d.ts.map +1 -1
  159. package/dist/charts/tableView/conditional.js +163 -256
  160. package/dist/charts/tableView/conditional.js.map +3 -3
  161. package/dist/charts/tableView/dom.d.ts +26 -2
  162. package/dist/charts/tableView/dom.d.ts.map +1 -1
  163. package/dist/charts/tableView/dom.js +609 -269
  164. package/dist/charts/tableView/dom.js.map +3 -3
  165. package/dist/charts/tableView/layout.d.ts +22 -0
  166. package/dist/charts/tableView/layout.d.ts.map +1 -0
  167. package/dist/charts/tableView/layout.js +246 -0
  168. package/dist/charts/tableView/layout.js.map +7 -0
  169. package/dist/charts/tableView/sketch.d.ts +3 -2
  170. package/dist/charts/tableView/sketch.d.ts.map +1 -1
  171. package/dist/charts/tableView/sketch.js +2 -2
  172. package/dist/charts/tableView/sketch.js.map +2 -2
  173. package/dist/charts/tableView/sketchBar.d.ts +7 -0
  174. package/dist/charts/tableView/sketchBar.d.ts.map +1 -0
  175. package/dist/charts/tableView/sketchBar.js +32 -0
  176. package/dist/charts/tableView/sketchBar.js.map +7 -0
  177. package/dist/charts/tableView/sort.d.ts +9 -0
  178. package/dist/charts/tableView/sort.d.ts.map +1 -0
  179. package/dist/charts/tableView/sort.js +70 -0
  180. package/dist/charts/tableView/sort.js.map +7 -0
  181. package/dist/charts/tableView/sparkline.d.ts +30 -0
  182. package/dist/charts/tableView/sparkline.d.ts.map +1 -0
  183. package/dist/charts/tableView/sparkline.js +63 -0
  184. package/dist/charts/tableView/sparkline.js.map +7 -0
  185. package/dist/charts/tableView/style.d.ts +67 -0
  186. package/dist/charts/tableView/style.d.ts.map +1 -0
  187. package/dist/charts/tableView/style.js +131 -0
  188. package/dist/charts/tableView/style.js.map +7 -0
  189. package/dist/charts/tableView/types.d.ts +69 -46
  190. package/dist/charts/tableView/types.d.ts.map +1 -1
  191. package/dist/charts/tableView/types.js +22 -87
  192. package/dist/charts/tableView/types.js.map +2 -2
  193. package/dist/charts/tableView.d.ts +10 -5
  194. package/dist/charts/tableView.d.ts.map +1 -1
  195. package/dist/charts/tableView.js +12 -8
  196. package/dist/charts/tableView.js.map +2 -2
  197. package/dist/charts/treemap.d.ts.map +1 -1
  198. package/dist/charts/treemap.js +177 -68
  199. package/dist/charts/treemap.js.map +3 -3
  200. package/dist/charts/trendline.d.ts +13 -5
  201. package/dist/charts/trendline.d.ts.map +1 -1
  202. package/dist/charts/trendline.js +205 -56
  203. package/dist/charts/trendline.js.map +2 -2
  204. package/dist/charts/waterfall.d.ts.map +1 -1
  205. package/dist/charts/waterfall.js +76 -5
  206. package/dist/charts/waterfall.js.map +2 -2
  207. package/dist/index.d.ts +1 -1
  208. package/dist/index.js +1 -1
  209. package/dist/index.js.map +1 -1
  210. package/dist/interaction/cartesian.d.ts +4 -1
  211. package/dist/interaction/cartesian.d.ts.map +1 -1
  212. package/dist/interaction/cartesian.js +104 -34
  213. package/dist/interaction/cartesian.js.map +2 -2
  214. package/dist/interaction/controller.d.ts +29 -1
  215. package/dist/interaction/controller.d.ts.map +1 -1
  216. package/dist/interaction/controller.js +131 -8
  217. package/dist/interaction/controller.js.map +2 -2
  218. package/dist/interaction/focus.d.ts +23 -0
  219. package/dist/interaction/focus.d.ts.map +1 -0
  220. package/dist/interaction/focus.js +65 -0
  221. package/dist/interaction/focus.js.map +7 -0
  222. package/dist/interaction/tooltip.d.ts +6 -0
  223. package/dist/interaction/tooltip.d.ts.map +1 -1
  224. package/dist/interaction/tooltip.js +41 -16
  225. package/dist/interaction/tooltip.js.map +2 -2
  226. package/dist/interaction/types.d.ts +19 -0
  227. package/dist/interaction/types.d.ts.map +1 -1
  228. package/dist/interaction/veil.d.ts +25 -0
  229. package/dist/interaction/veil.d.ts.map +1 -0
  230. package/dist/interaction/veil.js +35 -0
  231. package/dist/interaction/veil.js.map +7 -0
  232. package/dist/pivot/pivot.d.ts +18 -0
  233. package/dist/pivot/pivot.d.ts.map +1 -1
  234. package/dist/pivot/pivot.js +46 -34
  235. package/dist/pivot/pivot.js.map +2 -2
  236. package/dist/render/chromeMotion.d.ts +65 -0
  237. package/dist/render/chromeMotion.d.ts.map +1 -0
  238. package/dist/render/chromeMotion.js +79 -0
  239. package/dist/render/chromeMotion.js.map +7 -0
  240. package/dist/render/pathSample.d.ts +24 -0
  241. package/dist/render/pathSample.d.ts.map +1 -0
  242. package/dist/render/pathSample.js +76 -0
  243. package/dist/render/pathSample.js.map +7 -0
  244. package/dist/render/transient.d.ts +18 -0
  245. package/dist/render/transient.d.ts.map +1 -0
  246. package/dist/render/transient.js +19 -0
  247. package/dist/render/transient.js.map +7 -0
  248. package/dist/runtime/candlestick.d.ts +112 -0
  249. package/dist/runtime/candlestick.d.ts.map +1 -0
  250. package/dist/runtime/candlestick.js +531 -0
  251. package/dist/runtime/candlestick.js.map +7 -0
  252. package/dist/runtime/cartesian.d.ts +14 -3
  253. package/dist/runtime/cartesian.d.ts.map +1 -1
  254. package/dist/runtime/cartesian.js.map +2 -2
  255. package/dist/runtime/chartAnimation.d.ts +54 -7
  256. package/dist/runtime/chartAnimation.d.ts.map +1 -1
  257. package/dist/runtime/chartAnimation.js +146 -28
  258. package/dist/runtime/chartAnimation.js.map +2 -2
  259. package/dist/runtime/chartRuntime.d.ts +42 -0
  260. package/dist/runtime/chartRuntime.d.ts.map +1 -1
  261. package/dist/runtime/chartRuntime.js +196 -30
  262. package/dist/runtime/chartRuntime.js.map +2 -2
  263. package/dist/runtime/dashboardDom.d.ts.map +1 -1
  264. package/dist/runtime/dashboardDom.js +45 -0
  265. package/dist/runtime/dashboardDom.js.map +2 -2
  266. package/dist/runtime/facet.d.ts +1 -1
  267. package/dist/runtime/facet.d.ts.map +1 -1
  268. package/dist/runtime/gantt.d.ts +137 -0
  269. package/dist/runtime/gantt.d.ts.map +1 -0
  270. package/dist/runtime/gantt.js +647 -0
  271. package/dist/runtime/gantt.js.map +7 -0
  272. package/dist/runtime/morph.d.ts +33 -0
  273. package/dist/runtime/morph.d.ts.map +1 -0
  274. package/dist/runtime/morph.js +332 -0
  275. package/dist/runtime/morph.js.map +7 -0
  276. package/dist/runtime/radar.d.ts +75 -0
  277. package/dist/runtime/radar.d.ts.map +1 -0
  278. package/dist/runtime/radar.js +201 -0
  279. package/dist/runtime/radar.js.map +7 -0
  280. package/dist/runtime/radialBar.d.ts +81 -0
  281. package/dist/runtime/radialBar.d.ts.map +1 -0
  282. package/dist/runtime/radialBar.js +125 -0
  283. package/dist/runtime/radialBar.js.map +7 -0
  284. package/dist/runtime/report/constants.d.ts +2 -2
  285. package/dist/runtime/report/constants.d.ts.map +1 -1
  286. package/dist/runtime/runtimeShared.d.ts +3 -3
  287. package/dist/runtime/runtimeShared.d.ts.map +1 -1
  288. package/dist/runtime/sunburst.d.ts +74 -0
  289. package/dist/runtime/sunburst.d.ts.map +1 -0
  290. package/dist/runtime/sunburst.js +150 -0
  291. package/dist/runtime/sunburst.js.map +7 -0
  292. package/dist/runtime/wire.d.ts.map +1 -1
  293. package/dist/runtime/wire.js +3 -1
  294. package/dist/runtime/wire.js.map +2 -2
  295. package/dist/shape/arc.d.ts +15 -2
  296. package/dist/shape/arc.d.ts.map +1 -1
  297. package/dist/shape/arc.js +204 -32
  298. package/dist/shape/arc.js.map +2 -2
  299. package/dist/spec/chartDefinitions.d.ts +6 -0
  300. package/dist/spec/chartDefinitions.d.ts.map +1 -1
  301. package/dist/spec/chartDefinitions.js +7 -1
  302. package/dist/spec/chartDefinitions.js.map +2 -2
  303. package/dist/spec/templates.d.ts.map +1 -1
  304. package/dist/spec/templates.js +177 -2
  305. package/dist/spec/templates.js.map +2 -2
  306. package/dist/spec/types.d.ts +258 -6
  307. package/dist/spec/types.d.ts.map +1 -1
  308. package/dist/spec/types.js +6 -0
  309. package/dist/spec/types.js.map +2 -2
  310. package/dist/spec/validate/charts.js +147 -15
  311. package/dist/spec/validate/charts.js.map +2 -2
  312. package/dist/spec/validate/common.d.ts +6 -0
  313. package/dist/spec/validate/common.d.ts.map +1 -1
  314. package/dist/spec/validate/overlays.js +2 -2
  315. package/dist/spec/validate/overlays.js.map +2 -2
  316. package/dist/spec/validate.data.d.ts.map +1 -1
  317. package/dist/spec/validate.data.js +8 -3
  318. package/dist/spec/validate.data.js.map +2 -2
  319. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/runtime/chartRuntime.ts"],
4
- "sourcesContent": ["import type { Datum, Size } from '../types';\nimport type { ChartSpec, KpiSpec, ValueRef } from '../spec/types';\nimport { chartDefinition } from '../spec/chartDefinitions';\nimport { resolveSketch } from '../spec/sketch';\nimport { applyTransforms } from '../spec/transform';\nimport { validateSpec } from '../spec/validate';\nimport { ensureSketchFont, type ThemeTokens } from '../theme';\nimport { Surface } from '../render/surface';\nimport { getDevicePixelRatio } from '../render/env';\nimport { fontsLoading, onFontsReady } from '../render/fonts';\nimport { drawAxesUnderlay, drawOverlay } from '../axes';\nimport { applyA11y } from '../a11y';\nimport { buildCartesianModel, seriesColorDomain, type CartesianChartSpec, type CartesianModel } from './cartesian';\nimport { buildRenderReport, type RenderReport } from './report';\nimport { createInspector, type Inspector } from './inspect';\nimport { renderDebugView } from './debug';\nimport { isFaceted, buildFacetModels, drawFacet, facetReport } from './facet';\nimport {\n CARTESIAN_TYPES,\n cartesianRenderers,\n cartesianInteractionBuilders,\n customRenderers,\n drawAnnotations,\n drawAnnotationLabels,\n drawTrendlines,\n drawTrendlineLabels,\n} from '../charts';\nimport type { RenderContext } from '../charts';\nimport { kpiSparklineSeries } from '../charts/kpi';\nimport { InteractionController, buildCartesianInteraction, type InteractionModel, type LegendHitRegion } from '../interaction';\nimport { createSelectionStore, type SelectionStore } from '../interaction/store';\nimport { applyPick, dependentParams, DIM_ALPHA, resolveEmphasis, resolveFilterValues, type SelectConfig } from '../interaction/select';\nimport { filterRows } from '../interaction/predicate';\nimport { resolveValueRef } from '../pivot';\nimport type { SelectionParam, SelectionValue } from '../spec/selection';\nimport { prefersReducedMotion, resolveEntrance, resolveUpdate, type AnimationHandle, type ResolvedEntrance } from '../animation';\nimport type { ChartInstance, RenderOptions, SelectionChangeListener } from './render';\nimport {\n applyLegendVisibility,\n CANVAS_MARK_TYPES,\n COUNT_UP_TYPES,\n drawPlaceholder,\n EMPTY_DATA,\n paintBackground,\n publishLegendToggle,\n resolveSize,\n resolveSketchTokens,\n seriesFieldIdentity,\n signalReady,\n specLegendParam,\n SWEEP_TYPES,\n type LegendSelectionConfig,\n} from './runtimeShared';\nimport { runCartesianEntrance, runCustomRendererProgress, runFadeEntrance, runUpdateCrossfade, snapshotLayer } from './chartAnimation';\n\ninterface FrameState {\n tokens: ThemeTokens;\n size: Size;\n anim: ResolvedEntrance;\n frameSignal: AbortSignal;\n}\n\ninterface PreparedFrame {\n baseData: Datum[];\n type: ChartSpec['type'];\n colorDomain?: readonly string[];\n filtered: Datum[];\n effectiveSpec: ChartSpec;\n emphasis: ReturnType<typeof resolveEmphasis>;\n ownParam?: SelectionParam;\n}\n\ninterface DispatchResult {\n interactionModel: InteractionModel | null;\n reportModel?: CartesianModel;\n report?: RenderReport;\n legendSelect?: { cfg: LegendSelectionConfig; hits: LegendHitRegion[] } | null;\n}\n\nexport class ChartRuntime {\n readonly surface: Surface;\n readonly store: SelectionStore;\n private currentSpec: ChartSpec;\n private observer?: ResizeObserver;\n private interaction?: InteractionController;\n private entrance?: AnimationHandle;\n private updateTransition?: AnimationHandle;\n // The nested chart instance backing the debug view's live preview (when\n // spec.debug is set). Destroyed and recreated on every draw() so it never\n // leaks observers/rAF when the overlay is cleared.\n private preview?: ChartInstance;\n private destroyed = false;\n // The value the most recent draw() resolved for a single-value visual\n // (kpi/gauge), so a later data update() can tween the number/needle from\n // it to the new value instead of snapping. Null for non-value visuals.\n private lastValue: number | null = null;\n // Parallel to lastValue for the gauge comparison arc, so a data update() tweens\n // the \"prior period\" arc from its previous value like the main value arc.\n private lastCompare: number | null = null;\n // Parallel to lastValue for a kpi sparkline, so a data update() can morph the\n // trend line from its previous shape into the new one (see morphSparkline).\n private lastSparkline: number[] | null = null;\n // The size we last actually drew at. The resize observer redraws only when the\n // container's measured size, or current DPR, diverges from this frame.\n private lastDrawnW = -1;\n private lastDrawnH = -1;\n private lastDpr = -1;\n // Set when a draw measured text while a web font was still loading. We listen\n // for the font once and redraw so the final layout uses real metrics.\n private fontRefreshArmed = false;\n // Set when the font settles mid-entrance: we defer the corrective redraw until\n // the entrance finishes so the animation isn't cut short by a snap.\n private pendingFontRefresh = false;\n // One-shot guard so the lazy sketch-font load only ever arms a single redraw.\n private sketchFontArmed = false;\n // The diagnostics from the most recent draw(), exposed via instance.report().\n private lastReport: RenderReport | null = null;\n private refreshReport?: () => RenderReport;\n private frameController?: AbortController;\n // Re-armed after every DPR change; removed on destroy. Browser zoom and moving\n // a window between monitors can change backing scale without a CSS resize.\n private dprQuery?: MediaQueryList;\n private dprQueryListener?: () => void;\n // Selection changes can arrive in bursts (e.g. clearSelection emits per param);\n // coalesce them to one redraw per chart per microtask, while report()/reads\n // flush the pending frame so observable state is still current.\n private pendingSelectionRedraw = false;\n private selectionRedrawQueued = false;\n // Palette history retains keys only; cross-filters never reseed it from a subset.\n private retainedSeriesField?: string;\n private retainedColorKeys: string[] = [];\n // Memoize the transform pipeline so resize/selection redraws don't recompute it.\n // Explicit update() invalidates the memo even when the caller reuses object\n // references, so in-place row edits cannot render stale transformed data.\n private txSrc?: Datum[];\n private txDef: unknown;\n private txOut: Datum[] = [];\n private readonly hostListeners = new Set<SelectionChangeListener>();\n private readonly inspector?: Inspector;\n private readonly unsubscribe: () => void;\n\n constructor(private readonly container: HTMLElement, spec: ChartSpec, private readonly options: RenderOptions = {}) {\n this.currentSpec = spec;\n this.surface = new Surface(container);\n // Selection bus: shared (linked charts) or private to this instance. Seed any\n // initial param values that aren't already present so a shared store wins.\n this.store = options.store ?? createSelectionStore();\n this.seedParams(spec);\n // Two-way DOM inspection publishes config to `data-graphein-spec` and\n // re-renders on external edits after merging back in-memory data.\n this.inspector = options.inspect === false ? undefined : createInspector(this.surface.root, {\n onExternalEdit: (config) => this.applyExternalEdit(config),\n });\n this.unsubscribe = this.store.subscribe((name, value) => this.handleSelectionChange(name, value));\n this.setupResizeObserver();\n this.initialDraw();\n }\n\n instance(): ChartInstance {\n const getSpec = () => this.currentSpec;\n return {\n get spec() { return getSpec(); },\n surface: this.surface,\n store: this.store,\n report: () => this.report(),\n getSelection: (name?: string) => this.getSelection(name),\n setSelection: (name, value) => this.setSelection(name, value),\n clearSelection: (name?: string) => this.clearSelection(name),\n on: (_event, listener) => this.onSelection(listener),\n off: (_event, listener) => this.hostListeners.delete(listener),\n update: (next) => this.update(next),\n resize: () => this.resize(),\n destroy: () => this.destroy(),\n };\n }\n\n private initialDraw(): void {\n try {\n this.draw(true);\n } catch (error) {\n try { this.destroy(); } catch { this.surface.root.remove(); }\n throw error;\n }\n }\n\n private effectiveData(): Datum[] {\n const src = this.currentSpec.data ?? EMPTY_DATA;\n const tx = this.currentSpec.transform;\n if (!tx || tx.length === 0) return src;\n if (this.txSrc === src && this.txDef === tx) return this.txOut;\n this.txSrc = src;\n this.txDef = tx;\n this.txOut = applyTransforms(tx, src);\n return this.txOut;\n }\n\n private invalidateTransforms(): void {\n this.txSrc = undefined;\n this.txDef = undefined;\n this.txOut = [];\n }\n\n private draw(\n animateEntrance: boolean,\n valueTweenFrom?: number,\n compareTweenFrom?: number,\n sparklineTweenFrom?: number[],\n ): void {\n // Explicit stages keep the browser runtime aligned with the headless path:\n // frame setup \u2192 data prep \u2192 renderer dispatch \u2192 interaction \u2192 report/hooks.\n const frame = this.beginFrame(animateEntrance);\n const prepared = this.prepareFrame(frame);\n this.captureValueState(prepared);\n const dispatch = this.dispatch(frame, prepared, valueTweenFrom, compareTweenFrom, sparklineTweenFrom);\n this.wireInteraction(frame.tokens, prepared, dispatch);\n this.finishFrame(frame, prepared, dispatch);\n }\n\n private beginFrame(animateEntrance: boolean): FrameState {\n this.frameController?.abort('redraw');\n this.frameController = new AbortController();\n this.cancelFrameWork();\n const tokens = resolveSketchTokens(this.currentSpec);\n const size = resolveSize(this.container, this.currentSpec);\n this.lastDrawnW = size.width;\n this.lastDrawnH = size.height;\n this.lastDpr = getDevicePixelRatio();\n this.surface.resize(size.width, size.height, this.lastDpr);\n this.surface.root.removeAttribute('data-graphein-ready');\n this.surface.root.style.opacity = '';\n this.surface.root.style.transform = '';\n this.surface.clear();\n paintBackground(this.surface, tokens, this.currentSpec.background);\n const anim = resolveEntrance(this.currentSpec.animation, {\n reducedMotion: prefersReducedMotion(),\n disabled: !animateEntrance || this.options.synchronous === true || globalThis.__GRAPHEIN_DISABLE_ANIM === true,\n });\n return { tokens, size, anim, frameSignal: this.frameController.signal };\n }\n\n private cancelFrameWork(): void {\n this.entrance?.cancel();\n this.entrance = undefined;\n this.updateTransition?.cancel();\n this.updateTransition = undefined;\n this.preview?.destroy();\n this.preview = undefined;\n }\n\n private prepareFrame(frame: FrameState): PreparedFrame {\n const baseData = this.effectiveData();\n const type = this.currentSpec.type;\n const colorDomain = this.prepareColorDomain(type, baseData);\n // Resolve interactivity for this frame: the rows after cross-filtering, and\n // the highlight (emphasis) to dim non-selected marks.\n const filters = resolveFilterValues(this.currentSpec.filter, this.store);\n const filtered = filters.length ? filterRows(baseData, filters) : baseData;\n this.surface.evidence.reset(frame.size, filtered.length, this.currentSpec.background ?? frame.tokens.color.background);\n const effectiveSpec = filtered === (this.currentSpec.data ?? EMPTY_DATA)\n ? this.currentSpec\n : ({ ...this.currentSpec, data: filtered } as ChartSpec);\n return {\n baseData, type, colorDomain, filtered, effectiveSpec,\n emphasis: resolveEmphasis(this.currentSpec.highlight, this.store, DIM_ALPHA),\n ownParam: this.currentSpec.params?.[0],\n };\n }\n\n private prepareColorDomain(type: ChartSpec['type'], baseData: Datum[]): readonly string[] | undefined {\n if (!CARTESIAN_TYPES.has(type)) {\n this.retainedSeriesField = undefined;\n this.retainedColorKeys = [];\n return undefined;\n }\n const sourceSpec = { ...this.currentSpec, data: baseData } as CartesianChartSpec;\n const field = seriesFieldIdentity(sourceSpec, baseData);\n if (field !== this.retainedSeriesField) this.retainedColorKeys = [];\n this.retainedSeriesField = field;\n this.retainedColorKeys = seriesColorDomain(sourceSpec, this.retainedColorKeys);\n return this.retainedColorKeys;\n }\n\n private captureValueState(prepared: PreparedFrame): void {\n if (!COUNT_UP_TYPES.has(prepared.type) && !SWEEP_TYPES.has(prepared.type)) return;\n // Remember the value a single-value visual resolves this frame (over the\n // possibly cross-filtered rows the renderer actually sees), so a later\n // update() can tween the number/needle from it \u2014 see update()'s valueTween.\n const data = prepared.effectiveSpec.data ?? EMPTY_DATA;\n this.lastValue = resolveValueRef((prepared.effectiveSpec as { value?: ValueRef }).value, data);\n this.lastCompare = SWEEP_TYPES.has(prepared.type)\n ? resolveValueRef((prepared.effectiveSpec as { compare?: ValueRef }).compare, data)\n : null;\n this.lastSparkline = prepared.type === 'kpi' ? kpiSparklineSeries(prepared.effectiveSpec as KpiSpec, data) : null;\n }\n\n private dispatch(\n frame: FrameState,\n prepared: PreparedFrame,\n valueFrom?: number,\n compareFrom?: number,\n sparklineFrom?: number[],\n ): DispatchResult {\n // Debug and faceting are runtime-level compositions rather than leaf\n // renderers, so they short-circuit the normal cartesian/custom dispatch.\n const facet = !this.currentSpec.debug && isFaceted(prepared.effectiveSpec)\n ? buildFacetModels(prepared.effectiveSpec, frame.tokens, frame.size, prepared.colorDomain) : null;\n if (this.currentSpec.debug) return this.dispatchDebug(frame, prepared);\n if (facet) return this.dispatchFacet(frame, prepared, facet);\n if (CARTESIAN_TYPES.has(prepared.type)) return this.dispatchCartesian(frame, prepared);\n return this.dispatchCustom(frame, prepared, valueFrom, compareFrom, sparklineFrom);\n }\n\n private dispatchDebug(frame: FrameState, prepared: PreparedFrame): DispatchResult {\n const thisOptions = this.options;\n const result = renderDebugView(this.surface, prepared.effectiveSpec, frame.tokens, frame.size, {\n renderPreview: (host, spec) => new ChartRuntime(host, spec, {\n inspect: false,\n get synchronous() { return thisOptions.synchronous; },\n }).instance(),\n });\n this.preview = result.preview ?? undefined;\n return { interactionModel: null, report: result.report };\n }\n\n private dispatchFacet(frame: FrameState, spec: PreparedFrame, layout: NonNullable<ReturnType<typeof buildFacetModels>>): DispatchResult {\n drawFacet(this.surface, spec.effectiveSpec, layout, frame.tokens);\n return { interactionModel: null, report: facetReport(spec.effectiveSpec, layout, frame.tokens, frame.size) };\n }\n\n private dispatchCartesian(frame: FrameState, prepared: PreparedFrame): DispatchResult {\n const renderer = cartesianRenderers[prepared.type];\n const model = buildCartesianModel(prepared.effectiveSpec as CartesianChartSpec, frame.tokens, {\n ...frame.size, colorDomain: prepared.colorDomain,\n });\n const legendCfg = applyLegendVisibility(model, this.store);\n const legendSelect = legendCfg && model.legendHits?.length ? { cfg: legendCfg, hits: model.legendHits } : null;\n model.emphasis = prepared.emphasis;\n // When animating, the marks (and their gridline underlay) are painted by\n // the entrance loop frame-by-frame; otherwise paint them once now.\n if (!frame.anim.enabled) {\n drawAxesUnderlay(this.surface, model);\n if (renderer) renderer(this.surface, model);\n drawTrendlines(this.surface, model);\n drawAnnotations(this.surface, model);\n }\n drawOverlay(this.surface, model);\n drawAnnotationLabels(this.surface, model);\n drawTrendlineLabels(this.surface, model);\n const override = cartesianInteractionBuilders[prepared.type];\n const interactionModel = override ? (override(model) ?? null) : buildCartesianInteraction(model);\n if (frame.anim.enabled && renderer) this.entrance = runCartesianEntrance(this.surface, model, renderer,\n frame.tokens, this.currentSpec.background, frame.anim, () => this.finishEntrance(),\n chartDefinition(prepared.type).entrance === 'grow' ? 'grow' : 'wipe');\n return { interactionModel, reportModel: model, legendSelect };\n }\n\n private dispatchCustom(\n frame: FrameState,\n prepared: PreparedFrame,\n valueFrom?: number,\n compareFrom?: number,\n sparklineFrom?: number[],\n ): DispatchResult {\n const renderer = customRenderers[prepared.type];\n if (!renderer) return this.dispatchPlaceholder(frame, prepared.type);\n const ctx = this.customContext(frame, prepared);\n const interactionModel = renderer(this.surface, prepared.effectiveSpec, frame.tokens, frame.size, ctx) ?? null;\n if (frame.anim.enabled) this.startCustomEntrance(frame, prepared, renderer, ctx);\n else this.startValueTween(frame, prepared, renderer, ctx, valueFrom, compareFrom, sparklineFrom);\n return { interactionModel };\n }\n\n private dispatchPlaceholder(frame: FrameState, type: ChartSpec['type']): DispatchResult {\n drawPlaceholder(this.surface, frame.tokens, `\u201C${type}\u201D renderer not yet registered`);\n if (frame.anim.enabled) this.entrance = runFadeEntrance(this.surface, frame.anim, () => this.finishEntrance());\n return { interactionModel: null };\n }\n\n private customContext(frame: FrameState, prepared: PreparedFrame): RenderContext {\n return {\n emphasis: prepared.emphasis,\n store: this.store,\n param: prepared.ownParam?.name,\n def: prepared.ownParam?.select,\n sourceData: prepared.baseData,\n framed: this.options.frame === true,\n signal: frame.frameSignal,\n requestRedraw: () => { if (!this.destroyed) this.draw(false); },\n };\n }\n\n private startCustomEntrance(frame: FrameState, prepared: PreparedFrame, renderer: NonNullable<typeof customRenderers[ChartSpec['type']]>, ctx: RenderContext): void {\n if (!COUNT_UP_TYPES.has(prepared.type) && !SWEEP_TYPES.has(prepared.type)) {\n this.entrance = runFadeEntrance(this.surface, frame.anim, () => this.finishEntrance());\n return;\n }\n // Re-run the renderer each frame with an interpolation progress mixed into\n // its context (number roll-up / arc sweep). The final frame is pixel-identical\n // to the static draw above.\n const key = COUNT_UP_TYPES.has(prepared.type) ? 'valueProgress' : 'sweepProgress';\n this.entrance = runCustomRendererProgress(this.surface, renderer, prepared.effectiveSpec, frame.tokens, frame.size, {\n anim: frame.anim, onDone: () => this.finishEntrance(), dataLength: prepared.filtered.length,\n background: this.currentSpec.background, context: ctx, progressKey: key,\n });\n }\n\n private startValueTween(\n frame: FrameState,\n prepared: PreparedFrame,\n renderer: NonNullable<typeof customRenderers[ChartSpec['type']]>,\n ctx: RenderContext,\n valueFrom?: number,\n compareFrom?: number,\n sparklineFrom?: number[],\n ): void {\n if ((valueFrom === undefined && sparklineFrom === undefined) ||\n (!COUNT_UP_TYPES.has(prepared.type) && !SWEEP_TYPES.has(prepared.type))) return;\n // Data update() on a value visual: tween the number/needle from the\n // previously-shown value to the value just drawn above, reusing the entrance\n // count-up/sweep loop. The synchronous draw already painted the final value\n // (so SSR/no-rAF/test reads stay final); the first rAF frame rolls back to\n // ~the old value and animates forward.\n const tween = resolveUpdate(this.currentSpec.animation, {\n reducedMotion: prefersReducedMotion(),\n disabled: this.options.synchronous === true || globalThis.__GRAPHEIN_DISABLE_ANIM === true,\n });\n if (!tween.enabled) return;\n const key = COUNT_UP_TYPES.has(prepared.type) ? 'valueProgress' : 'sweepProgress';\n this.entrance = runCustomRendererProgress(this.surface, renderer, prepared.effectiveSpec, frame.tokens, frame.size, {\n anim: tween, onDone: () => this.finishEntrance(), dataLength: prepared.filtered.length,\n background: this.currentSpec.background, context: ctx, progressKey: key,\n extraContext: { valueFrom, compareFrom, sparklineFrom },\n });\n }\n\n private wireInteraction(tokens: ThemeTokens, prepared: PreparedFrame, result: DispatchResult): void {\n if (!this.interaction) this.interaction = new InteractionController(this.surface, tokens);\n this.interaction.setModel(result.interactionModel, tokens);\n const canPick = prepared.ownParam && result.interactionModel?.pick;\n const canLegend = result.legendSelect && result.interactionModel?.legendHits?.length;\n if (!canPick && !canLegend) return this.interaction.setSelect(null);\n // Wire click/tap selection when this chart defines a param and its model can\n // resolve a pick. Slicers publish via the render context instead.\n const cfg: SelectConfig | null = prepared.ownParam\n ? { store: this.store, param: prepared.ownParam.name, def: prepared.ownParam.select } : null;\n this.interaction.setSelect({\n onPick: cfg && result.interactionModel?.pick ? (value) => applyPick(cfg, value) : undefined,\n onLegendToggle: result.legendSelect ? (hit, event) => publishLegendToggle(\n this.store, result.legendSelect!.cfg, result.legendSelect!.hits, hit, event.shiftKey || event.altKey) : undefined,\n });\n }\n\n private finishFrame(frame: FrameState, prepared: PreparedFrame, result: DispatchResult): void {\n applyA11y(this.surface, this.currentSpec);\n this.inspector?.write(this.currentSpec);\n // Derive the machine-readable render report from the resolved model. Pure\n // (reads the model + theme, never the canvas), so it works headlessly too.\n this.refreshReport = () => result.report ?? buildRenderReport({\n type: prepared.type, spec: this.currentSpec, data: prepared.filtered,\n tokens: frame.tokens, size: frame.size, model: result.reportModel,\n labels: this.surface.labels.records, suppressedLabels: this.surface.labels.suppressed,\n evidence: this.surface.evidence.snapshot(),\n });\n this.lastReport = this.refreshReport();\n // Animated entrances signal ready on their final frame; everything else now.\n if (!this.entrance) signalReady(this.surface);\n // If text was measured with fallback metrics (web font still loading), arm a\n // one-shot corrective redraw for when the real font arrives.\n this.armFontRefresh();\n // Sketch charts use a bundled handwriting font that loads lazily; once it's\n // ready, redraw so text is laid out with its real glyph metrics.\n this.armSketchFont();\n this.armDprRefresh();\n }\n\n private finishEntrance(): void {\n // Entrance completion: mark ready, then apply any font-load correction that\n // was deferred so it wouldn't interrupt the animation.\n if (this.refreshReport) this.lastReport = this.refreshReport();\n signalReady(this.surface);\n if (this.pendingFontRefresh && !this.destroyed) {\n this.pendingFontRefresh = false;\n this.draw(false);\n }\n }\n\n private armFontRefresh(): void {\n // Self-healing layout: a chart drawn before its web font loads is measured\n // with fallback metrics. Listen once for the font and redraw with real\n // metrics. If an entrance is mid-flight, defer the redraw to its completion\n // to avoid a snap.\n if (this.fontRefreshArmed || !fontsLoading()) return;\n this.fontRefreshArmed = true;\n onFontsReady(() => {\n this.fontRefreshArmed = false;\n if (this.destroyed) return;\n if (this.entrance) this.pendingFontRefresh = true;\n else this.draw(false);\n });\n }\n\n private armSketchFont(): void {\n // The sketch font is bundled and loads lazily (data URL, no network). When it\n // first becomes available, redraw once so handwriting metrics replace the\n // fallback ones. `ensureSketchFont` resolves `true` only on the load that\n // actually injected it, so this never loops.\n if (this.sketchFontArmed || !resolveSketch(this.currentSpec)?.font) return;\n this.sketchFontArmed = true;\n void ensureSketchFont().then((loaded) => { if (loaded && !this.destroyed) this.draw(false); });\n }\n\n private armDprRefresh(): void {\n if (typeof globalThis.matchMedia !== 'function') return;\n this.clearDprRefresh();\n const query = globalThis.matchMedia(`(resolution: ${this.lastDpr}dppx)`);\n const listener = () => {\n if (this.destroyed) return;\n if (getDevicePixelRatio() !== this.lastDpr) this.draw(false);\n else this.armDprRefresh();\n };\n this.dprQuery = query;\n this.dprQueryListener = listener;\n if (typeof query.addEventListener === 'function') query.addEventListener('change', listener);\n else query.addListener?.(listener);\n }\n\n private clearDprRefresh(): void {\n if (!this.dprQuery || !this.dprQueryListener) return;\n if (typeof this.dprQuery.removeEventListener === 'function') {\n this.dprQuery.removeEventListener('change', this.dprQueryListener);\n } else this.dprQuery.removeListener?.(this.dprQueryListener);\n this.dprQuery = undefined;\n this.dprQueryListener = undefined;\n }\n\n private setupResizeObserver(): void {\n const auto = this.currentSpec.dimensions?.autoResize ??\n (this.currentSpec.dimensions?.width == null || this.currentSpec.dimensions?.height == null);\n if (!auto || typeof ResizeObserver === 'undefined') return;\n // Redraw on container resize, but only when the measured size or DPR actually\n // diverges from what we last drew. That skips the redundant delivery the\n // observer fires on observe() while still honoring a resize that lands before\n // the first delivery \u2014 e.g. a dashboard reflow. Resizes never animate.\n this.observer = new ResizeObserver(() => {\n if (this.destroyed) return;\n const s = resolveSize(this.container, this.currentSpec);\n if (s.width === this.lastDrawnW && s.height === this.lastDrawnH && getDevicePixelRatio() === this.lastDpr) return;\n this.draw(false);\n });\n this.observer.observe(this.container);\n }\n\n update(next: ChartSpec): void {\n if (this.destroyed) return;\n this.updateTransition?.cancel();\n this.updateTransition = undefined;\n this.pendingSelectionRedraw = false;\n this.selectionRedrawQueued = false;\n this.invalidateTransforms();\n this.seedParams(next);\n // Decide whether to cross-fade the marks layer: both the outgoing and\n // incoming chart must be canvas-mark kinds, motion must be enabled, and\n // the surface size must be unchanged (a dimension change is a resize, not\n // a data morph \u2014 those snap to avoid a stretched bitmap).\n const prevType = this.currentSpec.type;\n const before = this.updateSnapshot(prevType, next);\n const prevW = this.surface.width;\n const prevH = this.surface.height;\n // Value visuals (kpi/gauge) aren't canvas-mark kinds, so instead of a\n // bitmap cross-fade we roll the number / sweep the needle from the value the\n // last draw showed to the new one. Needs the same value type on both sides\n // and a real previous value; draw() gates the actual motion on resolveUpdate\n // (reduced-motion / screenshot kill-switch \u2192 snaps).\n const prev = { value: this.lastValue, compare: this.lastCompare, sparkline: this.lastSparkline };\n this.currentSpec = next;\n const wantValue = prevType === next.type && (COUNT_UP_TYPES.has(next.type) || SWEEP_TYPES.has(next.type)) && prev.value != null;\n // A KPI can morph its sparkline into the new shape even when the numeric\n // value itself is unavailable (shows \"\u2014\"), so drive that off the previous\n // series independently of the value roll-up.\n const wantSparkline = prevType === next.type && next.type === 'kpi' && !!prev.sparkline?.length;\n this.draw(false, wantValue ? (prev.value ?? undefined) : undefined,\n wantValue ? (prev.compare ?? undefined) : undefined,\n wantValue || wantSparkline ? (prev.sparkline ?? undefined) : undefined);\n this.startUpdateCrossfade(before, prevW, prevH, next);\n }\n\n private updateSnapshot(prevType: ChartSpec['type'], next: ChartSpec): HTMLCanvasElement | undefined {\n const anim = resolveUpdate(next.animation, {\n reducedMotion: prefersReducedMotion(),\n disabled: this.options.synchronous === true || globalThis.__GRAPHEIN_DISABLE_ANIM === true,\n });\n const wantFade = anim.enabled && CANVAS_MARK_TYPES.has(prevType) && CANVAS_MARK_TYPES.has(next.type);\n return wantFade ? snapshotLayer(this.surface.marks) : undefined;\n }\n\n private startUpdateCrossfade(before: HTMLCanvasElement | undefined, prevW: number, prevH: number, next: ChartSpec): void {\n if (!before || this.surface.width !== prevW || this.surface.height !== prevH ||\n this.surface.marks.canvas.width !== before.width || this.surface.marks.canvas.height !== before.height) return;\n const anim = resolveUpdate(next.animation, {\n reducedMotion: prefersReducedMotion(),\n disabled: this.options.synchronous === true || globalThis.__GRAPHEIN_DISABLE_ANIM === true,\n });\n this.updateTransition = runUpdateCrossfade(this.surface, before, anim);\n }\n\n resize(): void {\n if (!this.destroyed) this.draw(false);\n }\n\n report(): RenderReport {\n this.flushSelectionRedraw();\n if (!this.destroyed) {\n this.surface.collectEvidence?.();\n if (this.refreshReport) this.lastReport = this.refreshReport();\n }\n return this.lastReport ?? this.emptyReport();\n }\n\n private emptyReport(): RenderReport {\n return {\n type: this.currentSpec.type,\n size: resolveSize(this.container, this.currentSpec),\n markCount: 0, seriesCount: 0, colorCount: 0, ok: false,\n diagnostics: [{ code: 'render-evidence-incomplete', severity: 'warning',\n message: 'No completed draw evidence is available yet.' }],\n evidence: this.surface.evidence.snapshot(),\n };\n }\n\n getSelection(name?: string): SelectionValue | null | Record<string, SelectionValue | null> {\n this.flushSelectionRedraw();\n return name === undefined ? this.store.all() : this.store.get(name);\n }\n\n setSelection(name: string, value: SelectionValue | null): void {\n if (!this.destroyed) this.store.set(name, value);\n }\n\n clearSelection(name?: string): void {\n if (!this.destroyed) this.store.clear(name);\n }\n\n private onSelection(listener: SelectionChangeListener): () => void {\n this.hostListeners.add(listener);\n return () => this.hostListeners.delete(listener);\n }\n\n private handleSelectionChange(name: string, value: SelectionValue | null): void {\n for (const listener of [...this.hostListeners]) listener(name, value);\n if (this.destroyed) return;\n if (dependentParams(this.currentSpec.highlight, this.currentSpec.filter).has(name) ||\n specLegendParam(this.currentSpec) === name) this.scheduleSelectionRedraw();\n }\n\n private scheduleSelectionRedraw(): void {\n if (this.destroyed) return;\n this.pendingSelectionRedraw = true;\n if (this.options.synchronous === true) return this.flushSelectionRedraw();\n if (this.selectionRedrawQueued) return;\n this.selectionRedrawQueued = true;\n queueMicrotask(() => this.flushSelectionRedraw());\n }\n\n private flushSelectionRedraw(): void {\n if (!this.pendingSelectionRedraw || this.destroyed) return;\n this.pendingSelectionRedraw = false;\n this.selectionRedrawQueued = false;\n this.draw(false);\n }\n\n private applyExternalEdit(config: Record<string, unknown>): void {\n if (this.destroyed) return;\n // External DOM edits are config-only; merge them with in-memory data and\n // ignore invalid partial edits so the last good render remains intact.\n const merged = { ...config, data: this.currentSpec.data } as ChartSpec;\n if (validateSpec(merged).errors.length > 0) return;\n this.update(merged);\n }\n\n private seedParams(spec: ChartSpec): void {\n for (const param of spec.params ?? []) {\n if (param.value !== undefined && this.store.get(param.name) == null) {\n this.store.set(param.name, param.value ?? null);\n }\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.unsubscribe();\n this.hostListeners.clear();\n this.entrance?.cancel();\n this.updateTransition?.cancel();\n this.frameController?.abort('destroy');\n this.frameController = undefined;\n this.clearDprRefresh();\n this.observer?.disconnect();\n this.inspector?.destroy();\n this.interaction?.destroy();\n try { this.preview?.destroy(); } finally { this.surface.destroy(); }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Datum, Size } from '../types';\nimport type { ChartSpec, KpiSpec, ValueRef } from '../spec/types';\nimport { chartDefinition } from '../spec/chartDefinitions';\nimport { resolveSketch } from '../spec/sketch';\nimport { applyTransforms } from '../spec/transform';\nimport { validateSpec } from '../spec/validate';\nimport { ensureSketchFont, type ThemeTokens } from '../theme';\nimport { Surface } from '../render/surface';\nimport { getDevicePixelRatio } from '../render/env';\nimport { fontsLoading, onFontsReady } from '../render/fonts';\nimport { drawAxesUnderlay, drawOverlay } from '../axes';\nimport { applyA11y } from '../a11y';\nimport { buildCartesianModel, seriesColorDomain, type CartesianChartSpec, type CartesianModel } from './cartesian';\nimport { buildRenderReport, type RenderReport } from './report';\nimport { createInspector, type Inspector } from './inspect';\nimport { renderDebugView } from './debug';\nimport { isFaceted, buildFacetModels, drawFacet, facetReport } from './facet';\nimport {\n CARTESIAN_TYPES,\n cartesianRenderers,\n cartesianInteractionBuilders,\n customRenderers,\n drawAnnotations,\n drawAnnotationLabels,\n drawTrendlines,\n drawTrendlineLabels,\n} from '../charts';\nimport type { RenderContext } from '../charts';\nimport { kpiSparklineSeries } from '../charts/kpi';\nimport { InteractionController, buildCartesianInteraction, type InteractionModel, type LegendHitRegion } from '../interaction';\nimport { createSelectionStore, type SelectionStore } from '../interaction/store';\nimport { applyPick, dependentParams, DIM_ALPHA, resolveEmphasis, resolveFilterValues, type SelectConfig } from '../interaction/select';\nimport { filterRows } from '../interaction/predicate';\nimport { resolveValueRef } from '../pivot';\nimport type { SelectionParam, SelectionValue } from '../spec/selection';\nimport { prefersReducedMotion, resolveEntrance, resolveUpdate, type AnimationHandle, type ResolvedEntrance } from '../animation';\nimport type { ChartInstance, RenderOptions, SelectionChangeListener } from './render';\nimport {\n applyLegendVisibility,\n CANVAS_MARK_TYPES,\n COUNT_UP_TYPES,\n drawPlaceholder,\n EMPTY_DATA,\n paintBackground,\n publishLegendToggle,\n resolveSize,\n resolveSketchTokens,\n seriesFieldIdentity,\n signalReady,\n specLegendParam,\n SWEEP_TYPES,\n type LegendSelectionConfig,\n} from './runtimeShared';\nimport { runCartesianEntrance, runCartesianMorph, runCustomRendererProgress, runFadeEntrance, runUpdateCrossfade, snapshotLayer } from './chartAnimation';\nimport { planGeometryMorph, type GeometryMorph } from './morph';\nimport type { CartesianGeometry } from '../charts/geometry';\nimport { pieStateOf, type PieSliceState } from '../charts/pieState';\nimport { clearMorphFrame, morphFrameOf } from '../charts/morphFrame';\nimport { captureChrome, clearChrome, setChromeEntrance, type ChromeSnapshot } from '../render/chromeMotion';\n\n/** Chart types whose update transitions morph mark geometry instead of cross-fading. */\nconst MORPH_TYPES: ReadonlySet<ChartSpec['type']> = new Set<ChartSpec['type']>(['bar', 'line', 'area', 'scatter', 'box']);\n/** Above this many rows a custom chart's update cross-fades instead of re-rendering per frame. */\nconst CUSTOM_MORPH_ROW_LIMIT = 5000;\n\ninterface FrameState {\n tokens: ThemeTokens;\n size: Size;\n anim: ResolvedEntrance;\n frameSignal: AbortSignal;\n}\n\ninterface PreparedFrame {\n baseData: Datum[];\n type: ChartSpec['type'];\n colorDomain?: readonly string[];\n filtered: Datum[];\n effectiveSpec: ChartSpec;\n emphasis: ReturnType<typeof resolveEmphasis>;\n ownParam?: SelectionParam;\n}\n\ninterface DispatchResult {\n interactionModel: InteractionModel | null;\n reportModel?: CartesianModel;\n report?: RenderReport;\n legendSelect?: { cfg: LegendSelectionConfig; hits: LegendHitRegion[] } | null;\n}\n\nexport class ChartRuntime {\n readonly surface: Surface;\n readonly store: SelectionStore;\n private currentSpec: ChartSpec;\n private observer?: ResizeObserver;\n private interaction?: InteractionController;\n private entrance?: AnimationHandle;\n private updateTransition?: AnimationHandle;\n // The cartesian model behind the frame on screen; its `geometry` is where an\n // update morph starts from. Cleared whenever a non-cartesian frame is drawn.\n private lastModel?: CartesianModel;\n // The in-flight update morph and its latest eased progress, so an update that\n // interrupts it morphs onward from what is actually on screen.\n private morphState?: { morph: GeometryMorph; t: number };\n // Outgoing geometry handed from update()/selection redraws to the next draw.\n private pendingMorph?: CartesianGeometry;\n // Outgoing pie/donut slices handed to the next draw so slices re-balance.\n private pendingSliceMorph?: readonly PieSliceState[];\n // Outgoing keyed marks (see charts/morphFrame) a custom renderer stashed,\n // handed to the next draw so its marks travel instead of cross-fading.\n private pendingCustomMorph?: unknown;\n // The axes, annotations and trendlines on screen when an update began, so a\n // morph moves them with the marks (see render/chromeMotion).\n private pendingChrome?: ChromeSnapshot;\n // The nested chart instance backing the debug view's live preview (when\n // spec.debug is set). Destroyed and recreated on every draw() so it never\n // leaks observers/rAF when the overlay is cleared.\n private preview?: ChartInstance;\n private destroyed = false;\n // The value the most recent draw() resolved for a single-value visual\n // (kpi/gauge), so a later data update() can tween the number/needle from\n // it to the new value instead of snapping. Null for non-value visuals.\n private lastValue: number | null = null;\n // Parallel to lastValue for the gauge comparison arc, so a data update() tweens\n // the \"prior period\" arc from its previous value like the main value arc.\n private lastCompare: number | null = null;\n // Parallel to lastValue for a kpi sparkline, so a data update() can morph the\n // trend line from its previous shape into the new one (see morphSparkline).\n private lastSparkline: number[] | null = null;\n // The size we last actually drew at. The resize observer redraws only when the\n // container's measured size, or current DPR, diverges from this frame.\n private lastDrawnW = -1;\n private lastDrawnH = -1;\n private lastDpr = -1;\n // Set when a draw measured text while a web font was still loading. We listen\n // for the font once and redraw so the final layout uses real metrics.\n private fontRefreshArmed = false;\n // Set when the font settles mid-entrance: we defer the corrective redraw until\n // the entrance finishes so the animation isn't cut short by a snap.\n private pendingFontRefresh = false;\n // One-shot guard so the lazy sketch-font load only ever arms a single redraw.\n private sketchFontArmed = false;\n // The diagnostics from the most recent draw(), exposed via instance.report().\n private lastReport: RenderReport | null = null;\n private refreshReport?: () => RenderReport;\n private frameController?: AbortController;\n // Re-armed after every DPR change; removed on destroy. Browser zoom and moving\n // a window between monitors can change backing scale without a CSS resize.\n private dprQuery?: MediaQueryList;\n private dprQueryListener?: () => void;\n // Selection changes can arrive in bursts (e.g. clearSelection emits per param);\n // coalesce them to one redraw per chart per microtask, while report()/reads\n // flush the pending frame so observable state is still current.\n private pendingSelectionRedraw = false;\n private selectionRedrawQueued = false;\n // Palette history retains keys only; cross-filters never reseed it from a subset.\n private retainedSeriesField?: string;\n private retainedColorKeys: string[] = [];\n // Memoize the transform pipeline so resize/selection redraws don't recompute it.\n // Explicit update() invalidates the memo even when the caller reuses object\n // references, so in-place row edits cannot render stale transformed data.\n private txSrc?: Datum[];\n private txDef: unknown;\n private txOut: Datum[] = [];\n private readonly hostListeners = new Set<SelectionChangeListener>();\n private readonly inspector?: Inspector;\n private readonly unsubscribe: () => void;\n\n constructor(private readonly container: HTMLElement, spec: ChartSpec, private readonly options: RenderOptions = {}) {\n this.currentSpec = spec;\n this.surface = new Surface(container);\n // Selection bus: shared (linked charts) or private to this instance. Seed any\n // initial param values that aren't already present so a shared store wins.\n this.store = options.store ?? createSelectionStore();\n this.seedParams(spec);\n // Two-way DOM inspection publishes config to `data-graphein-spec` and\n // re-renders on external edits after merging back in-memory data.\n this.inspector = options.inspect === false ? undefined : createInspector(this.surface.root, {\n onExternalEdit: (config) => this.applyExternalEdit(config),\n });\n this.unsubscribe = this.store.subscribe((name, value) => this.handleSelectionChange(name, value));\n this.setupResizeObserver();\n this.initialDraw();\n }\n\n instance(): ChartInstance {\n const getSpec = () => this.currentSpec;\n return {\n get spec() { return getSpec(); },\n surface: this.surface,\n store: this.store,\n report: () => this.report(),\n getSelection: (name?: string) => this.getSelection(name),\n setSelection: (name, value) => this.setSelection(name, value),\n clearSelection: (name?: string) => this.clearSelection(name),\n on: (_event, listener) => this.onSelection(listener),\n off: (_event, listener) => this.hostListeners.delete(listener),\n update: (next) => this.update(next),\n resize: () => this.resize(),\n destroy: () => this.destroy(),\n };\n }\n\n private initialDraw(): void {\n try {\n this.draw(true);\n } catch (error) {\n try { this.destroy(); } catch { this.surface.root.remove(); }\n throw error;\n }\n }\n\n private effectiveData(): Datum[] {\n const src = this.currentSpec.data ?? EMPTY_DATA;\n const tx = this.currentSpec.transform;\n if (!tx || tx.length === 0) return src;\n if (this.txSrc === src && this.txDef === tx) return this.txOut;\n this.txSrc = src;\n this.txDef = tx;\n this.txOut = applyTransforms(tx, src);\n return this.txOut;\n }\n\n private invalidateTransforms(): void {\n this.txSrc = undefined;\n this.txDef = undefined;\n this.txOut = [];\n }\n\n private draw(\n animateEntrance: boolean,\n valueTweenFrom?: number,\n compareTweenFrom?: number,\n sparklineTweenFrom?: number[],\n ): void {\n // Explicit stages keep the browser runtime aligned with the headless path:\n // frame setup \u2192 data prep \u2192 renderer dispatch \u2192 interaction \u2192 report/hooks.\n const frame = this.beginFrame(animateEntrance);\n const prepared = this.prepareFrame(frame);\n this.captureValueState(prepared);\n const dispatch = this.dispatch(frame, prepared, valueTweenFrom, compareTweenFrom, sparklineTweenFrom);\n this.wireInteraction(frame.tokens, prepared, dispatch);\n this.finishFrame(frame, prepared, dispatch);\n }\n\n private beginFrame(animateEntrance: boolean): FrameState {\n this.frameController?.abort('redraw');\n this.frameController = new AbortController();\n this.cancelFrameWork();\n const tokens = resolveSketchTokens(this.currentSpec);\n const size = resolveSize(this.container, this.currentSpec);\n this.lastDrawnW = size.width;\n this.lastDrawnH = size.height;\n this.lastDpr = getDevicePixelRatio();\n this.surface.resize(size.width, size.height, this.lastDpr);\n this.surface.root.removeAttribute('data-graphein-ready');\n this.surface.root.style.opacity = '';\n this.surface.root.style.transform = '';\n this.surface.clear();\n paintBackground(this.surface, tokens, this.currentSpec.background);\n const anim = resolveEntrance(this.currentSpec.animation, {\n reducedMotion: prefersReducedMotion(),\n disabled: !animateEntrance || this.options.synchronous === true || globalThis.__GRAPHEIN_DISABLE_ANIM === true,\n });\n return { tokens, size, anim, frameSignal: this.frameController.signal };\n }\n\n private cancelFrameWork(): void {\n this.entrance?.cancel();\n this.entrance = undefined;\n this.updateTransition?.cancel();\n this.updateTransition = undefined;\n this.morphState = undefined;\n setChromeEntrance(this.surface, null);\n this.preview?.destroy();\n this.preview = undefined;\n }\n\n private prepareFrame(frame: FrameState): PreparedFrame {\n const baseData = this.effectiveData();\n const type = this.currentSpec.type;\n const colorDomain = this.prepareColorDomain(type, baseData);\n // Resolve interactivity for this frame: the rows after cross-filtering, and\n // the highlight (emphasis) to dim non-selected marks.\n const filters = resolveFilterValues(this.currentSpec.filter, this.store);\n const filtered = filters.length ? filterRows(baseData, filters) : baseData;\n this.surface.evidence.reset(frame.size, filtered.length, this.currentSpec.background ?? frame.tokens.color.background);\n const effectiveSpec = filtered === (this.currentSpec.data ?? EMPTY_DATA)\n ? this.currentSpec\n : ({ ...this.currentSpec, data: filtered } as ChartSpec);\n return {\n baseData, type, colorDomain, filtered, effectiveSpec,\n emphasis: resolveEmphasis(this.currentSpec.highlight, this.store, DIM_ALPHA),\n ownParam: this.currentSpec.params?.[0],\n };\n }\n\n private prepareColorDomain(type: ChartSpec['type'], baseData: Datum[]): readonly string[] | undefined {\n if (!CARTESIAN_TYPES.has(type)) {\n this.retainedSeriesField = undefined;\n this.retainedColorKeys = [];\n return undefined;\n }\n const sourceSpec = { ...this.currentSpec, data: baseData } as CartesianChartSpec;\n const field = seriesFieldIdentity(sourceSpec, baseData);\n if (field !== this.retainedSeriesField) this.retainedColorKeys = [];\n this.retainedSeriesField = field;\n this.retainedColorKeys = seriesColorDomain(sourceSpec, this.retainedColorKeys);\n return this.retainedColorKeys;\n }\n\n private captureValueState(prepared: PreparedFrame): void {\n if (!COUNT_UP_TYPES.has(prepared.type) && !SWEEP_TYPES.has(prepared.type)) return;\n // Remember the value a single-value visual resolves this frame (over the\n // possibly cross-filtered rows the renderer actually sees), so a later\n // update() can tween the number/needle from it \u2014 see update()'s valueTween.\n const data = prepared.effectiveSpec.data ?? EMPTY_DATA;\n this.lastValue = resolveValueRef((prepared.effectiveSpec as { value?: ValueRef }).value, data);\n this.lastCompare = SWEEP_TYPES.has(prepared.type)\n ? resolveValueRef((prepared.effectiveSpec as { compare?: ValueRef }).compare, data)\n : null;\n this.lastSparkline = prepared.type === 'kpi' ? kpiSparklineSeries(prepared.effectiveSpec as KpiSpec, data) : null;\n }\n\n private dispatch(\n frame: FrameState,\n prepared: PreparedFrame,\n valueFrom?: number,\n compareFrom?: number,\n sparklineFrom?: number[],\n ): DispatchResult {\n // Debug and faceting are runtime-level compositions rather than leaf\n // renderers, so they short-circuit the normal cartesian/custom dispatch.\n this.lastModel = undefined;\n // Morph sources were captured before this draw; a renderer that can morph\n // re-stashes the marks it paints now, so nothing stale outlives the frame.\n clearMorphFrame(this.surface);\n clearChrome(this.surface);\n const facet = !this.currentSpec.debug && isFaceted(prepared.effectiveSpec)\n ? buildFacetModels(prepared.effectiveSpec, frame.tokens, frame.size, prepared.colorDomain) : null;\n if (this.currentSpec.debug) return this.dispatchDebug(frame, prepared);\n if (facet) return this.dispatchFacet(frame, prepared, facet);\n if (CARTESIAN_TYPES.has(prepared.type)) return this.dispatchCartesian(frame, prepared);\n return this.dispatchCustom(frame, prepared, valueFrom, compareFrom, sparklineFrom);\n }\n\n private dispatchDebug(frame: FrameState, prepared: PreparedFrame): DispatchResult {\n const thisOptions = this.options;\n const result = renderDebugView(this.surface, prepared.effectiveSpec, frame.tokens, frame.size, {\n renderPreview: (host, spec) => new ChartRuntime(host, spec, {\n inspect: false,\n get synchronous() { return thisOptions.synchronous; },\n }).instance(),\n });\n this.preview = result.preview ?? undefined;\n return { interactionModel: null, report: result.report };\n }\n\n private dispatchFacet(frame: FrameState, spec: PreparedFrame, layout: NonNullable<ReturnType<typeof buildFacetModels>>): DispatchResult {\n drawFacet(this.surface, spec.effectiveSpec, layout, frame.tokens);\n return { interactionModel: null, report: facetReport(spec.effectiveSpec, layout, frame.tokens, frame.size) };\n }\n\n private dispatchCartesian(frame: FrameState, prepared: PreparedFrame): DispatchResult {\n const renderer = cartesianRenderers[prepared.type];\n const model = buildCartesianModel(prepared.effectiveSpec as CartesianChartSpec, frame.tokens, {\n ...frame.size, colorDomain: prepared.colorDomain,\n });\n const legendCfg = applyLegendVisibility(model, this.store);\n const legendSelect = legendCfg && model.legendHits?.length ? { cfg: legendCfg, hits: model.legendHits } : null;\n model.emphasis = prepared.emphasis;\n // When animating, the marks (and their gridline underlay) are painted by\n // the entrance loop frame-by-frame; otherwise paint them once now.\n if (!frame.anim.enabled) {\n drawAxesUnderlay(this.surface, model);\n if (renderer) renderer(this.surface, model);\n drawTrendlines(this.surface, model);\n drawAnnotations(this.surface, model);\n }\n drawOverlay(this.surface, model);\n const lateLabels = [...drawAnnotationLabels(this.surface, model), ...drawTrendlineLabels(this.surface, model)];\n const override = cartesianInteractionBuilders[prepared.type];\n const interactionModel = override ? (override(model) ?? null) : buildCartesianInteraction(model);\n if (frame.anim.enabled && renderer) this.entrance = runCartesianEntrance(this.surface, model, renderer,\n frame.tokens, this.currentSpec.background, frame.anim, () => this.finishEntrance(),\n chartDefinition(prepared.type).entrance === 'grow' ? 'grow' : 'wipe', lateLabels);\n this.lastModel = model;\n const morphFrom = this.pendingMorph;\n this.pendingMorph = undefined;\n if (morphFrom && !frame.anim.enabled) this.startMorph(frame, model, morphFrom);\n return { interactionModel, reportModel: model, legendSelect };\n }\n\n /**\n * Start an update morph from `from` (the outgoing frame's geometry) to the\n * frame just drawn statically. A no-op when the pair can't be morphed, which\n * leaves update() free to fall back to its cross-fade.\n */\n private startMorph(frame: FrameState, model: CartesianModel, from: CartesianGeometry): void {\n const to = model.geometry;\n const anim = this.updateMotion(this.currentSpec);\n if (!to || !anim.enabled) return;\n const morph = planGeometryMorph(from, to);\n if (!morph) return;\n const timing = morph.durationScale ? { ...anim, duration: anim.duration * morph.durationScale } : anim;\n this.updateTransition = runCartesianMorph(this.surface, model, morph, frame.tokens, this.currentSpec.background, timing,\n (t) => { this.morphState = { morph, t }; },\n () => { this.morphState = undefined; this.updateTransition = undefined; this.interaction?.refresh(); },\n this.pendingChrome);\n }\n\n /** Update-transition timing for `spec` under the current motion environment. */\n private updateMotion(spec: ChartSpec): ResolvedEntrance {\n return resolveUpdate(spec.animation, {\n reducedMotion: prefersReducedMotion(),\n disabled: this.options.synchronous === true || globalThis.__GRAPHEIN_DISABLE_ANIM === true,\n });\n }\n\n /**\n * The geometry an update from `prev` to `next` should morph from \u2014 what is on\n * screen right now, including a partially-played morph \u2014 or undefined when the\n * transition shouldn't morph (different or non-cartesian types, sketch/facet/\n * debug compositions, or motion disabled).\n */\n private morphSource(prev: ChartSpec, next: ChartSpec): CartesianGeometry | undefined {\n if (prev.type !== next.type || !MORPH_TYPES.has(next.type)) return undefined;\n if (prev.debug || next.debug || isFaceted(prev) || isFaceted(next)) return undefined;\n if (resolveSketch(prev) || resolveSketch(next)) return undefined;\n if (!this.updateMotion(next).enabled) return undefined;\n if (this.morphState) return this.morphState.morph.at(this.morphState.t);\n return this.lastModel?.geometry;\n }\n\n private dispatchCustom(\n frame: FrameState,\n prepared: PreparedFrame,\n valueFrom?: number,\n compareFrom?: number,\n sparklineFrom?: number[],\n ): DispatchResult {\n const renderer = customRenderers[prepared.type];\n if (!renderer) return this.dispatchPlaceholder(frame, prepared.type);\n const ctx = this.customContext(frame, prepared);\n const interactionModel = renderer(this.surface, prepared.effectiveSpec, frame.tokens, frame.size, ctx) ?? null;\n const sliceFrom = this.pendingSliceMorph;\n this.pendingSliceMorph = undefined;\n const morphFrom = this.pendingCustomMorph;\n this.pendingCustomMorph = undefined;\n if (frame.anim.enabled) this.startCustomEntrance(frame, prepared, renderer, ctx);\n else if (sliceFrom && prepared.type === 'pie') this.startSliceMorph(frame, prepared, renderer, ctx, sliceFrom);\n else if (morphFrom !== undefined && morphFrameOf(this.surface, prepared.type) !== undefined) {\n this.startCustomMorph(frame, prepared, renderer, ctx, morphFrom);\n } else this.startValueTween(frame, prepared, renderer, ctx, valueFrom, compareFrom, sparklineFrom);\n return { interactionModel };\n }\n\n /**\n * Custom-chart update morph: the renderer re-runs each frame with the marks\n * that were on screen (`morphFrom`) and a morph progress, so bars, tiles,\n * cells, nodes and links travel to the new data. The static draw above is\n * the final frame; tween frames are transient, so reports stay on it.\n */\n private startCustomMorph(\n frame: FrameState,\n prepared: PreparedFrame,\n renderer: NonNullable<typeof customRenderers[ChartSpec['type']]>,\n ctx: RenderContext,\n morphFrom: unknown,\n ): void {\n const tween = this.updateMotion(this.currentSpec);\n if (!tween.enabled) return;\n this.entrance = runCustomRendererProgress(this.surface, renderer, prepared.effectiveSpec, frame.tokens, frame.size, {\n anim: tween, onDone: () => this.finishEntrance(), dataLength: prepared.filtered.length,\n background: this.currentSpec.background, context: ctx, progressKey: 'morphProgress',\n extraContext: { morphFrom }, transient: true, paintInitial: true, chrome: this.pendingChrome,\n });\n }\n\n /**\n * The marks a custom chart's update from `prev` to `next` should travel from\n * (including a partially-played morph), or undefined when it can't morph:\n * a type change, pie (which re-balances slices instead), sketch/debug, or\n * motion disabled. Renderers opt in by stashing their marks.\n */\n private customMorphSource(prev: ChartSpec, next: ChartSpec): unknown {\n if (prev.type !== next.type || next.type === 'pie' || CARTESIAN_TYPES.has(next.type)) return undefined;\n if (prev.debug || next.debug || resolveSketch(prev) || resolveSketch(next)) return undefined;\n // Morph frames re-run the whole renderer over both datasets' marks; large ones cross-fade.\n if ((prev.data?.length ?? 0) > CUSTOM_MORPH_ROW_LIMIT || (next.data?.length ?? 0) > CUSTOM_MORPH_ROW_LIMIT) return undefined;\n if (!this.updateMotion(next).enabled) return undefined;\n return morphFrameOf(this.surface, next.type);\n }\n\n /**\n * Re-balance pie/donut slices from the ones on screen: the renderer re-runs\n * each frame with a morph progress (the static draw above is the final frame).\n */\n private startSliceMorph(\n frame: FrameState,\n prepared: PreparedFrame,\n renderer: NonNullable<typeof customRenderers[ChartSpec['type']]>,\n ctx: RenderContext,\n sliceFrom: readonly PieSliceState[],\n ): void {\n const tween = this.updateMotion(this.currentSpec);\n if (!tween.enabled) return;\n this.entrance = runCustomRendererProgress(this.surface, renderer, prepared.effectiveSpec, frame.tokens, frame.size, {\n anim: tween, onDone: () => this.finishEntrance(), dataLength: prepared.filtered.length,\n background: this.currentSpec.background, context: ctx, progressKey: 'morphProgress',\n extraContext: { sliceFrom }, transient: true, paintInitial: true,\n });\n }\n\n /** The pie/donut slices an update from `prev` to `next` should re-balance from. */\n private sliceMorphSource(prev: ChartSpec, next: ChartSpec): readonly PieSliceState[] | undefined {\n if (prev.type !== 'pie' || next.type !== 'pie' || prev.debug || next.debug) return undefined;\n if (resolveSketch(prev) || resolveSketch(next) || !this.updateMotion(next).enabled) return undefined;\n const slices = pieStateOf(this.surface);\n return slices?.length ? slices : undefined;\n }\n\n private dispatchPlaceholder(frame: FrameState, type: ChartSpec['type']): DispatchResult {\n drawPlaceholder(this.surface, frame.tokens, `\u201C${type}\u201D renderer not yet registered`);\n if (frame.anim.enabled) this.entrance = runFadeEntrance(this.surface, frame.anim, () => this.finishEntrance());\n return { interactionModel: null };\n }\n\n private customContext(frame: FrameState, prepared: PreparedFrame): RenderContext {\n return {\n emphasis: prepared.emphasis,\n store: this.store,\n param: prepared.ownParam?.name,\n def: prepared.ownParam?.select,\n sourceData: prepared.baseData,\n framed: this.options.frame === true,\n signal: frame.frameSignal,\n requestRedraw: () => { if (!this.destroyed) this.draw(false); },\n };\n }\n\n private startCustomEntrance(frame: FrameState, prepared: PreparedFrame, renderer: NonNullable<typeof customRenderers[ChartSpec['type']]>, ctx: RenderContext): void {\n // Re-run the renderer each frame with an interpolation progress mixed into\n // its context (number roll-up / arc sweep / marks growing in). The final\n // frame is pixel-identical to the static draw above.\n const key = COUNT_UP_TYPES.has(prepared.type) ? 'valueProgress'\n : SWEEP_TYPES.has(prepared.type) ? 'sweepProgress'\n : chartDefinition(prepared.type).entrance === 'grow' ? 'entranceProgress' : null;\n if (!key) {\n this.entrance = runFadeEntrance(this.surface, frame.anim, () => this.finishEntrance());\n return;\n }\n this.entrance = runCustomRendererProgress(this.surface, renderer, prepared.effectiveSpec, frame.tokens, frame.size, {\n anim: frame.anim, onDone: () => this.finishEntrance(), dataLength: prepared.filtered.length,\n background: this.currentSpec.background, context: ctx, progressKey: key, entranceChrome: true,\n });\n }\n\n private startValueTween(\n frame: FrameState,\n prepared: PreparedFrame,\n renderer: NonNullable<typeof customRenderers[ChartSpec['type']]>,\n ctx: RenderContext,\n valueFrom?: number,\n compareFrom?: number,\n sparklineFrom?: number[],\n ): void {\n if ((valueFrom === undefined && sparklineFrom === undefined) ||\n (!COUNT_UP_TYPES.has(prepared.type) && !SWEEP_TYPES.has(prepared.type))) return;\n // Data update() on a value visual: tween the number/needle from the\n // previously-shown value to the value just drawn above, reusing the entrance\n // count-up/sweep loop. The synchronous draw already painted the final value\n // (so SSR/no-rAF/test reads stay final); the first rAF frame rolls back to\n // ~the old value and animates forward.\n const tween = this.updateMotion(this.currentSpec);\n if (!tween.enabled) return;\n const key = COUNT_UP_TYPES.has(prepared.type) ? 'valueProgress' : 'sweepProgress';\n this.entrance = runCustomRendererProgress(this.surface, renderer, prepared.effectiveSpec, frame.tokens, frame.size, {\n anim: tween, onDone: () => this.finishEntrance(), dataLength: prepared.filtered.length,\n background: this.currentSpec.background, context: ctx, progressKey: key,\n extraContext: { valueFrom, compareFrom, sparklineFrom },\n });\n }\n\n private wireInteraction(tokens: ThemeTokens, prepared: PreparedFrame, result: DispatchResult): void {\n if (!this.interaction) this.interaction = new InteractionController(this.surface, tokens);\n this.interaction.setModel(result.interactionModel, tokens);\n const canPick = prepared.ownParam && result.interactionModel?.pick;\n const canLegend = result.legendSelect && result.interactionModel?.legendHits?.length;\n if (!canPick && !canLegend) return this.interaction.setSelect(null);\n // Wire click/tap selection when this chart defines a param and its model can\n // resolve a pick. Slicers publish via the render context instead.\n const cfg: SelectConfig | null = prepared.ownParam\n ? { store: this.store, param: prepared.ownParam.name, def: prepared.ownParam.select } : null;\n this.interaction.setSelect({\n onPick: cfg && result.interactionModel?.pick ? (value) => applyPick(cfg, value) : undefined,\n onLegendToggle: result.legendSelect ? (hit, event) => publishLegendToggle(\n this.store, result.legendSelect!.cfg, result.legendSelect!.hits, hit, event.shiftKey || event.altKey) : undefined,\n });\n }\n\n private finishFrame(frame: FrameState, prepared: PreparedFrame, result: DispatchResult): void {\n applyA11y(this.surface, this.currentSpec);\n this.inspector?.write(this.currentSpec);\n // Derive the machine-readable render report from the resolved model. Pure\n // (reads the model + theme, never the canvas), so it works headlessly too.\n this.refreshReport = () => result.report ?? buildRenderReport({\n type: prepared.type, spec: this.currentSpec, data: prepared.filtered,\n tokens: frame.tokens, size: frame.size, model: result.reportModel,\n labels: this.surface.labels.records, suppressedLabels: this.surface.labels.suppressed,\n evidence: this.surface.evidence.snapshot(),\n });\n this.lastReport = this.refreshReport();\n // Animated entrances signal ready on their final frame; everything else now.\n if (!this.entrance) signalReady(this.surface);\n // If text was measured with fallback metrics (web font still loading), arm a\n // one-shot corrective redraw for when the real font arrives.\n this.armFontRefresh();\n // Sketch charts use a bundled handwriting font that loads lazily; once it's\n // ready, redraw so text is laid out with its real glyph metrics.\n this.armSketchFont();\n this.armDprRefresh();\n }\n\n private finishEntrance(): void {\n // Entrance completion: mark ready, then apply any font-load correction that\n // was deferred so it wouldn't interrupt the animation.\n if (this.refreshReport) this.lastReport = this.refreshReport();\n signalReady(this.surface);\n this.interaction?.refresh();\n if (this.pendingFontRefresh && !this.destroyed) {\n this.pendingFontRefresh = false;\n this.draw(false);\n }\n }\n\n private armFontRefresh(): void {\n // Self-healing layout: a chart drawn before its web font loads is measured\n // with fallback metrics. Listen once for the font and redraw with real\n // metrics. If an entrance is mid-flight, defer the redraw to its completion\n // to avoid a snap.\n if (this.fontRefreshArmed || !fontsLoading()) return;\n this.fontRefreshArmed = true;\n onFontsReady(() => {\n this.fontRefreshArmed = false;\n if (this.destroyed) return;\n if (this.entrance) this.pendingFontRefresh = true;\n else this.draw(false);\n });\n }\n\n private armSketchFont(): void {\n // The sketch font is bundled and loads lazily (data URL, no network). When it\n // first becomes available, redraw once so handwriting metrics replace the\n // fallback ones. `ensureSketchFont` resolves `true` only on the load that\n // actually injected it, so this never loops.\n if (this.sketchFontArmed || !resolveSketch(this.currentSpec)?.font) return;\n this.sketchFontArmed = true;\n void ensureSketchFont().then((loaded) => { if (loaded && !this.destroyed) this.draw(false); });\n }\n\n private armDprRefresh(): void {\n if (typeof globalThis.matchMedia !== 'function') return;\n this.clearDprRefresh();\n const query = globalThis.matchMedia(`(resolution: ${this.lastDpr}dppx)`);\n const listener = () => {\n if (this.destroyed) return;\n if (getDevicePixelRatio() !== this.lastDpr) this.draw(false);\n else this.armDprRefresh();\n };\n this.dprQuery = query;\n this.dprQueryListener = listener;\n if (typeof query.addEventListener === 'function') query.addEventListener('change', listener);\n else query.addListener?.(listener);\n }\n\n private clearDprRefresh(): void {\n if (!this.dprQuery || !this.dprQueryListener) return;\n if (typeof this.dprQuery.removeEventListener === 'function') {\n this.dprQuery.removeEventListener('change', this.dprQueryListener);\n } else this.dprQuery.removeListener?.(this.dprQueryListener);\n this.dprQuery = undefined;\n this.dprQueryListener = undefined;\n }\n\n private setupResizeObserver(): void {\n const auto = this.currentSpec.dimensions?.autoResize ??\n (this.currentSpec.dimensions?.width == null || this.currentSpec.dimensions?.height == null);\n if (!auto || typeof ResizeObserver === 'undefined') return;\n // Redraw on container resize, but only when the measured size or DPR actually\n // diverges from what we last drew. That skips the redundant delivery the\n // observer fires on observe() while still honoring a resize that lands before\n // the first delivery \u2014 e.g. a dashboard reflow. Resizes never animate.\n this.observer = new ResizeObserver(() => {\n if (this.destroyed) return;\n const s = resolveSize(this.container, this.currentSpec);\n if (s.width === this.lastDrawnW && s.height === this.lastDrawnH && getDevicePixelRatio() === this.lastDpr) return;\n this.draw(false);\n });\n this.observer.observe(this.container);\n }\n\n update(next: ChartSpec): void {\n if (this.destroyed) return;\n this.updateTransition?.cancel();\n this.updateTransition = undefined;\n this.pendingSelectionRedraw = false;\n this.selectionRedrawQueued = false;\n this.invalidateTransforms();\n this.seedParams(next);\n // Marks morph from what is on screen: cartesian bars grow and slide, lines\n // reshape and points glide; pie slices re-balance; custom charts that stash\n // keyed marks (funnel stages, waterfall bars, treemap tiles, heatmap cells,\n // sankey nodes and links, \u2026) travel to their new geometry and colors.\n // Anything that can't morph falls back to a cross-fade of the marks layer:\n // both the outgoing and incoming chart must be canvas-mark kinds, motion\n // must be enabled, and the surface size must be unchanged (a dimension\n // change is a resize, not a data morph \u2014 those snap to avoid a stretched\n // bitmap).\n const prevType = this.currentSpec.type;\n const morphFrom = this.morphSource(this.currentSpec, next);\n const sliceFrom = this.sliceMorphSource(this.currentSpec, next);\n const customFrom = this.customMorphSource(this.currentSpec, next);\n const before = this.updateSnapshot(prevType, next);\n const prevW = this.surface.width;\n const prevH = this.surface.height;\n // Value visuals (kpi/gauge) aren't canvas-mark kinds, so instead of a\n // bitmap cross-fade we roll the number / sweep the needle from the value the\n // last draw showed to the new one. Needs the same value type on both sides\n // and a real previous value; draw() gates the actual motion on resolveUpdate\n // (reduced-motion / screenshot kill-switch \u2192 snaps).\n const prev = { value: this.lastValue, compare: this.lastCompare, sparkline: this.lastSparkline };\n this.currentSpec = next;\n const wantValue = prevType === next.type && (COUNT_UP_TYPES.has(next.type) || SWEEP_TYPES.has(next.type)) && prev.value != null;\n // A KPI can morph its sparkline into the new shape even when the numeric\n // value itself is unavailable (shows \"\u2014\"), so drive that off the previous\n // series independently of the value roll-up.\n const wantSparkline = prevType === next.type && next.type === 'kpi' && !!prev.sparkline?.length;\n this.pendingMorph = morphFrom;\n this.pendingSliceMorph = sliceFrom;\n this.pendingCustomMorph = customFrom;\n this.pendingChrome = captureChrome(this.surface);\n try {\n this.draw(false, wantValue ? (prev.value ?? undefined) : undefined,\n wantValue ? (prev.compare ?? undefined) : undefined,\n wantValue || wantSparkline ? (prev.sparkline ?? undefined) : undefined);\n } finally {\n this.pendingMorph = undefined;\n this.pendingSliceMorph = undefined;\n this.pendingCustomMorph = undefined;\n this.pendingChrome = undefined;\n }\n // A morph, slice re-balance or custom-mark morph replaces the cross-fade.\n if (!this.morphState && !this.entrance) this.startUpdateCrossfade(before, prevW, prevH, next);\n }\n\n private updateSnapshot(prevType: ChartSpec['type'], next: ChartSpec): HTMLCanvasElement | undefined {\n const wantFade = this.updateMotion(next).enabled && CANVAS_MARK_TYPES.has(prevType) && CANVAS_MARK_TYPES.has(next.type);\n return wantFade ? snapshotLayer(this.surface.marks) : undefined;\n }\n\n private startUpdateCrossfade(before: HTMLCanvasElement | undefined, prevW: number, prevH: number, next: ChartSpec): void {\n if (!before || this.surface.width !== prevW || this.surface.height !== prevH ||\n this.surface.marks.canvas.width !== before.width || this.surface.marks.canvas.height !== before.height) return;\n this.updateTransition = runUpdateCrossfade(this.surface, before, this.updateMotion(next));\n }\n\n resize(): void {\n if (!this.destroyed) this.draw(false);\n }\n\n report(): RenderReport {\n this.flushSelectionRedraw();\n if (!this.destroyed) {\n this.surface.collectEvidence?.();\n if (this.refreshReport) this.lastReport = this.refreshReport();\n }\n return this.lastReport ?? this.emptyReport();\n }\n\n private emptyReport(): RenderReport {\n return {\n type: this.currentSpec.type,\n size: resolveSize(this.container, this.currentSpec),\n markCount: 0, seriesCount: 0, colorCount: 0, ok: false,\n diagnostics: [{ code: 'render-evidence-incomplete', severity: 'warning',\n message: 'No completed draw evidence is available yet.' }],\n evidence: this.surface.evidence.snapshot(),\n };\n }\n\n getSelection(name?: string): SelectionValue | null | Record<string, SelectionValue | null> {\n this.flushSelectionRedraw();\n return name === undefined ? this.store.all() : this.store.get(name);\n }\n\n setSelection(name: string, value: SelectionValue | null): void {\n if (!this.destroyed) this.store.set(name, value);\n }\n\n clearSelection(name?: string): void {\n if (!this.destroyed) this.store.clear(name);\n }\n\n private onSelection(listener: SelectionChangeListener): () => void {\n this.hostListeners.add(listener);\n return () => this.hostListeners.delete(listener);\n }\n\n private handleSelectionChange(name: string, value: SelectionValue | null): void {\n for (const listener of [...this.hostListeners]) listener(name, value);\n if (this.destroyed) return;\n if (dependentParams(this.currentSpec.highlight, this.currentSpec.filter).has(name) ||\n specLegendParam(this.currentSpec) === name) this.scheduleSelectionRedraw();\n }\n\n private scheduleSelectionRedraw(): void {\n if (this.destroyed) return;\n this.pendingSelectionRedraw = true;\n if (this.options.synchronous === true) return this.flushSelectionRedraw();\n if (this.selectionRedrawQueued) return;\n this.selectionRedrawQueued = true;\n queueMicrotask(() => this.flushSelectionRedraw());\n }\n\n private flushSelectionRedraw(): void {\n if (!this.pendingSelectionRedraw || this.destroyed) return;\n this.pendingSelectionRedraw = false;\n this.selectionRedrawQueued = false;\n // Cross-filters, highlights and legend toggles morph from what's on screen,\n // so dashboards re-flow fluidly instead of snapping.\n this.pendingMorph = this.morphSource(this.currentSpec, this.currentSpec);\n this.pendingSliceMorph = this.sliceMorphSource(this.currentSpec, this.currentSpec);\n this.pendingCustomMorph = this.customMorphSource(this.currentSpec, this.currentSpec);\n this.pendingChrome = captureChrome(this.surface);\n try {\n this.draw(false);\n } finally {\n this.pendingMorph = undefined;\n this.pendingSliceMorph = undefined;\n this.pendingCustomMorph = undefined;\n this.pendingChrome = undefined;\n }\n }\n\n private applyExternalEdit(config: Record<string, unknown>): void {\n if (this.destroyed) return;\n // External DOM edits are config-only; merge them with in-memory data and\n // ignore invalid partial edits so the last good render remains intact.\n const merged = { ...config, data: this.currentSpec.data } as ChartSpec;\n if (validateSpec(merged).errors.length > 0) return;\n this.update(merged);\n }\n\n private seedParams(spec: ChartSpec): void {\n for (const param of spec.params ?? []) {\n if (param.value !== undefined && this.store.get(param.name) == null) {\n this.store.set(param.name, param.value ?? null);\n }\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.unsubscribe();\n this.hostListeners.clear();\n this.entrance?.cancel();\n this.updateTransition?.cancel();\n this.frameController?.abort('destroy');\n this.frameController = undefined;\n this.clearDprRefresh();\n this.observer?.disconnect();\n this.inspector?.destroy();\n this.interaction?.destroy();\n try { this.preview?.destroy(); } finally { this.surface.destroy(); }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dashboardDom.d.ts","sourceRoot":"","sources":["../../src/runtime/dashboardDom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,mBAAmB,CAAC;AA2BtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAiB7E,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,WAAW,CAOnF;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,WAAW,EACtB,IAAI,EAAE,aAAa,EACnB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,iBAAiB,CAGnB"}
1
+ {"version":3,"file":"dashboardDom.d.ts","sourceRoot":"","sources":["../../src/runtime/dashboardDom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,mBAAmB,CAAC;AA2BtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAkC7E,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,WAAW,CAOnF;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,WAAW,EACtB,IAAI,EAAE,aAAa,EACnB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,iBAAiB,CAGnB"}
@@ -23,6 +23,16 @@ import {
23
23
  resolveDashboardSections
24
24
  } from "./dashboardPlacement.js";
25
25
  import { coalescedStore, SourceCellRegistry } from "./dashboardSelection.js";
26
+ function dashboardStructureKey(spec) {
27
+ const { data: _data, views, ...page } = spec;
28
+ return JSON.stringify({
29
+ ...page,
30
+ views: views.map(({ spec: view, ...card }) => {
31
+ const slicer = view;
32
+ return { ...card, type: view.type, params: view.params, field: slicer.field, param: slicer.param };
33
+ })
34
+ });
35
+ }
26
36
  function resolveDashboardContainer(target) {
27
37
  if (typeof target === "string") {
28
38
  const el = document.querySelector(target);
@@ -49,6 +59,9 @@ class DashboardRuntime {
49
59
  __publicField(this, "chrome", []);
50
60
  __publicField(this, "hostListeners", /* @__PURE__ */ new Set());
51
61
  __publicField(this, "sourceCells", new SourceCellRegistry());
62
+ // Mounts still waiting for their host to become visible (collapsed sections,
63
+ // hidden breakpoints); in-place updates retarget them at the latest view spec.
64
+ __publicField(this, "deferred", []);
52
65
  __publicField(this, "root");
53
66
  __publicField(this, "resizeObs");
54
67
  // Publishes the dashboard config to the DOM and rebuilds on external edits.
@@ -95,6 +108,7 @@ class DashboardRuntime {
95
108
  },
96
109
  update: (next) => {
97
110
  if (this.destroyed) return;
111
+ if (this.updateInPlace(next)) return;
98
112
  this.teardown();
99
113
  this.currentSpec = next;
100
114
  this.build();
@@ -114,10 +128,39 @@ class DashboardRuntime {
114
128
  const wired = wireViews(this.currentSpec.views, this.currentSpec.interactions ?? "auto");
115
129
  const { stripViews, gridViews } = partitionDashboardViews(wired, { ...state.layout, navigators: state.layout.navigators ?? "top" });
116
130
  const deferred = [];
131
+ this.deferred = deferred;
117
132
  const groups = this.appendContent(stripViews, gridViews, state, deferred);
118
133
  this.attachAndLayout(state, groups, deferred);
119
134
  this.installInspector();
120
135
  }
136
+ /**
137
+ * Apply `next` to the live page when only data or view specs changed: every
138
+ * mounted view is updated in place, so its marks morph, its numbers roll, and
139
+ * its values tween — instead of the whole page being rebuilt and every view
140
+ * replaying its entrance. Every view gets its newly wired spec (rows may have
141
+ * been edited in place, and a peer's change can rewire its filters); unchanged
142
+ * frames morph invisibly. Returns false when the page must be rebuilt: its
143
+ * structure changed, or a view failed to update (the rebuild reports it).
144
+ */
145
+ updateInPlace(next) {
146
+ if (!this.root || this.mountErrors.length > 0) return false;
147
+ if (dashboardStructureKey(next) !== dashboardStructureKey(this.currentSpec)) return false;
148
+ this.currentSpec = next;
149
+ const tokens = resolveTheme(next.theme);
150
+ const wired = wireViews(next.views, next.interactions ?? "auto");
151
+ const byId = new Map(wired.map((view) => [view.id, view]));
152
+ for (const pending of this.deferred) pending.view = byId.get(pending.view.id) ?? pending.view;
153
+ try {
154
+ for (const mountedView of this.mounted) {
155
+ const view = byId.get(mountedView.id);
156
+ if (view) mountedView.instance.update(inheritInto(view.spec, next, tokens, !!(view.title || view.subtitle)));
157
+ }
158
+ } catch {
159
+ return false;
160
+ }
161
+ this.dashboardInspector?.write(next);
162
+ return true;
163
+ }
121
164
  createBuildState() {
122
165
  const tokens = resolveTheme(this.currentSpec.theme);
123
166
  const layout = resolveDashboardLayout(this.currentSpec.layout);
@@ -492,6 +535,7 @@ class DashboardRuntime {
492
535
  if (this.destroyed) return;
493
536
  const merged = { ...config, data: this.currentSpec.data };
494
537
  if (validateSpec(merged).errors.length > 0) return;
538
+ if (this.updateInPlace(merged)) return;
495
539
  this.teardown();
496
540
  this.currentSpec = merged;
497
541
  this.build();
@@ -573,6 +617,7 @@ class DashboardRuntime {
573
617
  this.mountErrors.length = 0;
574
618
  this.layoutDiagnostics.length = 0;
575
619
  this.chrome.length = 0;
620
+ this.deferred = [];
576
621
  if (this.root?.parentNode) this.root.parentNode.removeChild(this.root);
577
622
  this.root = void 0;
578
623
  this.sourceCells.clear();