graphein 0.20.0 → 0.21.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.
- package/dist/animation/animate.d.ts +6 -1
- package/dist/animation/animate.d.ts.map +1 -1
- package/dist/animation/animate.js +2 -2
- package/dist/animation/animate.js.map +2 -2
- package/dist/animation/env.d.ts +5 -0
- package/dist/animation/env.d.ts.map +1 -1
- package/dist/animation/env.js +4 -0
- package/dist/animation/env.js.map +2 -2
- package/dist/animation/index.d.ts +1 -0
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/animation/index.js +1 -0
- package/dist/animation/index.js.map +2 -2
- package/dist/animation/stagger.d.ts +13 -0
- package/dist/animation/stagger.d.ts.map +1 -0
- package/dist/animation/stagger.js +13 -0
- package/dist/animation/stagger.js.map +7 -0
- package/dist/axes/draw.d.ts +5 -1
- package/dist/axes/draw.d.ts.map +1 -1
- package/dist/axes/draw.js +13 -1
- package/dist/axes/draw.js.map +2 -2
- package/dist/axes/morph.d.ts +111 -0
- package/dist/axes/morph.d.ts.map +1 -0
- package/dist/axes/morph.js +207 -0
- package/dist/axes/morph.js.map +7 -0
- package/dist/axes/overlay.d.ts.map +1 -1
- package/dist/axes/overlay.js +88 -25
- package/dist/axes/overlay.js.map +2 -2
- package/dist/axes/text.d.ts +2 -0
- package/dist/axes/text.d.ts.map +1 -1
- package/dist/axes/text.js +1 -0
- package/dist/axes/text.js.map +2 -2
- package/dist/axes/tickLabels.d.ts +2 -0
- package/dist/axes/tickLabels.d.ts.map +1 -1
- package/dist/axes/tickLabels.js +2 -2
- package/dist/axes/tickLabels.js.map +2 -2
- package/dist/charts/annotations.d.ts +9 -3
- package/dist/charts/annotations.d.ts.map +1 -1
- package/dist/charts/annotations.js +82 -27
- package/dist/charts/annotations.js.map +2 -2
- package/dist/charts/area.d.ts +37 -1
- package/dist/charts/area.d.ts.map +1 -1
- package/dist/charts/area.js +35 -17
- package/dist/charts/area.js.map +2 -2
- package/dist/charts/bar.d.ts +53 -0
- package/dist/charts/bar.d.ts.map +1 -1
- package/dist/charts/bar.js +117 -83
- package/dist/charts/bar.js.map +2 -2
- package/dist/charts/box.d.ts +31 -0
- package/dist/charts/box.d.ts.map +1 -1
- package/dist/charts/box.js +93 -70
- package/dist/charts/box.js.map +2 -2
- package/dist/charts/bubbleMap.d.ts +20 -0
- package/dist/charts/bubbleMap.d.ts.map +1 -0
- package/dist/charts/bubbleMap.js +951 -0
- package/dist/charts/bubbleMap.js.map +7 -0
- package/dist/charts/bullet.d.ts.map +1 -1
- package/dist/charts/bullet.js +69 -51
- package/dist/charts/bullet.js.map +2 -2
- package/dist/charts/calendarHeatmap.d.ts.map +1 -1
- package/dist/charts/calendarHeatmap.js +56 -19
- package/dist/charts/calendarHeatmap.js.map +2 -2
- package/dist/charts/candlestick.d.ts +40 -0
- package/dist/charts/candlestick.d.ts.map +1 -0
- package/dist/charts/candlestick.js +325 -0
- package/dist/charts/candlestick.js.map +7 -0
- package/dist/charts/choropleth.d.ts.map +1 -1
- package/dist/charts/choropleth.js +46 -67
- package/dist/charts/choropleth.js.map +2 -2
- package/dist/charts/combo.d.ts.map +1 -1
- package/dist/charts/combo.js +127 -27
- package/dist/charts/combo.js.map +3 -3
- package/dist/charts/dumbbell.d.ts.map +1 -1
- package/dist/charts/dumbbell.js +100 -31
- package/dist/charts/dumbbell.js.map +2 -2
- package/dist/charts/funnel.d.ts.map +1 -1
- package/dist/charts/funnel.js +93 -28
- package/dist/charts/funnel.js.map +3 -3
- package/dist/charts/gantt.d.ts +22 -0
- package/dist/charts/gantt.d.ts.map +1 -0
- package/dist/charts/gantt.js +564 -0
- package/dist/charts/gantt.js.map +7 -0
- package/dist/charts/gauge.d.ts.map +1 -1
- package/dist/charts/gauge.js +30 -4
- package/dist/charts/gauge.js.map +2 -2
- package/dist/charts/geo.d.ts +87 -0
- package/dist/charts/geo.d.ts.map +1 -0
- package/dist/charts/geo.js +140 -0
- package/dist/charts/geo.js.map +7 -0
- package/dist/charts/geometry.d.ts +20 -0
- package/dist/charts/geometry.d.ts.map +1 -0
- package/dist/charts/geometry.js +25 -0
- package/dist/charts/geometry.js.map +7 -0
- package/dist/charts/heatmap.d.ts.map +1 -1
- package/dist/charts/heatmap.js +58 -49
- package/dist/charts/heatmap.js.map +2 -2
- package/dist/charts/histogram.d.ts +1 -1
- package/dist/charts/histogram.d.ts.map +1 -1
- package/dist/charts/histogram.js +49 -31
- package/dist/charts/histogram.js.map +2 -2
- package/dist/charts/index.d.ts +35 -1
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +12 -0
- package/dist/charts/index.js.map +2 -2
- package/dist/charts/legibility.d.ts +38 -0
- package/dist/charts/legibility.d.ts.map +1 -0
- package/dist/charts/legibility.js +72 -0
- package/dist/charts/legibility.js.map +7 -0
- package/dist/charts/line.d.ts +39 -1
- package/dist/charts/line.d.ts.map +1 -1
- package/dist/charts/line.js +48 -16
- package/dist/charts/line.js.map +2 -2
- package/dist/charts/morphFrame.d.ts +83 -0
- package/dist/charts/morphFrame.d.ts.map +1 -0
- package/dist/charts/morphFrame.js +128 -0
- package/dist/charts/morphFrame.js.map +7 -0
- package/dist/charts/pie.d.ts.map +1 -1
- package/dist/charts/pie.js +89 -26
- package/dist/charts/pie.js.map +2 -2
- package/dist/charts/pieState.d.ts +27 -0
- package/dist/charts/pieState.d.ts.map +1 -0
- package/dist/charts/pieState.js +55 -0
- package/dist/charts/pieState.js.map +7 -0
- package/dist/charts/radar.d.ts +62 -0
- package/dist/charts/radar.d.ts.map +1 -0
- package/dist/charts/radar.js +912 -0
- package/dist/charts/radar.js.map +7 -0
- package/dist/charts/radialBar.d.ts +60 -0
- package/dist/charts/radialBar.d.ts.map +1 -0
- package/dist/charts/radialBar.js +708 -0
- package/dist/charts/radialBar.js.map +7 -0
- package/dist/charts/sankey.d.ts.map +1 -1
- package/dist/charts/sankey.js +223 -57
- package/dist/charts/sankey.js.map +3 -3
- package/dist/charts/scatter.d.ts +31 -0
- package/dist/charts/scatter.d.ts.map +1 -1
- package/dist/charts/scatter.js +48 -12
- package/dist/charts/scatter.js.map +2 -2
- package/dist/charts/slope.d.ts.map +1 -1
- package/dist/charts/slope.js +55 -3
- package/dist/charts/slope.js.map +2 -2
- package/dist/charts/sunburst.d.ts +14 -0
- package/dist/charts/sunburst.d.ts.map +1 -0
- package/dist/charts/sunburst.js +885 -0
- package/dist/charts/sunburst.js.map +7 -0
- package/dist/charts/treemap.d.ts.map +1 -1
- package/dist/charts/treemap.js +177 -68
- package/dist/charts/treemap.js.map +3 -3
- package/dist/charts/trendline.d.ts +13 -5
- package/dist/charts/trendline.d.ts.map +1 -1
- package/dist/charts/trendline.js +205 -56
- package/dist/charts/trendline.js.map +2 -2
- package/dist/charts/waterfall.d.ts.map +1 -1
- package/dist/charts/waterfall.js +76 -5
- package/dist/charts/waterfall.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interaction/cartesian.d.ts +4 -1
- package/dist/interaction/cartesian.d.ts.map +1 -1
- package/dist/interaction/cartesian.js +104 -34
- package/dist/interaction/cartesian.js.map +2 -2
- package/dist/interaction/controller.d.ts +29 -1
- package/dist/interaction/controller.d.ts.map +1 -1
- package/dist/interaction/controller.js +131 -8
- package/dist/interaction/controller.js.map +2 -2
- package/dist/interaction/focus.d.ts +23 -0
- package/dist/interaction/focus.d.ts.map +1 -0
- package/dist/interaction/focus.js +65 -0
- package/dist/interaction/focus.js.map +7 -0
- package/dist/interaction/tooltip.d.ts +6 -0
- package/dist/interaction/tooltip.d.ts.map +1 -1
- package/dist/interaction/tooltip.js +41 -16
- package/dist/interaction/tooltip.js.map +2 -2
- package/dist/interaction/types.d.ts +19 -0
- package/dist/interaction/types.d.ts.map +1 -1
- package/dist/interaction/veil.d.ts +25 -0
- package/dist/interaction/veil.d.ts.map +1 -0
- package/dist/interaction/veil.js +35 -0
- package/dist/interaction/veil.js.map +7 -0
- package/dist/render/chromeMotion.d.ts +65 -0
- package/dist/render/chromeMotion.d.ts.map +1 -0
- package/dist/render/chromeMotion.js +79 -0
- package/dist/render/chromeMotion.js.map +7 -0
- package/dist/render/pathSample.d.ts +24 -0
- package/dist/render/pathSample.d.ts.map +1 -0
- package/dist/render/pathSample.js +76 -0
- package/dist/render/pathSample.js.map +7 -0
- package/dist/render/transient.d.ts +18 -0
- package/dist/render/transient.d.ts.map +1 -0
- package/dist/render/transient.js +19 -0
- package/dist/render/transient.js.map +7 -0
- package/dist/runtime/candlestick.d.ts +112 -0
- package/dist/runtime/candlestick.d.ts.map +1 -0
- package/dist/runtime/candlestick.js +531 -0
- package/dist/runtime/candlestick.js.map +7 -0
- package/dist/runtime/cartesian.d.ts +14 -3
- package/dist/runtime/cartesian.d.ts.map +1 -1
- package/dist/runtime/cartesian.js.map +2 -2
- package/dist/runtime/chartAnimation.d.ts +54 -7
- package/dist/runtime/chartAnimation.d.ts.map +1 -1
- package/dist/runtime/chartAnimation.js +146 -28
- package/dist/runtime/chartAnimation.js.map +2 -2
- package/dist/runtime/chartRuntime.d.ts +42 -0
- package/dist/runtime/chartRuntime.d.ts.map +1 -1
- package/dist/runtime/chartRuntime.js +196 -30
- package/dist/runtime/chartRuntime.js.map +2 -2
- package/dist/runtime/dashboardDom.d.ts.map +1 -1
- package/dist/runtime/dashboardDom.js +45 -0
- package/dist/runtime/dashboardDom.js.map +2 -2
- package/dist/runtime/facet.d.ts +1 -1
- package/dist/runtime/facet.d.ts.map +1 -1
- package/dist/runtime/gantt.d.ts +137 -0
- package/dist/runtime/gantt.d.ts.map +1 -0
- package/dist/runtime/gantt.js +647 -0
- package/dist/runtime/gantt.js.map +7 -0
- package/dist/runtime/morph.d.ts +33 -0
- package/dist/runtime/morph.d.ts.map +1 -0
- package/dist/runtime/morph.js +332 -0
- package/dist/runtime/morph.js.map +7 -0
- package/dist/runtime/radar.d.ts +75 -0
- package/dist/runtime/radar.d.ts.map +1 -0
- package/dist/runtime/radar.js +201 -0
- package/dist/runtime/radar.js.map +7 -0
- package/dist/runtime/radialBar.d.ts +81 -0
- package/dist/runtime/radialBar.d.ts.map +1 -0
- package/dist/runtime/radialBar.js +125 -0
- package/dist/runtime/radialBar.js.map +7 -0
- package/dist/runtime/report/constants.d.ts +2 -2
- package/dist/runtime/report/constants.d.ts.map +1 -1
- package/dist/runtime/runtimeShared.d.ts +3 -3
- package/dist/runtime/runtimeShared.d.ts.map +1 -1
- package/dist/runtime/sunburst.d.ts +74 -0
- package/dist/runtime/sunburst.d.ts.map +1 -0
- package/dist/runtime/sunburst.js +150 -0
- package/dist/runtime/sunburst.js.map +7 -0
- package/dist/shape/arc.d.ts +15 -2
- package/dist/shape/arc.d.ts.map +1 -1
- package/dist/shape/arc.js +204 -32
- package/dist/shape/arc.js.map +2 -2
- package/dist/spec/chartDefinitions.d.ts +6 -0
- package/dist/spec/chartDefinitions.d.ts.map +1 -1
- package/dist/spec/chartDefinitions.js +7 -1
- package/dist/spec/chartDefinitions.js.map +2 -2
- package/dist/spec/templates.d.ts.map +1 -1
- package/dist/spec/templates.js +175 -0
- package/dist/spec/templates.js.map +2 -2
- package/dist/spec/types.d.ts +200 -5
- package/dist/spec/types.d.ts.map +1 -1
- package/dist/spec/types.js +6 -0
- package/dist/spec/types.js.map +2 -2
- package/dist/spec/validate/charts.js +97 -1
- package/dist/spec/validate/charts.js.map +2 -2
- package/dist/spec/validate/common.d.ts +6 -0
- package/dist/spec/validate/common.d.ts.map +1 -1
- package/dist/spec/validate/overlays.js +2 -2
- package/dist/spec/validate/overlays.js.map +2 -2
- package/dist/spec/validate.data.d.ts.map +1 -1
- package/dist/spec/validate.data.js +5 -2
- package/dist/spec/validate.data.js.map +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export interface AnimateOptions {
|
|
2
2
|
duration: number;
|
|
3
3
|
easing?: (t: number) => number;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Called each frame with the eased progress and the raw (linear) clock. Eased
|
|
6
|
+
* progress may pass 1 mid-flight with overshooting easings; `raw` reaches 1
|
|
7
|
+
* only on the final frame.
|
|
8
|
+
*/
|
|
9
|
+
onUpdate: (t: number, raw: number) => void;
|
|
5
10
|
onComplete?: () => void;
|
|
6
11
|
now?: () => number;
|
|
7
12
|
raf?: (cb: (t: number) => void) => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animate.d.ts","sourceRoot":"","sources":["../../src/animation/animate.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"animate.d.ts","sourceRoot":"","sources":["../../src/animation/animate.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,CAAC;IAC1C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,IAAI,IAAI,CAAC;CAChB;AA2BD,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAmD7D"}
|
|
@@ -21,7 +21,7 @@ function clamp01(value) {
|
|
|
21
21
|
function animate(opts) {
|
|
22
22
|
const easing = opts.easing ?? linear;
|
|
23
23
|
if (opts.duration <= 0) {
|
|
24
|
-
opts.onUpdate(easing(1));
|
|
24
|
+
opts.onUpdate(easing(1), 1);
|
|
25
25
|
opts.onComplete?.();
|
|
26
26
|
return {
|
|
27
27
|
cancel() {
|
|
@@ -41,7 +41,7 @@ function animate(opts) {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
const rawT = clamp01((now() - start) / opts.duration);
|
|
44
|
-
opts.onUpdate(easing(rawT));
|
|
44
|
+
opts.onUpdate(easing(rawT), rawT);
|
|
45
45
|
if (rawT >= 1) {
|
|
46
46
|
completed = true;
|
|
47
47
|
opts.onComplete?.();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/animation/animate.ts"],
|
|
4
|
-
"sourcesContent": ["import { linear } from './easing';\n\nexport interface AnimateOptions {\n duration: number;\n easing?: (t: number) => number;\n onUpdate: (t: number) => void;\n onComplete?: () => void;\n now?: () => number;\n raf?: (cb: (t: number) => void) => number;\n cancelRaf?: (handle: number) => void;\n}\n\nexport interface AnimationHandle {\n cancel(): void;\n}\n\nfunction defaultNow(): number {\n return globalThis.performance?.now() ?? Date.now();\n}\n\nfunction defaultRaf(cb: (t: number) => void): number {\n if (globalThis.requestAnimationFrame !== undefined) {\n return globalThis.requestAnimationFrame(cb);\n }\n\n return globalThis.setTimeout(() => cb(defaultNow()), 16) as unknown as number;\n}\n\nfunction defaultCancelRaf(handle: number): void {\n if (globalThis.cancelAnimationFrame !== undefined) {\n globalThis.cancelAnimationFrame(handle);\n return;\n }\n\n globalThis.clearTimeout(handle);\n}\n\nfunction clamp01(value: number): number {\n return Math.min(1, Math.max(0, value));\n}\n\nexport function animate(opts: AnimateOptions): AnimationHandle {\n const easing = opts.easing ?? linear;\n\n if (opts.duration <= 0) {\n opts.onUpdate(easing(1));\n opts.onComplete?.();\n return {\n cancel(): void {\n return;\n },\n };\n }\n\n const now = opts.now ?? defaultNow;\n const raf = opts.raf ?? defaultRaf;\n const cancelRaf = opts.cancelRaf ?? defaultCancelRaf;\n const start = now();\n let cancelled = false;\n let completed = false;\n let frame: number | undefined;\n\n const step = (): void => {\n if (cancelled || completed) {\n return;\n }\n\n const rawT = clamp01((now() - start) / opts.duration);\n opts.onUpdate(easing(rawT));\n\n if (rawT >= 1) {\n completed = true;\n opts.onComplete?.();\n return;\n }\n\n frame = raf(step);\n };\n\n frame = raf(step);\n\n return {\n cancel(): void {\n if (cancelled || completed) {\n return;\n }\n cancelled = true;\n if (frame !== undefined) {\n cancelRaf(frame);\n }\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,cAAc;
|
|
4
|
+
"sourcesContent": ["import { linear } from './easing';\n\nexport interface AnimateOptions {\n duration: number;\n easing?: (t: number) => number;\n /**\n * Called each frame with the eased progress and the raw (linear) clock. Eased\n * progress may pass 1 mid-flight with overshooting easings; `raw` reaches 1\n * only on the final frame.\n */\n onUpdate: (t: number, raw: number) => void;\n onComplete?: () => void;\n now?: () => number;\n raf?: (cb: (t: number) => void) => number;\n cancelRaf?: (handle: number) => void;\n}\n\nexport interface AnimationHandle {\n cancel(): void;\n}\n\nfunction defaultNow(): number {\n return globalThis.performance?.now() ?? Date.now();\n}\n\nfunction defaultRaf(cb: (t: number) => void): number {\n if (globalThis.requestAnimationFrame !== undefined) {\n return globalThis.requestAnimationFrame(cb);\n }\n\n return globalThis.setTimeout(() => cb(defaultNow()), 16) as unknown as number;\n}\n\nfunction defaultCancelRaf(handle: number): void {\n if (globalThis.cancelAnimationFrame !== undefined) {\n globalThis.cancelAnimationFrame(handle);\n return;\n }\n\n globalThis.clearTimeout(handle);\n}\n\nfunction clamp01(value: number): number {\n return Math.min(1, Math.max(0, value));\n}\n\nexport function animate(opts: AnimateOptions): AnimationHandle {\n const easing = opts.easing ?? linear;\n\n if (opts.duration <= 0) {\n opts.onUpdate(easing(1), 1);\n opts.onComplete?.();\n return {\n cancel(): void {\n return;\n },\n };\n }\n\n const now = opts.now ?? defaultNow;\n const raf = opts.raf ?? defaultRaf;\n const cancelRaf = opts.cancelRaf ?? defaultCancelRaf;\n const start = now();\n let cancelled = false;\n let completed = false;\n let frame: number | undefined;\n\n const step = (): void => {\n if (cancelled || completed) {\n return;\n }\n\n const rawT = clamp01((now() - start) / opts.duration);\n opts.onUpdate(easing(rawT), rawT);\n\n if (rawT >= 1) {\n completed = true;\n opts.onComplete?.();\n return;\n }\n\n frame = raf(step);\n };\n\n frame = raf(step);\n\n return {\n cancel(): void {\n if (cancelled || completed) {\n return;\n }\n cancelled = true;\n if (frame !== undefined) {\n cancelRaf(frame);\n }\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,cAAc;AAqBvB,SAAS,aAAqB;AAC5B,SAAO,WAAW,aAAa,IAAI,KAAK,KAAK,IAAI;AACnD;AAEA,SAAS,WAAW,IAAiC;AACnD,MAAI,WAAW,0BAA0B,QAAW;AAClD,WAAO,WAAW,sBAAsB,EAAE;AAAA,EAC5C;AAEA,SAAO,WAAW,WAAW,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;AACzD;AAEA,SAAS,iBAAiB,QAAsB;AAC9C,MAAI,WAAW,yBAAyB,QAAW;AACjD,eAAW,qBAAqB,MAAM;AACtC;AAAA,EACF;AAEA,aAAW,aAAa,MAAM;AAChC;AAEA,SAAS,QAAQ,OAAuB;AACtC,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;AACvC;AAEO,SAAS,QAAQ,MAAuC;AAC7D,QAAM,SAAS,KAAK,UAAU;AAE9B,MAAI,KAAK,YAAY,GAAG;AACtB,SAAK,SAAS,OAAO,CAAC,GAAG,CAAC;AAC1B,SAAK,aAAa;AAClB,WAAO;AAAA,MACL,SAAe;AACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,KAAK,OAAO;AACxB,QAAM,MAAM,KAAK,OAAO;AACxB,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,QAAQ,IAAI;AAClB,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI;AAEJ,QAAM,OAAO,MAAY;AACvB,QAAI,aAAa,WAAW;AAC1B;AAAA,IACF;AAEA,UAAM,OAAO,SAAS,IAAI,IAAI,SAAS,KAAK,QAAQ;AACpD,SAAK,SAAS,OAAO,IAAI,GAAG,IAAI;AAEhC,QAAI,QAAQ,GAAG;AACb,kBAAY;AACZ,WAAK,aAAa;AAClB;AAAA,IACF;AAEA,YAAQ,IAAI,IAAI;AAAA,EAClB;AAEA,UAAQ,IAAI,IAAI;AAEhB,SAAO;AAAA,IACL,SAAe;AACb,UAAI,aAAa,WAAW;AAC1B;AAAA,MACF;AACA,kBAAY;AACZ,UAAI,UAAU,QAAW;AACvB,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/animation/env.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export declare function prefersReducedMotion(): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Interaction motion (hover glides, tooltip transitions) follows the OS
|
|
4
|
+
* reduced-motion setting and the global screenshot/automation kill-switch.
|
|
5
|
+
*/
|
|
6
|
+
export declare function interactionMotionDisabled(): boolean;
|
|
2
7
|
//# sourceMappingURL=env.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/animation/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C"}
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/animation/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD"}
|
package/dist/animation/env.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
function prefersReducedMotion() {
|
|
2
2
|
return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
|
|
3
3
|
}
|
|
4
|
+
function interactionMotionDisabled() {
|
|
5
|
+
return prefersReducedMotion() || globalThis.__GRAPHEIN_DISABLE_ANIM === true;
|
|
6
|
+
}
|
|
4
7
|
export {
|
|
8
|
+
interactionMotionDisabled,
|
|
5
9
|
prefersReducedMotion
|
|
6
10
|
};
|
|
7
11
|
//# sourceMappingURL=env.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/animation/env.ts"],
|
|
4
|
-
"sourcesContent": ["export function prefersReducedMotion(): boolean {\n return globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n}\n"],
|
|
5
|
-
"mappings": "AAAO,SAAS,uBAAgC;AAC9C,SAAO,WAAW,aAAa,kCAAkC,EAAE,WAAW;AAChF;",
|
|
4
|
+
"sourcesContent": ["export function prefersReducedMotion(): boolean {\n return globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n}\n\n/**\n * Interaction motion (hover glides, tooltip transitions) follows the OS\n * reduced-motion setting and the global screenshot/automation kill-switch.\n */\nexport function interactionMotionDisabled(): boolean {\n return prefersReducedMotion() || globalThis.__GRAPHEIN_DISABLE_ANIM === true;\n}\n"],
|
|
5
|
+
"mappings": "AAAO,SAAS,uBAAgC;AAC9C,SAAO,WAAW,aAAa,kCAAkC,EAAE,WAAW;AAChF;AAMO,SAAS,4BAAqC;AACnD,SAAO,qBAAqB,KAAK,WAAW,4BAA4B;AAC1E;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/animation/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/animation/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
package/dist/animation/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/animation/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './animate';\nexport * from './easing';\nexport * from './entrance';\nexport * from './env';\nexport * from './interpolate';\nexport * from './transition';\n"],
|
|
5
|
-
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
4
|
+
"sourcesContent": ["export * from './animate';\nexport * from './easing';\nexport * from './entrance';\nexport * from './env';\nexport * from './interpolate';\nexport * from './stagger';\nexport * from './transition';\n"],
|
|
5
|
+
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staggered entrance timing.
|
|
3
|
+
*
|
|
4
|
+
* A staggered entrance drives every item from one raw (linear) clock but starts
|
|
5
|
+
* each item a little later than the previous one, so marks arrive as a wave
|
|
6
|
+
* rather than all at once. Item `index` of `count` begins at
|
|
7
|
+
* `stagger * index / (count - 1)` of the clock and runs for the remaining
|
|
8
|
+
* `1 - stagger`, eased individually. The clock reaching 1 always yields exactly
|
|
9
|
+
* 1 for every item, so the final frame is the static draw.
|
|
10
|
+
*/
|
|
11
|
+
import type { EasingFunction } from './easing.js';
|
|
12
|
+
export declare function staggerProgress(raw: number, index: number, count: number, stagger: number, ease?: EasingFunction): number;
|
|
13
|
+
//# sourceMappingURL=stagger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stagger.d.ts","sourceRoot":"","sources":["../../src/animation/stagger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI/C,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,cAAc,GACpB,MAAM,CAOR"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const MAX_STAGGER = 0.9;
|
|
2
|
+
function staggerProgress(raw, index, count, stagger, ease) {
|
|
3
|
+
if (raw >= 1) return 1;
|
|
4
|
+
if (raw <= 0) return 0;
|
|
5
|
+
const spread = Math.min(MAX_STAGGER, Math.max(0, stagger));
|
|
6
|
+
const offset = count > 1 ? spread * Math.min(index, count - 1) / (count - 1) : 0;
|
|
7
|
+
const local = Math.min(1, Math.max(0, (raw - offset) / (1 - spread)));
|
|
8
|
+
return ease ? ease(local) : local;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
staggerProgress
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=stagger.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/animation/stagger.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Staggered entrance timing.\n *\n * A staggered entrance drives every item from one raw (linear) clock but starts\n * each item a little later than the previous one, so marks arrive as a wave\n * rather than all at once. Item `index` of `count` begins at\n * `stagger * index / (count - 1)` of the clock and runs for the remaining\n * `1 - stagger`, eased individually. The clock reaching 1 always yields exactly\n * 1 for every item, so the final frame is the static draw.\n */\n\nimport type { EasingFunction } from './easing';\n\nconst MAX_STAGGER = 0.9;\n\nexport function staggerProgress(\n raw: number,\n index: number,\n count: number,\n stagger: number,\n ease?: EasingFunction,\n): number {\n if (raw >= 1) return 1;\n if (raw <= 0) return 0;\n const spread = Math.min(MAX_STAGGER, Math.max(0, stagger));\n const offset = count > 1 ? (spread * Math.min(index, count - 1)) / (count - 1) : 0;\n const local = Math.min(1, Math.max(0, (raw - offset) / (1 - spread)));\n return ease ? ease(local) : local;\n}\n"],
|
|
5
|
+
"mappings": "AAaA,MAAM,cAAc;AAEb,SAAS,gBACd,KACA,OACA,OACA,SACA,MACQ;AACR,MAAI,OAAO,EAAG,QAAO;AACrB,MAAI,OAAO,EAAG,QAAO;AACrB,QAAM,SAAS,KAAK,IAAI,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC;AACzD,QAAM,SAAS,QAAQ,IAAK,SAAS,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAM,QAAQ,KAAK;AACjF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,OAAO,CAAC;AACpE,SAAO,OAAO,KAAK,KAAK,IAAI;AAC9B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/axes/draw.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ import type { CartesianModel } from '../runtime/cartesian.js';
|
|
|
11
11
|
export { drawOverlay } from './overlay.js';
|
|
12
12
|
export { drawLegend } from './legend.js';
|
|
13
13
|
export { drawTitle } from './title.js';
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Draw gridlines + axis baselines + tick marks on the marks canvas (behind marks).
|
|
16
|
+
* While a morph is drawing (see axes/morph.ts) the lines glide from the outgoing
|
|
17
|
+
* frame's positions instead of jumping to the new scale.
|
|
18
|
+
*/
|
|
15
19
|
export declare function drawAxesUnderlay(surface: Surface, model: CartesianModel): void;
|
|
16
20
|
//# sourceMappingURL=draw.d.ts.map
|
package/dist/axes/draw.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draw.d.ts","sourceRoot":"","sources":["../../src/axes/draw.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"draw.d.ts","sourceRoot":"","sources":["../../src/axes/draw.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AA8BpC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAiG9E"}
|
package/dist/axes/draw.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { crisp } from "../util/math.js";
|
|
2
2
|
import { TICK_SIZE } from "../layout/index.js";
|
|
3
3
|
import { RoughPen } from "../rough/index.js";
|
|
4
|
+
import { chromeMorph, stashChrome } from "../render/chromeMotion.js";
|
|
4
5
|
import { resolveXLabels } from "./tickLabels.js";
|
|
6
|
+
import { AXIS_UNDERLAY, blendUnderlay, paintUnderlay, trackScales, underlayFrameOf } from "./morph.js";
|
|
5
7
|
import { drawOverlay } from "./overlay.js";
|
|
6
8
|
import { drawLegend } from "./legend.js";
|
|
7
9
|
import { drawTitle } from "./title.js";
|
|
@@ -28,6 +30,17 @@ function axisSegment(pen, model, sx0, sy0, sx1, sy1, stroke) {
|
|
|
28
30
|
);
|
|
29
31
|
}
|
|
30
32
|
function drawAxesUnderlay(surface, model) {
|
|
33
|
+
const scales = trackScales(surface, model);
|
|
34
|
+
const xPlaced = model.orientation === "horizontal" ? [] : resolveXLabels(model);
|
|
35
|
+
const frame = underlayFrameOf(model, xPlaced, { x: xGridEnabled(model), y: yGridEnabled(model) });
|
|
36
|
+
const morph = scales && !model.sketch ? chromeMorph(surface, AXIS_UNDERLAY) : null;
|
|
37
|
+
if (scales && morph) {
|
|
38
|
+
const blended = blendUnderlay(morph.from, frame, morph.t, scales.from, model);
|
|
39
|
+
paintUnderlay(surface.marks.ctx, blended, { grid: model.tokens.color.grid, axis: model.tokens.color.axis }, TICK_SIZE);
|
|
40
|
+
stashChrome(surface, AXIS_UNDERLAY, blended);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
stashChrome(surface, AXIS_UNDERLAY, frame);
|
|
31
44
|
if (model.orientation === "horizontal") {
|
|
32
45
|
drawHorizontalAxesUnderlay(surface, model);
|
|
33
46
|
return;
|
|
@@ -40,7 +53,6 @@ function drawAxesUnderlay(surface, model) {
|
|
|
40
53
|
const y1 = plot.y + plot.height;
|
|
41
54
|
ctx.save();
|
|
42
55
|
ctx.lineWidth = 1;
|
|
43
|
-
const xPlaced = resolveXLabels(model);
|
|
44
56
|
const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;
|
|
45
57
|
const seg = (sx0, sy0, sx1, sy1, stroke) => axisSegment(pen, model, sx0, sy0, sx1, sy1, stroke);
|
|
46
58
|
if (yGridEnabled(model)) {
|
package/dist/axes/draw.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/axes/draw.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Axis, gridline, legend, and title rendering for cartesian charts.\n *\n * Marks (gridlines, tick marks, axis baselines) are drawn on the canvas; text\n * (tick labels, axis titles, chart title, legend) lives in the HTML overlay for\n * crisp, accessible, selectable typography. Geometry comes from the already\n * computed `CartesianModel` / `Frame`, so this module is pure presentation.\n */\n\nimport type { Surface } from '../render/surface';\nimport { crisp } from '../util/math';\nimport { TICK_SIZE } from '../layout';\nimport type { CartesianModel } from '../runtime/cartesian';\nimport { RoughPen } from '../rough';\nimport { resolveXLabels } from './tickLabels';\n\nexport { drawOverlay } from './overlay';\nexport { drawLegend } from './legend';\nexport { drawTitle } from './title';\n\n// Gridlines, tick marks and baselines stay in this facade because they are the\n// canvas underlay paired with the overlay text exported above.\n\nfunction xGridEnabled(model: CartesianModel): boolean {\n const cfg = model.spec.axes?.x;\n if (cfg?.grid !== undefined) return cfg.grid;\n return model.x.kind === 'linear' || model.x.kind === 'time' || model.spec.type === 'scatter';\n}\n\nfunction yGridEnabled(model: CartesianModel): boolean {\n return model.spec.axes?.y?.grid !== false;\n}\n\nfunction axisSegment(pen: RoughPen, model: CartesianModel, sx0: number, sy0: number, sx1: number, sy1: number, stroke: string): void {\n pen.polyline(\n [\n { x: sx0, y: sy0 },\n { x: sx1, y: sy1 },\n ],\n {\n stroke,\n strokeWidth: 1,\n roughness: model.sketch!.roughness * 0.5,\n bowing: model.sketch!.bowing * 0.55,\n },\n );\n}\n\n
|
|
5
|
-
"mappings": "AAUA,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAE1B,SAAS,gBAAgB;AACzB,SAAS,sBAAsB;
|
|
4
|
+
"sourcesContent": ["/**\n * Axis, gridline, legend, and title rendering for cartesian charts.\n *\n * Marks (gridlines, tick marks, axis baselines) are drawn on the canvas; text\n * (tick labels, axis titles, chart title, legend) lives in the HTML overlay for\n * crisp, accessible, selectable typography. Geometry comes from the already\n * computed `CartesianModel` / `Frame`, so this module is pure presentation.\n */\n\nimport type { Surface } from '../render/surface';\nimport { crisp } from '../util/math';\nimport { TICK_SIZE } from '../layout';\nimport type { CartesianModel } from '../runtime/cartesian';\nimport { RoughPen } from '../rough';\nimport { chromeMorph, stashChrome } from '../render/chromeMotion';\nimport { resolveXLabels } from './tickLabels';\nimport { AXIS_UNDERLAY, blendUnderlay, paintUnderlay, trackScales, underlayFrameOf, type UnderlayFrame } from './morph';\n\nexport { drawOverlay } from './overlay';\nexport { drawLegend } from './legend';\nexport { drawTitle } from './title';\n\n// Gridlines, tick marks and baselines stay in this facade because they are the\n// canvas underlay paired with the overlay text exported above.\n\nfunction xGridEnabled(model: CartesianModel): boolean {\n const cfg = model.spec.axes?.x;\n if (cfg?.grid !== undefined) return cfg.grid;\n return model.x.kind === 'linear' || model.x.kind === 'time' || model.spec.type === 'scatter';\n}\n\nfunction yGridEnabled(model: CartesianModel): boolean {\n return model.spec.axes?.y?.grid !== false;\n}\n\nfunction axisSegment(pen: RoughPen, model: CartesianModel, sx0: number, sy0: number, sx1: number, sy1: number, stroke: string): void {\n pen.polyline(\n [\n { x: sx0, y: sy0 },\n { x: sx1, y: sy1 },\n ],\n {\n stroke,\n strokeWidth: 1,\n roughness: model.sketch!.roughness * 0.5,\n bowing: model.sketch!.bowing * 0.55,\n },\n );\n}\n\n/**\n * Draw gridlines + axis baselines + tick marks on the marks canvas (behind marks).\n * While a morph is drawing (see axes/morph.ts) the lines glide from the outgoing\n * frame's positions instead of jumping to the new scale.\n */\nexport function drawAxesUnderlay(surface: Surface, model: CartesianModel): void {\n const scales = trackScales(surface, model);\n // The labelled x-tick subset drives gridlines, tick marks and labels alike so\n // a dense axis never shows more gridlines than it has room to label.\n const xPlaced = model.orientation === 'horizontal' ? [] : resolveXLabels(model);\n const frame = underlayFrameOf(model, xPlaced, { x: xGridEnabled(model), y: yGridEnabled(model) });\n const morph = scales && !model.sketch ? chromeMorph<UnderlayFrame>(surface, AXIS_UNDERLAY) : null;\n if (scales && morph) {\n const blended = blendUnderlay(morph.from, frame, morph.t, scales.from, model);\n paintUnderlay(surface.marks.ctx, blended, { grid: model.tokens.color.grid, axis: model.tokens.color.axis }, TICK_SIZE);\n stashChrome(surface, AXIS_UNDERLAY, blended);\n return;\n }\n stashChrome(surface, AXIS_UNDERLAY, frame);\n if (model.orientation === 'horizontal') {\n drawHorizontalAxesUnderlay(surface, model);\n return;\n }\n const ctx = surface.marks.ctx;\n const { plot, tokens } = model;\n const x0 = plot.x;\n const x1 = plot.x + plot.width;\n const y0 = plot.y;\n const y1 = plot.y + plot.height;\n\n ctx.save();\n ctx.lineWidth = 1;\n\n // When sketching, gridlines/ticks are drawn as gently wavy hand-drawn segments\n // (reduced roughness keeps them subtle behind the bolder data marks).\n const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;\n const seg = (sx0: number, sy0: number, sx1: number, sy1: number, stroke: string): void =>\n axisSegment(pen!, model, sx0, sy0, sx1, sy1, stroke);\n\n // Horizontal y gridlines.\n if (yGridEnabled(model)) {\n if (pen) {\n for (const t of model.yTicks) seg(x0, t.pos, x1, t.pos, tokens.color.grid);\n } else {\n ctx.strokeStyle = tokens.color.grid;\n ctx.beginPath();\n for (const t of model.yTicks) {\n const y = crisp(t.pos);\n ctx.moveTo(x0, y);\n ctx.lineTo(x1, y);\n }\n ctx.stroke();\n }\n }\n\n // Vertical x gridlines (aligned to the labelled ticks for a clean read).\n if (xGridEnabled(model)) {\n if (pen) {\n for (const p of xPlaced) seg(p.pos, y0, p.pos, y1, tokens.color.grid);\n } else {\n ctx.strokeStyle = tokens.color.grid;\n ctx.beginPath();\n for (const p of xPlaced) {\n const x = crisp(p.pos);\n ctx.moveTo(x, y0);\n ctx.lineTo(x, y1);\n }\n ctx.stroke();\n }\n }\n\n // Axis baselines. The y axis relies on horizontal gridlines + labels (no\n // vertical domain line) for a cleaner, more modern read; only the x baseline\n // is drawn to anchor the marks.\n if (model.spec.axes?.x?.show !== false) {\n if (pen) {\n seg(x0, y1, x1, y1, tokens.color.axis);\n } else {\n ctx.strokeStyle = tokens.color.axis;\n ctx.beginPath();\n ctx.moveTo(x0, crisp(y1));\n ctx.lineTo(x1, crisp(y1));\n ctx.stroke();\n }\n }\n\n // X tick marks (subtle), drawn only where labels sit.\n if (model.spec.axes?.x?.show !== false) {\n if (pen) {\n for (const p of xPlaced) seg(p.pos, y1, p.pos, y1 + TICK_SIZE, tokens.color.axis);\n } else {\n ctx.strokeStyle = tokens.color.axis;\n ctx.beginPath();\n for (const p of xPlaced) {\n const x = crisp(p.pos);\n ctx.moveTo(x, y1);\n ctx.lineTo(x, y1 + TICK_SIZE);\n }\n ctx.stroke();\n }\n }\n ctx.restore();\n}\n\n/**\n * Horizontal-bar axis underlay: the value axis runs along the bottom (vertical\n * gridlines at each value tick) and the category axis is a left spine with\n * outward tick marks that anchors the bars. Mirror of the vertical layout.\n */\nfunction drawHorizontalAxesUnderlay(surface: Surface, model: CartesianModel): void {\n const ctx = surface.marks.ctx;\n const { plot, tokens } = model;\n const x0 = plot.x;\n const y0 = plot.y;\n const y1 = plot.y + plot.height;\n\n ctx.save();\n ctx.lineWidth = 1;\n\n const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;\n const seg = (sx0: number, sy0: number, sx1: number, sy1: number, stroke: string): void =>\n axisSegment(pen!, model, sx0, sy0, sx1, sy1, stroke);\n\n // Vertical value gridlines (the value axis runs horizontally).\n if (yGridEnabled(model)) {\n if (pen) {\n for (const t of model.yTicks) seg(t.pos, y0, t.pos, y1, tokens.color.grid);\n } else {\n ctx.strokeStyle = tokens.color.grid;\n ctx.beginPath();\n for (const t of model.yTicks) {\n const x = crisp(t.pos);\n ctx.moveTo(x, y0);\n ctx.lineTo(x, y1);\n }\n ctx.stroke();\n }\n }\n\n // Left category spine + outward tick marks anchor the bars.\n if (model.spec.axes?.x?.show !== false) {\n if (pen) {\n seg(x0, y0, x0, y1, tokens.color.axis);\n for (const t of model.xTicks) seg(x0 - TICK_SIZE, t.pos, x0, t.pos, tokens.color.axis);\n } else {\n ctx.strokeStyle = tokens.color.axis;\n ctx.beginPath();\n ctx.moveTo(crisp(x0), y0);\n ctx.lineTo(crisp(x0), y1);\n ctx.stroke();\n ctx.beginPath();\n for (const t of model.xTicks) {\n const y = crisp(t.pos);\n ctx.moveTo(x0 - TICK_SIZE, y);\n ctx.lineTo(x0, y);\n }\n ctx.stroke();\n }\n }\n\n ctx.restore();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axis motion — gridlines, tick marks and tick labels glide with the scale.
|
|
3
|
+
*
|
|
4
|
+
* Each axis draw stashes what it drew (see render/chromeMotion). When a morph
|
|
5
|
+
* redraws a chart on a tween view, the axis modules blend the outgoing frame
|
|
6
|
+
* with the incoming one: a tick present in both glides between its positions,
|
|
7
|
+
* a new tick slides in from where its value sat on the old scale while fading
|
|
8
|
+
* in, and a tick that is gone slides toward where its value lands on the new
|
|
9
|
+
* scale while fading out — so the axis moves exactly with the marks, which
|
|
10
|
+
* interpolate between the same two pixel mappings.
|
|
11
|
+
*/
|
|
12
|
+
import type { Rect } from '../types.js';
|
|
13
|
+
import type { CartesianModel, Tick } from '../runtime/cartesian.js';
|
|
14
|
+
import type { Surface } from '../render/surface.js';
|
|
15
|
+
/** Chrome stash names shared by the axis, annotation and trendline modules. */
|
|
16
|
+
export declare const AXIS_SCALES = "axes:scales";
|
|
17
|
+
export declare const AXIS_UNDERLAY = "axes:underlay";
|
|
18
|
+
export declare const AXIS_LABELS = "axes:labels";
|
|
19
|
+
export type TickValue = Tick['value'];
|
|
20
|
+
/** Value → pixel mappings of one drawn frame. */
|
|
21
|
+
export interface ScaleMaps {
|
|
22
|
+
xAt(value: unknown): number | undefined;
|
|
23
|
+
yAt(value: unknown): number | undefined;
|
|
24
|
+
}
|
|
25
|
+
/** A frame's plot rect and value → pixel mappings, for placing the other frame's ticks. */
|
|
26
|
+
export interface ScaleFrame extends ScaleMaps {
|
|
27
|
+
plot: Rect;
|
|
28
|
+
/**
|
|
29
|
+
* The static frames this one mixes, with weights summing to 1. However many
|
|
30
|
+
* morphs interrupt one another, a blend stays this flat list — never a chain
|
|
31
|
+
* of nested closures — and frames whose weight has decayed away are dropped.
|
|
32
|
+
*/
|
|
33
|
+
parts: ReadonlyArray<{
|
|
34
|
+
weight: number;
|
|
35
|
+
maps: ScaleMaps;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/** One drawn axis element, keyed by its tick value. */
|
|
39
|
+
export interface AxisItem {
|
|
40
|
+
key: string;
|
|
41
|
+
value: TickValue;
|
|
42
|
+
/** Pixel position along its axis. */
|
|
43
|
+
pos: number;
|
|
44
|
+
alpha: number;
|
|
45
|
+
}
|
|
46
|
+
/** The axis lines one frame drew (see drawAxesUnderlay). */
|
|
47
|
+
export interface UnderlayFrame {
|
|
48
|
+
orientation: 'vertical' | 'horizontal';
|
|
49
|
+
plot: Rect;
|
|
50
|
+
/** Gridlines at value (y) ticks: horizontal lines, or vertical ones for horizontal bars. */
|
|
51
|
+
valueGrid: AxisItem[];
|
|
52
|
+
/** Vertical gridlines at the labelled x ticks (vertical orientation). */
|
|
53
|
+
xGrid: AxisItem[];
|
|
54
|
+
/** Tick marks on the category/x axis. */
|
|
55
|
+
xMarks: AxisItem[];
|
|
56
|
+
/** Whether the x baseline (or the horizontal-bar spine) is drawn. */
|
|
57
|
+
axisLine: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare const lerp: (a: number, b: number, t: number) => number;
|
|
60
|
+
export declare function lerpRect(a: Rect, b: Rect, t: number): Rect;
|
|
61
|
+
/** A stable key for a tick value (numbers and strings never collide). */
|
|
62
|
+
export declare function tickKey(value: TickValue): string;
|
|
63
|
+
/**
|
|
64
|
+
* Blend two frames' items: shared ones (same key, and `same` agrees) glide and
|
|
65
|
+
* keep the incoming item; new ones start where their value sat on the outgoing
|
|
66
|
+
* scale and fade in; departing ones head to where their value lands on the
|
|
67
|
+
* incoming scale and fade out. Departing items come first so they paint beneath.
|
|
68
|
+
*/
|
|
69
|
+
export declare function blendItems<T extends AxisItem>(from: readonly T[], to: readonly T[], t: number, fromAt: (value: TickValue) => number | undefined, toAt: (value: TickValue) => number | undefined, same?: (a: T, b: T) => boolean): Array<{
|
|
70
|
+
item: T;
|
|
71
|
+
pos: number;
|
|
72
|
+
alpha: number;
|
|
73
|
+
}>;
|
|
74
|
+
/** The current frame's mappings, as stashed for the next morph. */
|
|
75
|
+
export declare function scaleFrameOf(model: CartesianModel): ScaleFrame;
|
|
76
|
+
/** `from` mixed `t` of the way into `model`'s mappings. */
|
|
77
|
+
export declare function blendScales(from: ScaleFrame, model: CartesianModel, t: number): ScaleFrame;
|
|
78
|
+
/**
|
|
79
|
+
* Stash this frame's mappings and return the outgoing ones while morphing (null
|
|
80
|
+
* otherwise). Call once per axis draw, before anything uses {@link morphedModel}.
|
|
81
|
+
* `name` lets a secondary axis (combo's right axis) track its own scale.
|
|
82
|
+
*/
|
|
83
|
+
export declare function trackScales(surface: Surface, model: CartesianModel, name?: string): {
|
|
84
|
+
from: ScaleFrame;
|
|
85
|
+
t: number;
|
|
86
|
+
} | null;
|
|
87
|
+
/**
|
|
88
|
+
* `model` with its plot and value → pixel mappings mixed from the outgoing
|
|
89
|
+
* frame's while a morph is drawing (so annotations and trendlines move with the
|
|
90
|
+
* axes); `model` itself otherwise.
|
|
91
|
+
*/
|
|
92
|
+
export declare function morphedModel(surface: Surface, model: CartesianModel): CartesianModel;
|
|
93
|
+
/** The axis lines a static draw of `model` produces (`xPlaced` = the labelled x ticks). */
|
|
94
|
+
export declare function underlayFrameOf(model: CartesianModel, xPlaced: ReadonlyArray<{
|
|
95
|
+
value: TickValue;
|
|
96
|
+
pos: number;
|
|
97
|
+
}>, grid: {
|
|
98
|
+
x: boolean;
|
|
99
|
+
y: boolean;
|
|
100
|
+
}): UnderlayFrame;
|
|
101
|
+
/** `to` blended from `from`: what a tween frame paints (and stashes). */
|
|
102
|
+
export declare function blendUnderlay(from: UnderlayFrame, to: UnderlayFrame, t: number, scales: ScaleFrame, model: CartesianModel): UnderlayFrame;
|
|
103
|
+
/**
|
|
104
|
+
* Paint a blended underlay: gridlines clipped to the (moving) plot, each at its
|
|
105
|
+
* own opacity, then the axis line and tick marks.
|
|
106
|
+
*/
|
|
107
|
+
export declare function paintUnderlay(ctx: CanvasRenderingContext2D, frame: UnderlayFrame, colors: {
|
|
108
|
+
grid: string;
|
|
109
|
+
axis: string;
|
|
110
|
+
}, tickSize: number): void;
|
|
111
|
+
//# sourceMappingURL=morph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"morph.d.ts","sourceRoot":"","sources":["../../src/axes/morph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { chromeMorph, stashChrome, visibleItems } from "../render/chromeMotion.js";
|
|
2
|
+
import { crisp } from "../util/math.js";
|
|
3
|
+
const AXIS_SCALES = "axes:scales";
|
|
4
|
+
const AXIS_UNDERLAY = "axes:underlay";
|
|
5
|
+
const AXIS_LABELS = "axes:labels";
|
|
6
|
+
const MIN_PART_WEIGHT = 1e-3;
|
|
7
|
+
const MAX_PARTS = 12;
|
|
8
|
+
const lerp = (a, b, t) => a + (b - a) * t;
|
|
9
|
+
function lerpRect(a, b, t) {
|
|
10
|
+
return { x: lerp(a.x, b.x, t), y: lerp(a.y, b.y, t), width: lerp(a.width, b.width, t), height: lerp(a.height, b.height, t) };
|
|
11
|
+
}
|
|
12
|
+
function tickKey(value) {
|
|
13
|
+
return `${typeof value === "number" ? "n" : "s"}:${value}`;
|
|
14
|
+
}
|
|
15
|
+
function finiteOr(value, fallback) {
|
|
16
|
+
return value !== void 0 && Number.isFinite(value) ? value : fallback;
|
|
17
|
+
}
|
|
18
|
+
function blendItems(from, to, t, fromAt, toAt, same = () => true) {
|
|
19
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const a of from) byKey.set(a.key, a);
|
|
21
|
+
const kept = /* @__PURE__ */ new Set();
|
|
22
|
+
const entering = [];
|
|
23
|
+
for (const b of to) {
|
|
24
|
+
const a = byKey.get(b.key);
|
|
25
|
+
if (a && !kept.has(a) && same(a, b)) {
|
|
26
|
+
kept.add(a);
|
|
27
|
+
entering.push({ item: b, pos: lerp(a.pos, b.pos, t), alpha: lerp(a.alpha, b.alpha, t) });
|
|
28
|
+
} else {
|
|
29
|
+
entering.push({ item: b, pos: lerp(finiteOr(fromAt(b.value), b.pos), b.pos, t), alpha: b.alpha * t });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const leaving = from.filter((a) => !kept.has(a)).map((a) => ({ item: a, pos: lerp(a.pos, finiteOr(toAt(a.value), a.pos), t), alpha: a.alpha * (1 - t) }));
|
|
33
|
+
return [...leaving, ...entering];
|
|
34
|
+
}
|
|
35
|
+
function mixedAt(parts, axis) {
|
|
36
|
+
if (parts.length === 1) return parts[0].maps[axis];
|
|
37
|
+
return (value) => {
|
|
38
|
+
let sum = 0;
|
|
39
|
+
let total = 0;
|
|
40
|
+
for (const { weight, maps } of parts) {
|
|
41
|
+
if (!(weight > 0)) continue;
|
|
42
|
+
const p = maps[axis](value);
|
|
43
|
+
if (p === void 0 || !Number.isFinite(p)) continue;
|
|
44
|
+
sum += weight * p;
|
|
45
|
+
total += weight;
|
|
46
|
+
}
|
|
47
|
+
if (total > 0) return sum / total;
|
|
48
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
49
|
+
const p = parts[i].maps[axis](value);
|
|
50
|
+
if (p !== void 0 && Number.isFinite(p)) return p;
|
|
51
|
+
}
|
|
52
|
+
return void 0;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function scaleFrameOf(model) {
|
|
56
|
+
const maps = { xAt: (v) => model.x.pixel(v), yAt: (v) => model.y.pixel(v) };
|
|
57
|
+
return { plot: model.plot, xAt: maps.xAt, yAt: maps.yAt, parts: [{ weight: 1, maps }] };
|
|
58
|
+
}
|
|
59
|
+
function blendScales(from, model, t) {
|
|
60
|
+
const to = scaleFrameOf(model);
|
|
61
|
+
const w = Math.min(1, Math.max(0, t));
|
|
62
|
+
const incoming = { weight: w, maps: to.parts[0].maps };
|
|
63
|
+
let outgoing = from.parts.map((part) => ({ weight: part.weight * (1 - w), maps: part.maps })).filter((part) => part.weight >= MIN_PART_WEIGHT);
|
|
64
|
+
if (outgoing.length > MAX_PARTS - 1) outgoing = outgoing.sort((a, b) => b.weight - a.weight).slice(0, MAX_PARTS - 1);
|
|
65
|
+
const total = outgoing.reduce((sum, part) => sum + part.weight, incoming.weight);
|
|
66
|
+
const parts = total > 0 ? [...outgoing, incoming].map((part) => ({ weight: part.weight / total, maps: part.maps })) : [{ weight: 1, maps: incoming.maps }];
|
|
67
|
+
return { plot: lerpRect(from.plot, to.plot, t), xAt: mixedAt(parts, "xAt"), yAt: mixedAt(parts, "yAt"), parts };
|
|
68
|
+
}
|
|
69
|
+
function trackScales(surface, model, name = AXIS_SCALES) {
|
|
70
|
+
const morph = chromeMorph(surface, name);
|
|
71
|
+
stashChrome(surface, name, morph ? blendScales(morph.from, model, morph.t) : scaleFrameOf(model));
|
|
72
|
+
return morph;
|
|
73
|
+
}
|
|
74
|
+
function morphedModel(surface, model) {
|
|
75
|
+
const morph = chromeMorph(surface, AXIS_SCALES);
|
|
76
|
+
if (!morph) return model;
|
|
77
|
+
const blended = blendScales(morph.from, model, morph.t);
|
|
78
|
+
return {
|
|
79
|
+
...model,
|
|
80
|
+
plot: blended.plot,
|
|
81
|
+
x: { ...model.x, pixel: blended.xAt },
|
|
82
|
+
y: {
|
|
83
|
+
...model.y,
|
|
84
|
+
baseline: lerp(finiteOr(morph.from.yAt(0), model.y.baseline), model.y.baseline, morph.t),
|
|
85
|
+
pixel: (v) => blended.yAt(v) ?? NaN
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function underlayFrameOf(model, xPlaced, grid) {
|
|
90
|
+
const item = (value, pos) => ({ key: tickKey(value), value, pos, alpha: 1 });
|
|
91
|
+
const axisLine = model.spec.axes?.x?.show !== false;
|
|
92
|
+
if (model.orientation === "horizontal") {
|
|
93
|
+
return {
|
|
94
|
+
orientation: "horizontal",
|
|
95
|
+
plot: model.plot,
|
|
96
|
+
valueGrid: grid.y ? model.yTicks.map((tick) => item(tick.value, tick.pos)) : [],
|
|
97
|
+
xGrid: [],
|
|
98
|
+
xMarks: axisLine ? model.xTicks.map((tick) => item(tick.value, tick.pos)) : [],
|
|
99
|
+
axisLine
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
orientation: "vertical",
|
|
104
|
+
plot: model.plot,
|
|
105
|
+
valueGrid: grid.y ? model.yTicks.map((tick) => item(tick.value, tick.pos)) : [],
|
|
106
|
+
xGrid: grid.x ? xPlaced.map((p) => item(p.value, p.pos)) : [],
|
|
107
|
+
xMarks: axisLine ? xPlaced.map((p) => item(p.value, p.pos)) : [],
|
|
108
|
+
axisLine
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function blendUnderlay(from, to, t, scales, model) {
|
|
112
|
+
const xAt = (v) => model.x.pixel(v);
|
|
113
|
+
const yAt = (v) => model.y.pixel(v);
|
|
114
|
+
const settle = (items) => visibleItems(items.map(({ item, pos, alpha }) => ({ ...item, pos, alpha })));
|
|
115
|
+
const flipped = from.orientation !== to.orientation;
|
|
116
|
+
const fromOf = (items) => flipped ? [] : items;
|
|
117
|
+
return {
|
|
118
|
+
orientation: to.orientation,
|
|
119
|
+
plot: lerpRect(from.plot, to.plot, t),
|
|
120
|
+
valueGrid: settle(blendItems(fromOf(from.valueGrid), to.valueGrid, t, scales.yAt, yAt)),
|
|
121
|
+
xGrid: settle(blendItems(fromOf(from.xGrid), to.xGrid, t, scales.xAt, xAt)),
|
|
122
|
+
xMarks: settle(blendItems(fromOf(from.xMarks), to.xMarks, t, scales.xAt, xAt)),
|
|
123
|
+
axisLine: to.axisLine
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function paintUnderlay(ctx, frame, colors, tickSize) {
|
|
127
|
+
const { plot } = frame;
|
|
128
|
+
const x0 = plot.x;
|
|
129
|
+
const x1 = plot.x + plot.width;
|
|
130
|
+
const y0 = plot.y;
|
|
131
|
+
const y1 = plot.y + plot.height;
|
|
132
|
+
const stroke = (alpha, color, path) => {
|
|
133
|
+
if (!(alpha > 2e-3)) return;
|
|
134
|
+
ctx.globalAlpha = Math.min(1, alpha);
|
|
135
|
+
ctx.strokeStyle = color;
|
|
136
|
+
ctx.beginPath();
|
|
137
|
+
path();
|
|
138
|
+
ctx.stroke();
|
|
139
|
+
};
|
|
140
|
+
const horizontal = frame.orientation === "horizontal";
|
|
141
|
+
ctx.save();
|
|
142
|
+
ctx.lineWidth = 1;
|
|
143
|
+
ctx.save();
|
|
144
|
+
ctx.beginPath();
|
|
145
|
+
ctx.rect(x0 - 0.5, y0 - 0.5, plot.width + 1, plot.height + 1);
|
|
146
|
+
ctx.clip();
|
|
147
|
+
for (const line of frame.valueGrid) {
|
|
148
|
+
stroke(line.alpha, colors.grid, () => {
|
|
149
|
+
if (horizontal) {
|
|
150
|
+
ctx.moveTo(crisp(line.pos), y0);
|
|
151
|
+
ctx.lineTo(crisp(line.pos), y1);
|
|
152
|
+
} else {
|
|
153
|
+
ctx.moveTo(x0, crisp(line.pos));
|
|
154
|
+
ctx.lineTo(x1, crisp(line.pos));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
for (const line of frame.xGrid) {
|
|
159
|
+
stroke(line.alpha, colors.grid, () => {
|
|
160
|
+
ctx.moveTo(crisp(line.pos), y0);
|
|
161
|
+
ctx.lineTo(crisp(line.pos), y1);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
ctx.restore();
|
|
165
|
+
if (frame.axisLine) {
|
|
166
|
+
stroke(1, colors.axis, () => {
|
|
167
|
+
if (horizontal) {
|
|
168
|
+
ctx.moveTo(crisp(x0), y0);
|
|
169
|
+
ctx.lineTo(crisp(x0), y1);
|
|
170
|
+
} else {
|
|
171
|
+
ctx.moveTo(x0, crisp(y1));
|
|
172
|
+
ctx.lineTo(x1, crisp(y1));
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
for (const mark of frame.xMarks) {
|
|
176
|
+
const inside = horizontal ? mark.pos >= y0 - 1 && mark.pos <= y1 + 1 : mark.pos >= x0 - 1 && mark.pos <= x1 + 1;
|
|
177
|
+
if (!inside) continue;
|
|
178
|
+
stroke(mark.alpha, colors.axis, () => {
|
|
179
|
+
if (horizontal) {
|
|
180
|
+
ctx.moveTo(x0 - tickSize, crisp(mark.pos));
|
|
181
|
+
ctx.lineTo(x0, crisp(mark.pos));
|
|
182
|
+
} else {
|
|
183
|
+
ctx.moveTo(crisp(mark.pos), y1);
|
|
184
|
+
ctx.lineTo(crisp(mark.pos), y1 + tickSize);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
ctx.restore();
|
|
190
|
+
}
|
|
191
|
+
export {
|
|
192
|
+
AXIS_LABELS,
|
|
193
|
+
AXIS_SCALES,
|
|
194
|
+
AXIS_UNDERLAY,
|
|
195
|
+
blendItems,
|
|
196
|
+
blendScales,
|
|
197
|
+
blendUnderlay,
|
|
198
|
+
lerp,
|
|
199
|
+
lerpRect,
|
|
200
|
+
morphedModel,
|
|
201
|
+
paintUnderlay,
|
|
202
|
+
scaleFrameOf,
|
|
203
|
+
tickKey,
|
|
204
|
+
trackScales,
|
|
205
|
+
underlayFrameOf
|
|
206
|
+
};
|
|
207
|
+
//# sourceMappingURL=morph.js.map
|