@vielzeug/prism 26.10.15 → 26.10.17
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/LICENSE +21 -0
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +6 -1
- package/dist/_dev.js.map +1 -1
- package/dist/_tappers.cjs.map +1 -1
- package/dist/_tappers.js +25 -1
- package/dist/_tappers.js.map +1 -1
- package/dist/animation/easing.cjs.map +1 -1
- package/dist/animation/easing.js +15 -1
- package/dist/animation/easing.js.map +1 -1
- package/dist/animation/motion.cjs.map +1 -1
- package/dist/animation/motion.js +15 -1
- package/dist/animation/motion.js.map +1 -1
- package/dist/animation/reveal.cjs.map +1 -1
- package/dist/animation/reveal.js +97 -1
- package/dist/animation/reveal.js.map +1 -1
- package/dist/animation/transition.cjs.map +1 -1
- package/dist/animation/transition.js +39 -1
- package/dist/animation/transition.js.map +1 -1
- package/dist/animation/tween.cjs.map +1 -1
- package/dist/animation/tween.js +7 -1
- package/dist/animation/tween.js.map +1 -1
- package/dist/axes/axis.cjs.map +1 -1
- package/dist/axes/axis.js +76 -1
- package/dist/axes/axis.js.map +1 -1
- package/dist/axes/grid.cjs.map +1 -1
- package/dist/axes/grid.js +29 -1
- package/dist/axes/grid.js.map +1 -1
- package/dist/axes/scale-utils.cjs.map +1 -1
- package/dist/axes/scale-utils.js +10 -1
- package/dist/axes/scale-utils.js.map +1 -1
- package/dist/charts/area/area-chart.cjs.map +1 -1
- package/dist/charts/area/area-chart.js +71 -1
- package/dist/charts/area/area-chart.js.map +1 -1
- package/dist/charts/area/area-renderer.cjs.map +1 -1
- package/dist/charts/area/area-renderer.js +128 -1
- package/dist/charts/area/area-renderer.js.map +1 -1
- package/dist/charts/bar/bar-chart.cjs.map +1 -1
- package/dist/charts/bar/bar-chart.js +228 -1
- package/dist/charts/bar/bar-chart.js.map +1 -1
- package/dist/charts/bar/bar-hit-test.cjs.map +1 -1
- package/dist/charts/bar/bar-hit-test.js +25 -1
- package/dist/charts/bar/bar-hit-test.js.map +1 -1
- package/dist/charts/bar/bar-renderer.cjs.map +1 -1
- package/dist/charts/bar/bar-renderer.js +139 -1
- package/dist/charts/bar/bar-renderer.js.map +1 -1
- package/dist/charts/line/line-chart.cjs.map +1 -1
- package/dist/charts/line/line-chart.js +93 -1
- package/dist/charts/line/line-chart.js.map +1 -1
- package/dist/charts/line/line-renderer.cjs.map +1 -1
- package/dist/charts/line/line-renderer.js +143 -1
- package/dist/charts/line/line-renderer.js.map +1 -1
- package/dist/charts/pie/pie-chart.cjs +1 -1
- package/dist/charts/pie/pie-chart.cjs.map +1 -1
- package/dist/charts/pie/pie-chart.js +207 -1
- package/dist/charts/pie/pie-chart.js.map +1 -1
- package/dist/charts/pie/pie-renderer.cjs.map +1 -1
- package/dist/charts/pie/pie-renderer.js +68 -1
- package/dist/charts/pie/pie-renderer.js.map +1 -1
- package/dist/charts/radar/radar-chart.cjs +1 -1
- package/dist/charts/radar/radar-chart.cjs.map +1 -1
- package/dist/charts/radar/radar-chart.js +281 -1
- package/dist/charts/radar/radar-chart.js.map +1 -1
- package/dist/charts/radar/radar-geometry.cjs.map +1 -1
- package/dist/charts/radar/radar-geometry.js +69 -1
- package/dist/charts/radar/radar-geometry.js.map +1 -1
- package/dist/charts/scatter/scatter-chart.cjs.map +1 -1
- package/dist/charts/scatter/scatter-chart.js +69 -1
- package/dist/charts/scatter/scatter-chart.js.map +1 -1
- package/dist/charts/scatter/scatter-renderer.cjs.map +1 -1
- package/dist/charts/scatter/scatter-renderer.js +57 -1
- package/dist/charts/scatter/scatter-renderer.js.map +1 -1
- package/dist/charts/sparkline/sparkline.cjs +1 -1
- package/dist/charts/sparkline/sparkline.cjs.map +1 -1
- package/dist/charts/sparkline/sparkline.js +251 -1
- package/dist/charts/sparkline/sparkline.js.map +1 -1
- package/dist/core/cartesian-model.cjs +1 -1
- package/dist/core/cartesian-model.cjs.map +1 -1
- package/dist/core/cartesian-model.js +26 -1
- package/dist/core/cartesian-model.js.map +1 -1
- package/dist/core/cartesian-scales.cjs.map +1 -1
- package/dist/core/cartesian-scales.js +38 -1
- package/dist/core/cartesian-scales.js.map +1 -1
- package/dist/core/chart-base.cjs.map +1 -1
- package/dist/core/chart-base.js +62 -1
- package/dist/core/chart-base.js.map +1 -1
- package/dist/core/chart-scaffold.cjs.map +1 -1
- package/dist/core/chart-scaffold.js +103 -1
- package/dist/core/chart-scaffold.js.map +1 -1
- package/dist/core/datum-style.cjs +1 -1
- package/dist/core/datum-style.cjs.map +1 -1
- package/dist/core/datum-style.js +22 -1
- package/dist/core/datum-style.js.map +1 -1
- package/dist/core/ids.cjs.map +1 -1
- package/dist/core/ids.js +8 -1
- package/dist/core/ids.js.map +1 -1
- package/dist/core/layout.cjs.map +1 -1
- package/dist/core/layout.js +22 -1
- package/dist/core/layout.js.map +1 -1
- package/dist/core/polar.cjs.map +1 -1
- package/dist/core/polar.js +13 -1
- package/dist/core/polar.js.map +1 -1
- package/dist/core/responsive.cjs.map +1 -1
- package/dist/core/responsive.js +20 -1
- package/dist/core/responsive.js.map +1 -1
- package/dist/core/series-id.cjs.map +1 -1
- package/dist/core/series-id.js +7 -1
- package/dist/core/series-id.js.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js +9 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.js +13 -1
- package/dist/interaction/announcer.cjs.map +1 -1
- package/dist/interaction/announcer.js +25 -1
- package/dist/interaction/announcer.js.map +1 -1
- package/dist/interaction/crosshair.cjs.map +1 -1
- package/dist/interaction/crosshair.js +37 -1
- package/dist/interaction/crosshair.js.map +1 -1
- package/dist/interaction/events.cjs.map +1 -1
- package/dist/interaction/events.js +11 -1
- package/dist/interaction/events.js.map +1 -1
- package/dist/interaction/legend.cjs.map +1 -1
- package/dist/interaction/legend.js +31 -1
- package/dist/interaction/legend.js.map +1 -1
- package/dist/interaction/scatter-interaction.cjs.map +1 -1
- package/dist/interaction/scatter-interaction.js +105 -1
- package/dist/interaction/scatter-interaction.js.map +1 -1
- package/dist/interaction/series-interaction.cjs.map +1 -1
- package/dist/interaction/series-interaction.js +163 -1
- package/dist/interaction/series-interaction.js.map +1 -1
- package/dist/interaction/tooltip.cjs +1 -1
- package/dist/interaction/tooltip.cjs.map +1 -1
- package/dist/interaction/tooltip.js +87 -1
- package/dist/interaction/tooltip.js.map +1 -1
- package/dist/prism.cjs +1 -1
- package/dist/prism.cjs.map +1 -1
- package/dist/prism.iife.js +1 -1
- package/dist/prism.iife.js.map +1 -1
- package/dist/prism.js +2930 -1
- package/dist/prism.js.map +1 -1
- package/dist/scales/band.cjs.map +1 -1
- package/dist/scales/band.js +39 -1
- package/dist/scales/band.js.map +1 -1
- package/dist/scales/linear.cjs.map +1 -1
- package/dist/scales/linear.js +43 -1
- package/dist/scales/linear.js.map +1 -1
- package/dist/scales/time.cjs.map +1 -1
- package/dist/scales/time.js +61 -1
- package/dist/scales/time.js.map +1 -1
- package/dist/svg/element.cjs +1 -1
- package/dist/svg/element.cjs.map +1 -1
- package/dist/svg/element.js +16 -1
- package/dist/svg/element.js.map +1 -1
- package/dist/svg/path.cjs.map +1 -1
- package/dist/svg/path.js +48 -1
- package/dist/svg/path.js.map +1 -1
- package/dist/svg/text.cjs.map +1 -1
- package/dist/svg/text.js +13 -1
- package/dist/svg/text.js.map +1 -1
- package/dist/theme/index.cjs.map +1 -1
- package/dist/theme/index.js +37 -1
- package/dist/theme/index.js.map +1 -1
- package/package.json +6 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Helmuth Saatkamp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/_dev.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/** @internal: Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":"AASA,SAAgB,KAAK,EAAmB,CAExC,CAGA,SAAgB,QAAQ,EAAsB,CAE9C"}
|
|
1
|
+
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/** @internal: Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":"AASA,SAAgB,KAAK,EAAmB,CAExC,CAGA,SAAgB,QAAQ,EAAsB,CAE9C,C"}
|
package/dist/_dev.js
CHANGED
package/dist/_dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/** @internal: Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":"AASA,SAAgB,KAAK,
|
|
1
|
+
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/** @internal: Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":";AASA,SAAgB,KAAK,GAAmB,CAExC;AAGA,SAAgB,QAAQ,GAAsB,CAE9C"}
|
package/dist/_tappers.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_tappers.cjs","names":[],"sources":["../src/_tappers.ts"],"sourcesContent":["/**\n * Shared `tap()` machinery for chart handles.\n *\n * @internal Private to the package: consumers observe charts through\n * `ChartHandle.tap()`, never through this module.\n */\n\nexport interface Tappers<E extends { readonly type: string }> {\n /** Delivers `event` to every registered handler, swallowing handler errors. */\n emit(event: E): void;\n /** Clears every handler; later `tap()` calls return a no-op unsubscribe. */\n stop(): void;\n tap(handler: (event: E) => void, options?: { readonly signal?: AbortSignal }): () => void;\n}\n\nexport function createTappers<E extends { readonly type: string }>(): Tappers<E> {\n const tappers = new Set<(event: E) => void>();\n let stopped = false;\n\n return {\n emit(event) {\n // Zero-overhead guard: observation costs nothing while nobody is watching.\n if (tappers.size === 0) return;\n\n for (const handler of tappers) {\n try {\n handler(event);\n } catch {\n // Observability must never affect chart behavior.\n }\n }\n },\n stop() {\n stopped = true;\n tappers.clear();\n },\n tap(handler, options) {\n if (stopped || options?.signal?.aborted) return () => {};\n\n tappers.add(handler);\n\n const detach = (): void => {\n tappers.delete(handler);\n };\n\n options?.signal?.addEventListener('abort', detach, { once: true });\n\n return detach;\n },\n };\n}\n"],"mappings":"AAeA,SAAgB,eAAiE,CAC/E,
|
|
1
|
+
{"version":3,"file":"_tappers.cjs","names":["tappers","stopped","handler","event","options"],"sources":["../src/_tappers.ts"],"sourcesContent":["/**\n * Shared `tap()` machinery for chart handles.\n *\n * @internal Private to the package: consumers observe charts through\n * `ChartHandle.tap()`, never through this module.\n */\n\nexport interface Tappers<E extends { readonly type: string }> {\n /** Delivers `event` to every registered handler, swallowing handler errors. */\n emit(event: E): void;\n /** Clears every handler; later `tap()` calls return a no-op unsubscribe. */\n stop(): void;\n tap(handler: (event: E) => void, options?: { readonly signal?: AbortSignal }): () => void;\n}\n\nexport function createTappers<E extends { readonly type: string }>(): Tappers<E> {\n const tappers = new Set<(event: E) => void>();\n let stopped = false;\n\n return {\n emit(event) {\n // Zero-overhead guard: observation costs nothing while nobody is watching.\n if (tappers.size === 0) return;\n\n for (const handler of tappers) {\n try {\n handler(event);\n } catch {\n // Observability must never affect chart behavior.\n }\n }\n },\n stop() {\n stopped = true;\n tappers.clear();\n },\n tap(handler, options) {\n if (stopped || options?.signal?.aborted) return () => {};\n\n tappers.add(handler);\n\n const detach = (): void => {\n tappers.delete(handler);\n };\n\n options?.signal?.addEventListener('abort', detach, { once: true });\n\n return detach;\n },\n };\n}\n"],"mappings":"AAeA,SAAgB,eAAiE,CAC/E,IAAMA,EAAU,IAAI,IAChBC,EAAU,GAEd,MAAO,CACL,KAAK,EAAO,CAEV,GAAID,EAAQ,OAAS,EAErB,IAAK,IAAME,KAAWF,EACpB,GAAI,CACFE,EAAQC,CAAK,CACf,MAAQ,CAER,CAEJ,EACA,MAAO,CACL,EAAU,GACVH,EAAQ,MAAM,CAChB,EACA,IAAI,EAAS,EAAS,CACpB,GAAIC,GAAWG,GAAS,QAAQ,QAAS,UAAa,CAAC,EAEvDJ,EAAQ,IAAIE,CAAO,EAEnB,IAAM,WAAqB,CACzBF,EAAQ,OAAOE,CAAO,CACxB,EAIA,OAFAE,GAAS,QAAQ,iBAAiB,QAAS,OAAQ,CAAE,KAAM,EAAK,CAAC,EAE1D,MACT,CACF,CACF,C"}
|
package/dist/_tappers.js
CHANGED
|
@@ -1,2 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/_tappers.ts
|
|
2
|
+
function createTappers() {
|
|
3
|
+
let e = /* @__PURE__ */ new Set(), t = !1;
|
|
4
|
+
return {
|
|
5
|
+
emit(t) {
|
|
6
|
+
if (e.size !== 0) for (let n of e) try {
|
|
7
|
+
n(t);
|
|
8
|
+
} catch {}
|
|
9
|
+
},
|
|
10
|
+
stop() {
|
|
11
|
+
t = !0, e.clear();
|
|
12
|
+
},
|
|
13
|
+
tap(n, r) {
|
|
14
|
+
if (t || r?.signal?.aborted) return () => {};
|
|
15
|
+
e.add(n);
|
|
16
|
+
let detach = () => {
|
|
17
|
+
e.delete(n);
|
|
18
|
+
};
|
|
19
|
+
return r?.signal?.addEventListener("abort", detach, { once: !0 }), detach;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { createTappers };
|
|
25
|
+
|
|
2
26
|
//# sourceMappingURL=_tappers.js.map
|
package/dist/_tappers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_tappers.js","names":[],"sources":["../src/_tappers.ts"],"sourcesContent":["/**\n * Shared `tap()` machinery for chart handles.\n *\n * @internal Private to the package: consumers observe charts through\n * `ChartHandle.tap()`, never through this module.\n */\n\nexport interface Tappers<E extends { readonly type: string }> {\n /** Delivers `event` to every registered handler, swallowing handler errors. */\n emit(event: E): void;\n /** Clears every handler; later `tap()` calls return a no-op unsubscribe. */\n stop(): void;\n tap(handler: (event: E) => void, options?: { readonly signal?: AbortSignal }): () => void;\n}\n\nexport function createTappers<E extends { readonly type: string }>(): Tappers<E> {\n const tappers = new Set<(event: E) => void>();\n let stopped = false;\n\n return {\n emit(event) {\n // Zero-overhead guard: observation costs nothing while nobody is watching.\n if (tappers.size === 0) return;\n\n for (const handler of tappers) {\n try {\n handler(event);\n } catch {\n // Observability must never affect chart behavior.\n }\n }\n },\n stop() {\n stopped = true;\n tappers.clear();\n },\n tap(handler, options) {\n if (stopped || options?.signal?.aborted) return () => {};\n\n tappers.add(handler);\n\n const detach = (): void => {\n tappers.delete(handler);\n };\n\n options?.signal?.addEventListener('abort', detach, { once: true });\n\n return detach;\n },\n };\n}\n"],"mappings":"AAeA,SAAgB,
|
|
1
|
+
{"version":3,"file":"_tappers.js","names":["tappers","stopped","handler","event","options"],"sources":["../src/_tappers.ts"],"sourcesContent":["/**\n * Shared `tap()` machinery for chart handles.\n *\n * @internal Private to the package: consumers observe charts through\n * `ChartHandle.tap()`, never through this module.\n */\n\nexport interface Tappers<E extends { readonly type: string }> {\n /** Delivers `event` to every registered handler, swallowing handler errors. */\n emit(event: E): void;\n /** Clears every handler; later `tap()` calls return a no-op unsubscribe. */\n stop(): void;\n tap(handler: (event: E) => void, options?: { readonly signal?: AbortSignal }): () => void;\n}\n\nexport function createTappers<E extends { readonly type: string }>(): Tappers<E> {\n const tappers = new Set<(event: E) => void>();\n let stopped = false;\n\n return {\n emit(event) {\n // Zero-overhead guard: observation costs nothing while nobody is watching.\n if (tappers.size === 0) return;\n\n for (const handler of tappers) {\n try {\n handler(event);\n } catch {\n // Observability must never affect chart behavior.\n }\n }\n },\n stop() {\n stopped = true;\n tappers.clear();\n },\n tap(handler, options) {\n if (stopped || options?.signal?.aborted) return () => {};\n\n tappers.add(handler);\n\n const detach = (): void => {\n tappers.delete(handler);\n };\n\n options?.signal?.addEventListener('abort', detach, { once: true });\n\n return detach;\n },\n };\n}\n"],"mappings":";AAeA,SAAgB,gBAAiE;CAC/E,IAAMA,oBAAU,IAAI,IAAwB,GACxCC,IAAU;CAEd,OAAO;EACL,KAAK,GAAO;GAEV,IAAID,EAAQ,SAAS,GAErB,KAAK,IAAME,KAAWF,GACpB,IAAI;IACF,EAAQG,CAAK;GACf,QAAQ,CAER;EAEJ;EACA,OAAO;GAEL,AADA,IAAU,IACVH,EAAQ,MAAM;EAChB;EACA,IAAI,GAAS,GAAS;GACpB,IAAIC,KAAWG,GAAS,QAAQ,SAAS,aAAa,CAAC;GAEvD,EAAQ,IAAIF,CAAO;GAEnB,IAAM,eAAqB;IACzB,EAAQ,OAAOA,CAAO;GACxB;GAIA,OAFAE,GAAS,QAAQ,iBAAiB,SAAS,QAAQ,EAAE,MAAM,GAAK,CAAC,GAE1D;EACT;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"easing.cjs","names":[],"sources":["../../src/animation/easing.ts"],"sourcesContent":["export type EasingFn = (t: number) => number;\n\n/** Overshoot coefficient behind CSS `cubic-bezier(.34, 1.56, .64, 1)`. */\nconst BACK_OVERSHOOT = 1.70158;\n\n/**\n * The named curves a {@link TransitionConfig} can select. The `ease-*` curves are cubic,\n * matching the feel of the CSS easing keywords; `expo-out` decelerates hard for data\n * reveals and `back-out` overshoots slightly for bar entrances.\n */\nexport const easings = {\n 'back-out': (t: number) => 1 + (BACK_OVERSHOOT + 1) * (t - 1) ** 3 + BACK_OVERSHOOT * (t - 1) ** 2,\n 'ease-in': (t: number) => t * t * t,\n 'ease-in-out': (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),\n 'ease-out': (t: number) => 1 - (1 - t) ** 3,\n 'expo-out': (t: number) => (t >= 1 ? 1 : 1 - 2 ** (-10 * t)),\n linear: (t: number) => t,\n} satisfies Record<string, EasingFn>;\n\n/** The literal names {@link resolveEasing} accepts, derived from {@link easings}. */\nexport type EasingName = keyof typeof easings;\n\nexport function resolveEasing(easing: string | ((t: number) => number) | undefined): EasingFn {\n if (typeof easing === 'function') return easing;\n\n // `Object.hasOwn` guards against `easing` being a prototype-chain key (e.g. `'__proto__'`,\n // `'constructor'`): a plain bracket lookup on those would silently resolve to an\n // `Object.prototype` value instead of `undefined`, which is either not callable (throws)\n // or callable but not an easing function (produces garbage interpolation).\n if (easing !== undefined && Object.hasOwn(easings, easing)) {\n return (easings as Record<string, EasingFn>)[easing];\n }\n\n return easings['ease-out'];\n}\n"],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"easing.cjs","names":["easings","t","easing"],"sources":["../../src/animation/easing.ts"],"sourcesContent":["export type EasingFn = (t: number) => number;\n\n/** Overshoot coefficient behind CSS `cubic-bezier(.34, 1.56, .64, 1)`. */\nconst BACK_OVERSHOOT = 1.70158;\n\n/**\n * The named curves a {@link TransitionConfig} can select. The `ease-*` curves are cubic,\n * matching the feel of the CSS easing keywords; `expo-out` decelerates hard for data\n * reveals and `back-out` overshoots slightly for bar entrances.\n */\nexport const easings = {\n 'back-out': (t: number) => 1 + (BACK_OVERSHOOT + 1) * (t - 1) ** 3 + BACK_OVERSHOOT * (t - 1) ** 2,\n 'ease-in': (t: number) => t * t * t,\n 'ease-in-out': (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),\n 'ease-out': (t: number) => 1 - (1 - t) ** 3,\n 'expo-out': (t: number) => (t >= 1 ? 1 : 1 - 2 ** (-10 * t)),\n linear: (t: number) => t,\n} satisfies Record<string, EasingFn>;\n\n/** The literal names {@link resolveEasing} accepts, derived from {@link easings}. */\nexport type EasingName = keyof typeof easings;\n\nexport function resolveEasing(easing: string | ((t: number) => number) | undefined): EasingFn {\n if (typeof easing === 'function') return easing;\n\n // `Object.hasOwn` guards against `easing` being a prototype-chain key (e.g. `'__proto__'`,\n // `'constructor'`): a plain bracket lookup on those would silently resolve to an\n // `Object.prototype` value instead of `undefined`, which is either not callable (throws)\n // or callable but not an easing function (produces garbage interpolation).\n if (easing !== undefined && Object.hasOwn(easings, easing)) {\n return (easings as Record<string, EasingFn>)[easing];\n }\n\n return easings['ease-out'];\n}\n"],"mappings":"AAGA,IAOaA,EAAU,CACrB,WAAa,GAAc,EAAK,SAAuBC,EAAI,IAAM,EAAI,SAAkBA,EAAI,IAAM,EACjG,UAAY,GAAcA,EAAIA,EAAIA,EAClC,cAAgB,GAAeA,EAAI,GAAM,EAAIA,EAAIA,EAAIA,EAAI,GAAK,GAAKA,EAAI,IAAM,EAAI,EACjF,WAAa,GAAc,GAAK,EAAIA,IAAM,EAC1C,WAAa,GAAeA,GAAK,EAAI,EAAI,EAAI,IAAM,IAAMA,GACzD,OAAS,GAAcA,CACzB,EAKA,SAAgB,cAAc,EAAgE,CAW5F,OAVI,OAAOC,GAAW,WAAmBA,EAMrCA,IAAW,IAAA,IAAa,OAAO,OAAOF,EAASE,CAAM,EAC/CF,EAAqCE,GAGxCF,EAAQ,WACjB,C"}
|
package/dist/animation/easing.js
CHANGED
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/animation/easing.ts
|
|
2
|
+
var e = {
|
|
3
|
+
"back-out": (e) => 1 + 2.70158 * (e - 1) ** 3 + 1.70158 * (e - 1) ** 2,
|
|
4
|
+
"ease-in": (e) => e * e * e,
|
|
5
|
+
"ease-in-out": (e) => e < .5 ? 4 * e * e * e : 1 - (-2 * e + 2) ** 3 / 2,
|
|
6
|
+
"ease-out": (e) => 1 - (1 - e) ** 3,
|
|
7
|
+
"expo-out": (e) => e >= 1 ? 1 : 1 - 2 ** (-10 * e),
|
|
8
|
+
linear: (e) => e
|
|
9
|
+
};
|
|
10
|
+
function resolveEasing(t) {
|
|
11
|
+
return typeof t == "function" ? t : t !== void 0 && Object.hasOwn(e, t) ? e[t] : e["ease-out"];
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { e as easings, resolveEasing };
|
|
15
|
+
|
|
2
16
|
//# sourceMappingURL=easing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"easing.js","names":[],"sources":["../../src/animation/easing.ts"],"sourcesContent":["export type EasingFn = (t: number) => number;\n\n/** Overshoot coefficient behind CSS `cubic-bezier(.34, 1.56, .64, 1)`. */\nconst BACK_OVERSHOOT = 1.70158;\n\n/**\n * The named curves a {@link TransitionConfig} can select. The `ease-*` curves are cubic,\n * matching the feel of the CSS easing keywords; `expo-out` decelerates hard for data\n * reveals and `back-out` overshoots slightly for bar entrances.\n */\nexport const easings = {\n 'back-out': (t: number) => 1 + (BACK_OVERSHOOT + 1) * (t - 1) ** 3 + BACK_OVERSHOOT * (t - 1) ** 2,\n 'ease-in': (t: number) => t * t * t,\n 'ease-in-out': (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),\n 'ease-out': (t: number) => 1 - (1 - t) ** 3,\n 'expo-out': (t: number) => (t >= 1 ? 1 : 1 - 2 ** (-10 * t)),\n linear: (t: number) => t,\n} satisfies Record<string, EasingFn>;\n\n/** The literal names {@link resolveEasing} accepts, derived from {@link easings}. */\nexport type EasingName = keyof typeof easings;\n\nexport function resolveEasing(easing: string | ((t: number) => number) | undefined): EasingFn {\n if (typeof easing === 'function') return easing;\n\n // `Object.hasOwn` guards against `easing` being a prototype-chain key (e.g. `'__proto__'`,\n // `'constructor'`): a plain bracket lookup on those would silently resolve to an\n // `Object.prototype` value instead of `undefined`, which is either not callable (throws)\n // or callable but not an easing function (produces garbage interpolation).\n if (easing !== undefined && Object.hasOwn(easings, easing)) {\n return (easings as Record<string, EasingFn>)[easing];\n }\n\n return easings['ease-out'];\n}\n"],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"easing.js","names":["easings","t","easing"],"sources":["../../src/animation/easing.ts"],"sourcesContent":["export type EasingFn = (t: number) => number;\n\n/** Overshoot coefficient behind CSS `cubic-bezier(.34, 1.56, .64, 1)`. */\nconst BACK_OVERSHOOT = 1.70158;\n\n/**\n * The named curves a {@link TransitionConfig} can select. The `ease-*` curves are cubic,\n * matching the feel of the CSS easing keywords; `expo-out` decelerates hard for data\n * reveals and `back-out` overshoots slightly for bar entrances.\n */\nexport const easings = {\n 'back-out': (t: number) => 1 + (BACK_OVERSHOOT + 1) * (t - 1) ** 3 + BACK_OVERSHOOT * (t - 1) ** 2,\n 'ease-in': (t: number) => t * t * t,\n 'ease-in-out': (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),\n 'ease-out': (t: number) => 1 - (1 - t) ** 3,\n 'expo-out': (t: number) => (t >= 1 ? 1 : 1 - 2 ** (-10 * t)),\n linear: (t: number) => t,\n} satisfies Record<string, EasingFn>;\n\n/** The literal names {@link resolveEasing} accepts, derived from {@link easings}. */\nexport type EasingName = keyof typeof easings;\n\nexport function resolveEasing(easing: string | ((t: number) => number) | undefined): EasingFn {\n if (typeof easing === 'function') return easing;\n\n // `Object.hasOwn` guards against `easing` being a prototype-chain key (e.g. `'__proto__'`,\n // `'constructor'`): a plain bracket lookup on those would silently resolve to an\n // `Object.prototype` value instead of `undefined`, which is either not callable (throws)\n // or callable but not an easing function (produces garbage interpolation).\n if (easing !== undefined && Object.hasOwn(easings, easing)) {\n return (easings as Record<string, EasingFn>)[easing];\n }\n\n return easings['ease-out'];\n}\n"],"mappings":";AAGA,IAOaA,IAAU;CACrB,aAAa,MAAc,IAAK,WAAuBC,IAAI,MAAM,IAAI,WAAkBA,IAAI,MAAM;CACjG,YAAY,MAAcA,IAAIA,IAAIA;CAClC,gBAAgB,MAAeA,IAAI,KAAM,IAAIA,IAAIA,IAAIA,IAAI,KAAK,KAAKA,IAAI,MAAM,IAAI;CACjF,aAAa,MAAc,KAAK,IAAIA,MAAM;CAC1C,aAAa,MAAeA,KAAK,IAAI,IAAI,IAAI,MAAM,MAAMA;CACzD,SAAS,MAAcA;AACzB;AAKA,SAAgB,cAAc,GAAgE;CAW5F,OAVI,OAAOC,KAAW,aAAmBA,IAMrCA,MAAW,KAAA,KAAa,OAAO,OAAOF,GAASE,CAAM,IAC/CF,EAAqCE,KAGxCF,EAAQ;AACjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"motion.cjs","names":[],"sources":["../../src/animation/motion.ts"],"sourcesContent":["import type { TransitionConfig, TransitionOption } from '../types';\n\n/** Duration (ms) every chart uses when motion is enabled without an explicit `duration`. */\nexport const DEFAULT_DURATION = 300;\n\n/**\n * Resolves a user-facing `transition` option into concrete motion values.\n *\n * - `false` disables motion entirely: renderers apply their final state synchronously.\n * - `true` (or omitted) enables motion with the chart's `defaultDuration`/`defaultStagger`.\n * - `preference: 'system'` (the default) disables motion when the user prefers reduced motion.\n */\nexport function resolveMotion(\n config?: TransitionOption,\n defaults?: { defaultDuration?: number; defaultStagger?: number },\n): TransitionConfig & { duration: number; stagger: number } {\n if (config === false) return { duration: 0, stagger: 0 };\n\n const options = config === true ? undefined : config;\n const preference = options?.preference ?? 'system';\n const reduced = typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n const duration =\n preference === 'never' || (preference === 'system' && reduced)\n ? 0\n : (options?.duration ?? defaults?.defaultDuration ?? DEFAULT_DURATION);\n\n return { ...options, duration, stagger: Math.max(0, options?.stagger ?? defaults?.defaultStagger ?? 0) };\n}\n"],"mappings":"AAYA,SAAgB,cACd,EACA,EAC0D,CAC1D,
|
|
1
|
+
{"version":3,"file":"motion.cjs","names":["config","options","preference","reduced","duration","defaults"],"sources":["../../src/animation/motion.ts"],"sourcesContent":["import type { TransitionConfig, TransitionOption } from '../types';\n\n/** Duration (ms) every chart uses when motion is enabled without an explicit `duration`. */\nexport const DEFAULT_DURATION = 300;\n\n/**\n * Resolves a user-facing `transition` option into concrete motion values.\n *\n * - `false` disables motion entirely: renderers apply their final state synchronously.\n * - `true` (or omitted) enables motion with the chart's `defaultDuration`/`defaultStagger`.\n * - `preference: 'system'` (the default) disables motion when the user prefers reduced motion.\n */\nexport function resolveMotion(\n config?: TransitionOption,\n defaults?: { defaultDuration?: number; defaultStagger?: number },\n): TransitionConfig & { duration: number; stagger: number } {\n if (config === false) return { duration: 0, stagger: 0 };\n\n const options = config === true ? undefined : config;\n const preference = options?.preference ?? 'system';\n const reduced = typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n const duration =\n preference === 'never' || (preference === 'system' && reduced)\n ? 0\n : (options?.duration ?? defaults?.defaultDuration ?? DEFAULT_DURATION);\n\n return { ...options, duration, stagger: Math.max(0, options?.stagger ?? defaults?.defaultStagger ?? 0) };\n}\n"],"mappings":"AAYA,SAAgB,cACd,EACA,EAC0D,CAC1D,GAAIA,IAAW,GAAO,MAAO,CAAE,SAAU,EAAG,QAAS,CAAE,EAEvD,IAAMC,EAAUD,IAAW,GAAO,IAAA,GAAYA,EACxCE,EAAaD,GAAS,YAAc,SACpCE,EAAU,OAAO,WAAe,KAAe,WAAW,kCAAkC,CAAC,CAAC,QAC9FC,EACJF,IAAe,SAAYA,IAAe,UAAYC,EAClD,EACCF,GAAS,UAAYI,GAAU,iBAAA,IAEtC,MAAO,CAAE,GAAGJ,EAAS,WAAU,QAAS,KAAK,IAAI,EAAGA,GAAS,SAAWI,GAAU,gBAAkB,CAAC,CAAE,CACzG,C"}
|
package/dist/animation/motion.js
CHANGED
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
function resolveMotion(e,t)
|
|
1
|
+
function resolveMotion(e, t) {
|
|
2
|
+
if (e === !1) return {
|
|
3
|
+
duration: 0,
|
|
4
|
+
stagger: 0
|
|
5
|
+
};
|
|
6
|
+
let n = e === !0 ? void 0 : e, r = n?.preference ?? "system", i = typeof matchMedia < "u" && matchMedia("(prefers-reduced-motion: reduce)").matches, a = r === "never" || r === "system" && i ? 0 : n?.duration ?? t?.defaultDuration ?? 300;
|
|
7
|
+
return {
|
|
8
|
+
...n,
|
|
9
|
+
duration: a,
|
|
10
|
+
stagger: Math.max(0, n?.stagger ?? t?.defaultStagger ?? 0)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { resolveMotion };
|
|
15
|
+
|
|
2
16
|
//# sourceMappingURL=motion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"motion.js","names":[],"sources":["../../src/animation/motion.ts"],"sourcesContent":["import type { TransitionConfig, TransitionOption } from '../types';\n\n/** Duration (ms) every chart uses when motion is enabled without an explicit `duration`. */\nexport const DEFAULT_DURATION = 300;\n\n/**\n * Resolves a user-facing `transition` option into concrete motion values.\n *\n * - `false` disables motion entirely: renderers apply their final state synchronously.\n * - `true` (or omitted) enables motion with the chart's `defaultDuration`/`defaultStagger`.\n * - `preference: 'system'` (the default) disables motion when the user prefers reduced motion.\n */\nexport function resolveMotion(\n config?: TransitionOption,\n defaults?: { defaultDuration?: number; defaultStagger?: number },\n): TransitionConfig & { duration: number; stagger: number } {\n if (config === false) return { duration: 0, stagger: 0 };\n\n const options = config === true ? undefined : config;\n const preference = options?.preference ?? 'system';\n const reduced = typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n const duration =\n preference === 'never' || (preference === 'system' && reduced)\n ? 0\n : (options?.duration ?? defaults?.defaultDuration ?? DEFAULT_DURATION);\n\n return { ...options, duration, stagger: Math.max(0, options?.stagger ?? defaults?.defaultStagger ?? 0) };\n}\n"],"mappings":"AAYA,SAAgB,cACd,
|
|
1
|
+
{"version":3,"file":"motion.js","names":["config","options","preference","reduced","duration","defaults"],"sources":["../../src/animation/motion.ts"],"sourcesContent":["import type { TransitionConfig, TransitionOption } from '../types';\n\n/** Duration (ms) every chart uses when motion is enabled without an explicit `duration`. */\nexport const DEFAULT_DURATION = 300;\n\n/**\n * Resolves a user-facing `transition` option into concrete motion values.\n *\n * - `false` disables motion entirely: renderers apply their final state synchronously.\n * - `true` (or omitted) enables motion with the chart's `defaultDuration`/`defaultStagger`.\n * - `preference: 'system'` (the default) disables motion when the user prefers reduced motion.\n */\nexport function resolveMotion(\n config?: TransitionOption,\n defaults?: { defaultDuration?: number; defaultStagger?: number },\n): TransitionConfig & { duration: number; stagger: number } {\n if (config === false) return { duration: 0, stagger: 0 };\n\n const options = config === true ? undefined : config;\n const preference = options?.preference ?? 'system';\n const reduced = typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n const duration =\n preference === 'never' || (preference === 'system' && reduced)\n ? 0\n : (options?.duration ?? defaults?.defaultDuration ?? DEFAULT_DURATION);\n\n return { ...options, duration, stagger: Math.max(0, options?.stagger ?? defaults?.defaultStagger ?? 0) };\n}\n"],"mappings":"AAYA,SAAgB,cACd,GACA,GAC0D;CAC1D,IAAIA,MAAW,IAAO,OAAO;EAAE,UAAU;EAAG,SAAS;CAAE;CAEvD,IAAMC,IAAUD,MAAW,KAAO,KAAA,IAAYA,GACxCE,IAAaD,GAAS,cAAc,UACpCE,IAAU,OAAO,aAAe,OAAe,WAAW,kCAAkC,CAAC,CAAC,SAC9FC,IACJF,MAAe,WAAYA,MAAe,YAAYC,IAClD,IACCF,GAAS,YAAYI,GAAU,mBAAA;CAEtC,OAAO;EAAE,GAAGJ;EAAS;EAAU,SAAS,KAAK,IAAI,GAAGA,GAAS,WAAWI,GAAU,kBAAkB,CAAC;CAAE;AACzG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reveal.cjs","names":[],"sources":["../../src/animation/reveal.ts"],"sourcesContent":["import { uniqueId } from '../core/ids';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { TransitionConfig } from '../types';\nimport { resolveEasing } from './easing';\nimport { startTween } from './transition';\n\nconst activeReveals = new WeakMap<Element, () => void>();\n\nexport function cancelReveal(parent: Element): void {\n activeReveals.get(parent)?.();\n}\n\n/** Traces final line geometry without replacing its dash or per-datum styling. */\nexport function playTraceReveal(\n parent: SVGGElement,\n bounds: { height: number; width: number },\n paths: readonly { d: string; end: number; start: number }[],\n strokeWidth: number,\n motion: TransitionConfig & { duration: number },\n signal?: AbortSignal,\n): () => void {\n cancelReveal(parent);\n if (motion.duration <= 0 || signal?.aborted) return () => {};\n\n const maskId = uniqueId('prism-trace');\n const host = createSvgElement('defs');\n const padding = strokeWidth / 2;\n const mask = createSvgElement('mask', {\n height: bounds.height + strokeWidth,\n id: maskId,\n maskContentUnits: 'userSpaceOnUse',\n maskUnits: 'userSpaceOnUse',\n width: bounds.width + strokeWidth,\n x: -padding,\n y: -padding,\n });\n const traces = paths.map(({ d }) => {\n const trace = createSvgElement('path', {\n d,\n fill: 'none',\n pathLength: 1,\n stroke: 'white',\n 'stroke-dasharray': '1 1',\n 'stroke-dashoffset': 1,\n 'stroke-width': strokeWidth,\n });\n mask.appendChild(trace);\n return trace;\n });\n host.appendChild(mask);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('mask', `url(#${maskId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('mask');\n host.remove();\n signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: 1,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n const e = progress(0);\n for (const [i, trace] of traces.entries()) {\n const { start, end } = paths[i];\n const revealed = Math.max(0, Math.min(1, (e - start) / (end - start)));\n trace.setAttribute('stroke-dashoffset', String(1 - revealed));\n }\n },\n signal,\n });\n return finish;\n}\n\nexport interface GrowRevealLane {\n anchor: number;\n height: number;\n width: number;\n x: number;\n y: number;\n}\n\n/** Reveals finished bars from their own baseline without distorting rounded corners. */\nexport function playGrowReveal(\n parent: SVGGElement,\n lanes: readonly GrowRevealLane[],\n paintFinal: () => void,\n motion: TransitionConfig & { duration: number },\n options: { axis: 'x' | 'y'; signal?: AbortSignal; stagger?: number },\n): () => void {\n cancelReveal(parent);\n paintFinal();\n if (motion.duration <= 0 || lanes.length === 0 || options.signal?.aborted) return () => {};\n\n const clipId = uniqueId('prism-reveal');\n const host = createSvgElement('defs');\n const clipPath = createSvgElement('clipPath', { id: clipId });\n const rects = lanes.map((lane) => {\n const rect = createSvgElement('rect', { height: 0, width: 0, x: lane.x, y: lane.y });\n clipPath.appendChild(rect);\n return rect;\n });\n host.appendChild(clipPath);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('clip-path', `url(#${clipId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('clip-path');\n host.remove();\n options.signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n options.signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: lanes.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n for (const [i, rect] of rects.entries()) {\n const lane = lanes[i];\n const e = Math.max(0, Math.min(1, progress(i)));\n if (options.axis === 'y') {\n const top = lane.anchor + (lane.y - lane.anchor) * e;\n const bottom = lane.anchor + (lane.y + lane.height - lane.anchor) * e;\n setAttributes(rect, { height: Math.max(0, bottom - top), width: lane.width, y: top });\n } else {\n const left = lane.anchor + (lane.x - lane.anchor) * e;\n const right = lane.anchor + (lane.x + lane.width - lane.anchor) * e;\n setAttributes(rect, { height: lane.height, width: Math.max(0, right - left), x: left });\n }\n }\n },\n signal: options.signal,\n stagger: options.stagger,\n });\n return finish;\n}\n"],"mappings":"2HAMA,
|
|
1
|
+
{"version":3,"file":"reveal.cjs","names":["uniqueId","createSvgElement","startTween","resolveEasing","require_element","require_easing","require_transition","require_ids","activeReveals","parent","motion","signal","maskId","host","padding","strokeWidth","mask","bounds","traces","paths","trace","e","progress","i","revealed","start","end","paintFinal","lanes","options","clipId","clipPath","rects","rect","lane","top","bottom","left","right"],"sources":["../../src/animation/reveal.ts"],"sourcesContent":["import { uniqueId } from '../core/ids';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { TransitionConfig } from '../types';\nimport { resolveEasing } from './easing';\nimport { startTween } from './transition';\n\nconst activeReveals = new WeakMap<Element, () => void>();\n\nexport function cancelReveal(parent: Element): void {\n activeReveals.get(parent)?.();\n}\n\n/** Traces final line geometry without replacing its dash or per-datum styling. */\nexport function playTraceReveal(\n parent: SVGGElement,\n bounds: { height: number; width: number },\n paths: readonly { d: string; end: number; start: number }[],\n strokeWidth: number,\n motion: TransitionConfig & { duration: number },\n signal?: AbortSignal,\n): () => void {\n cancelReveal(parent);\n if (motion.duration <= 0 || signal?.aborted) return () => {};\n\n const maskId = uniqueId('prism-trace');\n const host = createSvgElement('defs');\n const padding = strokeWidth / 2;\n const mask = createSvgElement('mask', {\n height: bounds.height + strokeWidth,\n id: maskId,\n maskContentUnits: 'userSpaceOnUse',\n maskUnits: 'userSpaceOnUse',\n width: bounds.width + strokeWidth,\n x: -padding,\n y: -padding,\n });\n const traces = paths.map(({ d }) => {\n const trace = createSvgElement('path', {\n d,\n fill: 'none',\n pathLength: 1,\n stroke: 'white',\n 'stroke-dasharray': '1 1',\n 'stroke-dashoffset': 1,\n 'stroke-width': strokeWidth,\n });\n mask.appendChild(trace);\n return trace;\n });\n host.appendChild(mask);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('mask', `url(#${maskId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('mask');\n host.remove();\n signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: 1,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n const e = progress(0);\n for (const [i, trace] of traces.entries()) {\n const { start, end } = paths[i];\n const revealed = Math.max(0, Math.min(1, (e - start) / (end - start)));\n trace.setAttribute('stroke-dashoffset', String(1 - revealed));\n }\n },\n signal,\n });\n return finish;\n}\n\nexport interface GrowRevealLane {\n anchor: number;\n height: number;\n width: number;\n x: number;\n y: number;\n}\n\n/** Reveals finished bars from their own baseline without distorting rounded corners. */\nexport function playGrowReveal(\n parent: SVGGElement,\n lanes: readonly GrowRevealLane[],\n paintFinal: () => void,\n motion: TransitionConfig & { duration: number },\n options: { axis: 'x' | 'y'; signal?: AbortSignal; stagger?: number },\n): () => void {\n cancelReveal(parent);\n paintFinal();\n if (motion.duration <= 0 || lanes.length === 0 || options.signal?.aborted) return () => {};\n\n const clipId = uniqueId('prism-reveal');\n const host = createSvgElement('defs');\n const clipPath = createSvgElement('clipPath', { id: clipId });\n const rects = lanes.map((lane) => {\n const rect = createSvgElement('rect', { height: 0, width: 0, x: lane.x, y: lane.y });\n clipPath.appendChild(rect);\n return rect;\n });\n host.appendChild(clipPath);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('clip-path', `url(#${clipId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('clip-path');\n host.remove();\n options.signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n options.signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: lanes.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n for (const [i, rect] of rects.entries()) {\n const lane = lanes[i];\n const e = Math.max(0, Math.min(1, progress(i)));\n if (options.axis === 'y') {\n const top = lane.anchor + (lane.y - lane.anchor) * e;\n const bottom = lane.anchor + (lane.y + lane.height - lane.anchor) * e;\n setAttributes(rect, { height: Math.max(0, bottom - top), width: lane.width, y: top });\n } else {\n const left = lane.anchor + (lane.x - lane.anchor) * e;\n const right = lane.anchor + (lane.x + lane.width - lane.anchor) * e;\n setAttributes(rect, { height: lane.height, width: Math.max(0, right - left), x: left });\n }\n }\n },\n signal: options.signal,\n stagger: options.stagger,\n });\n return finish;\n}\n"],"mappings":"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"}
|
package/dist/animation/reveal.js
CHANGED
|
@@ -1,2 +1,98 @@
|
|
|
1
|
-
import{createSvgElement as e,setAttributes as t
|
|
1
|
+
import { createSvgElement as e, setAttributes as t } from "../svg/element.js";
|
|
2
|
+
import { resolveEasing as n } from "./easing.js";
|
|
3
|
+
import { startTween as r } from "./transition.js";
|
|
4
|
+
import { uniqueId as i } from "../core/ids.js";
|
|
5
|
+
//#region src/animation/reveal.ts
|
|
6
|
+
var a = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function cancelReveal(e) {
|
|
8
|
+
a.get(e)?.();
|
|
9
|
+
}
|
|
10
|
+
function playTraceReveal(t, o, s, c, l, u) {
|
|
11
|
+
if (cancelReveal(t), l.duration <= 0 || u?.aborted) return () => {};
|
|
12
|
+
let d = i("prism-trace"), f = e("defs"), p = c / 2, m = e("mask", {
|
|
13
|
+
height: o.height + c,
|
|
14
|
+
id: d,
|
|
15
|
+
maskContentUnits: "userSpaceOnUse",
|
|
16
|
+
maskUnits: "userSpaceOnUse",
|
|
17
|
+
width: o.width + c,
|
|
18
|
+
x: -p,
|
|
19
|
+
y: -p
|
|
20
|
+
}), h = s.map(({ d: t }) => {
|
|
21
|
+
let n = e("path", {
|
|
22
|
+
d: t,
|
|
23
|
+
fill: "none",
|
|
24
|
+
pathLength: 1,
|
|
25
|
+
stroke: "white",
|
|
26
|
+
"stroke-dasharray": "1 1",
|
|
27
|
+
"stroke-dashoffset": 1,
|
|
28
|
+
"stroke-width": c
|
|
29
|
+
});
|
|
30
|
+
return m.appendChild(n), n;
|
|
31
|
+
});
|
|
32
|
+
f.appendChild(m), t.insertBefore(f, t.firstChild), t.setAttribute("mask", `url(#${d})`);
|
|
33
|
+
let cancelTween = () => {}, finish = () => {
|
|
34
|
+
a.delete(t), t.removeAttribute("mask"), f.remove(), u?.removeEventListener("abort", finish), cancelTween();
|
|
35
|
+
};
|
|
36
|
+
return a.set(t, finish), u?.addEventListener("abort", finish, { once: !0 }), cancelTween = r({
|
|
37
|
+
count: 1,
|
|
38
|
+
duration: l.duration,
|
|
39
|
+
easing: n(l.easing),
|
|
40
|
+
onComplete: finish,
|
|
41
|
+
onFrame: (e) => {
|
|
42
|
+
let t = e(0);
|
|
43
|
+
for (let [e, n] of h.entries()) {
|
|
44
|
+
let { start: r, end: i } = s[e], a = Math.max(0, Math.min(1, (t - r) / (i - r)));
|
|
45
|
+
n.setAttribute("stroke-dashoffset", String(1 - a));
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
signal: u
|
|
49
|
+
}), finish;
|
|
50
|
+
}
|
|
51
|
+
function playGrowReveal(o, s, c, l, u) {
|
|
52
|
+
if (cancelReveal(o), c(), l.duration <= 0 || s.length === 0 || u.signal?.aborted) return () => {};
|
|
53
|
+
let d = i("prism-reveal"), f = e("defs"), p = e("clipPath", { id: d }), m = s.map((t) => {
|
|
54
|
+
let n = e("rect", {
|
|
55
|
+
height: 0,
|
|
56
|
+
width: 0,
|
|
57
|
+
x: t.x,
|
|
58
|
+
y: t.y
|
|
59
|
+
});
|
|
60
|
+
return p.appendChild(n), n;
|
|
61
|
+
});
|
|
62
|
+
f.appendChild(p), o.insertBefore(f, o.firstChild), o.setAttribute("clip-path", `url(#${d})`);
|
|
63
|
+
let cancelTween = () => {}, finish = () => {
|
|
64
|
+
a.delete(o), o.removeAttribute("clip-path"), f.remove(), u.signal?.removeEventListener("abort", finish), cancelTween();
|
|
65
|
+
};
|
|
66
|
+
return a.set(o, finish), u.signal?.addEventListener("abort", finish, { once: !0 }), cancelTween = r({
|
|
67
|
+
count: s.length,
|
|
68
|
+
duration: l.duration,
|
|
69
|
+
easing: n(l.easing),
|
|
70
|
+
onComplete: finish,
|
|
71
|
+
onFrame: (e) => {
|
|
72
|
+
for (let [n, r] of m.entries()) {
|
|
73
|
+
let i = s[n], a = Math.max(0, Math.min(1, e(n)));
|
|
74
|
+
if (u.axis === "y") {
|
|
75
|
+
let e = i.anchor + (i.y - i.anchor) * a, n = i.anchor + (i.y + i.height - i.anchor) * a;
|
|
76
|
+
t(r, {
|
|
77
|
+
height: Math.max(0, n - e),
|
|
78
|
+
width: i.width,
|
|
79
|
+
y: e
|
|
80
|
+
});
|
|
81
|
+
} else {
|
|
82
|
+
let e = i.anchor + (i.x - i.anchor) * a, n = i.anchor + (i.x + i.width - i.anchor) * a;
|
|
83
|
+
t(r, {
|
|
84
|
+
height: i.height,
|
|
85
|
+
width: Math.max(0, n - e),
|
|
86
|
+
x: e
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
signal: u.signal,
|
|
92
|
+
stagger: u.stagger
|
|
93
|
+
}), finish;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { cancelReveal, playGrowReveal, playTraceReveal };
|
|
97
|
+
|
|
2
98
|
//# sourceMappingURL=reveal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reveal.js","names":[],"sources":["../../src/animation/reveal.ts"],"sourcesContent":["import { uniqueId } from '../core/ids';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { TransitionConfig } from '../types';\nimport { resolveEasing } from './easing';\nimport { startTween } from './transition';\n\nconst activeReveals = new WeakMap<Element, () => void>();\n\nexport function cancelReveal(parent: Element): void {\n activeReveals.get(parent)?.();\n}\n\n/** Traces final line geometry without replacing its dash or per-datum styling. */\nexport function playTraceReveal(\n parent: SVGGElement,\n bounds: { height: number; width: number },\n paths: readonly { d: string; end: number; start: number }[],\n strokeWidth: number,\n motion: TransitionConfig & { duration: number },\n signal?: AbortSignal,\n): () => void {\n cancelReveal(parent);\n if (motion.duration <= 0 || signal?.aborted) return () => {};\n\n const maskId = uniqueId('prism-trace');\n const host = createSvgElement('defs');\n const padding = strokeWidth / 2;\n const mask = createSvgElement('mask', {\n height: bounds.height + strokeWidth,\n id: maskId,\n maskContentUnits: 'userSpaceOnUse',\n maskUnits: 'userSpaceOnUse',\n width: bounds.width + strokeWidth,\n x: -padding,\n y: -padding,\n });\n const traces = paths.map(({ d }) => {\n const trace = createSvgElement('path', {\n d,\n fill: 'none',\n pathLength: 1,\n stroke: 'white',\n 'stroke-dasharray': '1 1',\n 'stroke-dashoffset': 1,\n 'stroke-width': strokeWidth,\n });\n mask.appendChild(trace);\n return trace;\n });\n host.appendChild(mask);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('mask', `url(#${maskId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('mask');\n host.remove();\n signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: 1,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n const e = progress(0);\n for (const [i, trace] of traces.entries()) {\n const { start, end } = paths[i];\n const revealed = Math.max(0, Math.min(1, (e - start) / (end - start)));\n trace.setAttribute('stroke-dashoffset', String(1 - revealed));\n }\n },\n signal,\n });\n return finish;\n}\n\nexport interface GrowRevealLane {\n anchor: number;\n height: number;\n width: number;\n x: number;\n y: number;\n}\n\n/** Reveals finished bars from their own baseline without distorting rounded corners. */\nexport function playGrowReveal(\n parent: SVGGElement,\n lanes: readonly GrowRevealLane[],\n paintFinal: () => void,\n motion: TransitionConfig & { duration: number },\n options: { axis: 'x' | 'y'; signal?: AbortSignal; stagger?: number },\n): () => void {\n cancelReveal(parent);\n paintFinal();\n if (motion.duration <= 0 || lanes.length === 0 || options.signal?.aborted) return () => {};\n\n const clipId = uniqueId('prism-reveal');\n const host = createSvgElement('defs');\n const clipPath = createSvgElement('clipPath', { id: clipId });\n const rects = lanes.map((lane) => {\n const rect = createSvgElement('rect', { height: 0, width: 0, x: lane.x, y: lane.y });\n clipPath.appendChild(rect);\n return rect;\n });\n host.appendChild(clipPath);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('clip-path', `url(#${clipId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('clip-path');\n host.remove();\n options.signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n options.signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: lanes.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n for (const [i, rect] of rects.entries()) {\n const lane = lanes[i];\n const e = Math.max(0, Math.min(1, progress(i)));\n if (options.axis === 'y') {\n const top = lane.anchor + (lane.y - lane.anchor) * e;\n const bottom = lane.anchor + (lane.y + lane.height - lane.anchor) * e;\n setAttributes(rect, { height: Math.max(0, bottom - top), width: lane.width, y: top });\n } else {\n const left = lane.anchor + (lane.x - lane.anchor) * e;\n const right = lane.anchor + (lane.x + lane.width - lane.anchor) * e;\n setAttributes(rect, { height: lane.height, width: Math.max(0, right - left), x: left });\n }\n }\n },\n signal: options.signal,\n stagger: options.stagger,\n });\n return finish;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"reveal.js","names":["activeReveals","parent","motion","signal","maskId","uniqueId","host","createSvgElement","padding","strokeWidth","mask","bounds","traces","paths","trace","startTween","resolveEasing","e","progress","i","revealed","start","end","paintFinal","lanes","options","clipId","clipPath","rects","rect","lane","top","bottom","left","right"],"sources":["../../src/animation/reveal.ts"],"sourcesContent":["import { uniqueId } from '../core/ids';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { TransitionConfig } from '../types';\nimport { resolveEasing } from './easing';\nimport { startTween } from './transition';\n\nconst activeReveals = new WeakMap<Element, () => void>();\n\nexport function cancelReveal(parent: Element): void {\n activeReveals.get(parent)?.();\n}\n\n/** Traces final line geometry without replacing its dash or per-datum styling. */\nexport function playTraceReveal(\n parent: SVGGElement,\n bounds: { height: number; width: number },\n paths: readonly { d: string; end: number; start: number }[],\n strokeWidth: number,\n motion: TransitionConfig & { duration: number },\n signal?: AbortSignal,\n): () => void {\n cancelReveal(parent);\n if (motion.duration <= 0 || signal?.aborted) return () => {};\n\n const maskId = uniqueId('prism-trace');\n const host = createSvgElement('defs');\n const padding = strokeWidth / 2;\n const mask = createSvgElement('mask', {\n height: bounds.height + strokeWidth,\n id: maskId,\n maskContentUnits: 'userSpaceOnUse',\n maskUnits: 'userSpaceOnUse',\n width: bounds.width + strokeWidth,\n x: -padding,\n y: -padding,\n });\n const traces = paths.map(({ d }) => {\n const trace = createSvgElement('path', {\n d,\n fill: 'none',\n pathLength: 1,\n stroke: 'white',\n 'stroke-dasharray': '1 1',\n 'stroke-dashoffset': 1,\n 'stroke-width': strokeWidth,\n });\n mask.appendChild(trace);\n return trace;\n });\n host.appendChild(mask);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('mask', `url(#${maskId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('mask');\n host.remove();\n signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: 1,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n const e = progress(0);\n for (const [i, trace] of traces.entries()) {\n const { start, end } = paths[i];\n const revealed = Math.max(0, Math.min(1, (e - start) / (end - start)));\n trace.setAttribute('stroke-dashoffset', String(1 - revealed));\n }\n },\n signal,\n });\n return finish;\n}\n\nexport interface GrowRevealLane {\n anchor: number;\n height: number;\n width: number;\n x: number;\n y: number;\n}\n\n/** Reveals finished bars from their own baseline without distorting rounded corners. */\nexport function playGrowReveal(\n parent: SVGGElement,\n lanes: readonly GrowRevealLane[],\n paintFinal: () => void,\n motion: TransitionConfig & { duration: number },\n options: { axis: 'x' | 'y'; signal?: AbortSignal; stagger?: number },\n): () => void {\n cancelReveal(parent);\n paintFinal();\n if (motion.duration <= 0 || lanes.length === 0 || options.signal?.aborted) return () => {};\n\n const clipId = uniqueId('prism-reveal');\n const host = createSvgElement('defs');\n const clipPath = createSvgElement('clipPath', { id: clipId });\n const rects = lanes.map((lane) => {\n const rect = createSvgElement('rect', { height: 0, width: 0, x: lane.x, y: lane.y });\n clipPath.appendChild(rect);\n return rect;\n });\n host.appendChild(clipPath);\n parent.insertBefore(host, parent.firstChild);\n parent.setAttribute('clip-path', `url(#${clipId})`);\n\n let cancelTween: () => void = () => {};\n const finish = (): void => {\n activeReveals.delete(parent);\n parent.removeAttribute('clip-path');\n host.remove();\n options.signal?.removeEventListener('abort', finish);\n cancelTween();\n };\n activeReveals.set(parent, finish);\n options.signal?.addEventListener('abort', finish, { once: true });\n cancelTween = startTween({\n count: lanes.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: finish,\n onFrame: (progress) => {\n for (const [i, rect] of rects.entries()) {\n const lane = lanes[i];\n const e = Math.max(0, Math.min(1, progress(i)));\n if (options.axis === 'y') {\n const top = lane.anchor + (lane.y - lane.anchor) * e;\n const bottom = lane.anchor + (lane.y + lane.height - lane.anchor) * e;\n setAttributes(rect, { height: Math.max(0, bottom - top), width: lane.width, y: top });\n } else {\n const left = lane.anchor + (lane.x - lane.anchor) * e;\n const right = lane.anchor + (lane.x + lane.width - lane.anchor) * e;\n setAttributes(rect, { height: lane.height, width: Math.max(0, right - left), x: left });\n }\n }\n },\n signal: options.signal,\n stagger: options.stagger,\n });\n return finish;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition.cjs","names":[],"sources":["../../src/animation/transition.ts"],"sourcesContent":["import type { TransitionConfig } from '../types';\nimport type { EasingFn } from './easing';\nimport { resolveEasing } from './easing';\nimport { resolveMotion } from './motion';\nimport { tweenNumber } from './tween';\n\nexport interface AnimationTarget {\n attrs: Record<string, { from: number; to: number }>;\n el: SVGElement;\n}\n\nexport interface TweenOptions {\n /** Number of staggered lanes; the loop runs until the last lane finishes. */\n count: number;\n /** Milliseconds per lane. A non-positive value completes synchronously. */\n duration: number;\n easing: EasingFn;\n onComplete?: () => void;\n /**\n * Runs once per frame (and once synchronously for a zero-length tween). Receives a\n * `progress(lane)` resolver returning that lane's eased 0-1 value, so callers\n * interpolate their own values without re-deriving elapsed time.\n */\n onFrame: (progress: (lane: number) => number) => void;\n /** Aborted when the owning chart is disposed: cancels the in-flight frame. */\n signal?: AbortSignal;\n /** Per-lane delay in milliseconds; each lane starts `stagger` ms after the previous. */\n stagger?: number;\n}\n\n/**\n * The package's single `requestAnimationFrame` tween loop. Every animated surface\n * (bar, line, area, pie, radar, sparkline) drives its transition through here, so\n * disposal-correctness is enforced in exactly one place: an aborted `signal` cancels\n * the in-flight frame and stops rescheduling.\n *\n * Elapsed time comes from the timestamp the browser passes to the frame callback,\n * never a captured `performance.now()`. Returns a `cancel()` function for superseding\n * a tween before it ends.\n */\nexport function startTween(options: TweenOptions): () => void {\n const { count, duration, easing, stagger = 0, signal, onFrame, onComplete } = options;\n\n if (signal?.aborted) return () => {};\n\n // A zero-length (or reduced-motion) tween applies its final frame synchronously: no rAF.\n if (duration <= 0) {\n onFrame(() => 1);\n onComplete?.();\n\n return () => {};\n }\n\n if (count === 0) {\n onComplete?.();\n\n return () => {};\n }\n\n const totalDuration = duration + stagger * (count - 1);\n let startTime: number | null = null;\n let rafId: number | null = null;\n let cancelled = false;\n\n const cancel = (): void => {\n cancelled = true;\n\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n\n signal?.removeEventListener('abort', cancel);\n };\n\n const frame = (timestamp: number): void => {\n if (cancelled || signal?.aborted) return;\n\n if (startTime === null) startTime = timestamp;\n\n const elapsed = timestamp - startTime;\n\n onFrame((lane) => easing(Math.max(0, Math.min(1, (elapsed - lane * stagger) / duration))));\n\n if (elapsed < totalDuration) {\n rafId = requestAnimationFrame(frame);\n } else {\n rafId = null;\n signal?.removeEventListener('abort', cancel);\n onComplete?.();\n }\n };\n\n signal?.addEventListener('abort', cancel, { once: true });\n rafId = requestAnimationFrame(frame);\n\n return cancel;\n}\n\n/**\n * Runs a batch of numeric-attribute tweens through {@link startTween}, sharing one\n * `requestAnimationFrame` loop. Returns the loop's `cancel()` function.\n */\nexport function animate(\n targets: AnimationTarget[],\n config?: TransitionConfig,\n onComplete?: () => void,\n signal?: AbortSignal,\n): () => void {\n const motion = resolveMotion(config);\n\n return startTween({\n count: targets.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete,\n onFrame: (progress) => {\n for (const [lane, target] of targets.entries()) {\n const eased = progress(lane);\n\n for (const [attr, { from, to }] of Object.entries(target.attrs)) {\n target.el.setAttribute(attr, String(tweenNumber(from, to, eased)));\n }\n }\n },\n signal,\n stagger: motion.stagger,\n });\n}\n"],"mappings":"mFAwCA,SAAgB,WAAW,EAAmC,CAC5D,GAAM,CAAE,QAAO,WAAU,SAAQ,UAAU,EAAG,SAAQ,UAAS,
|
|
1
|
+
{"version":3,"file":"transition.cjs","names":["resolveMotion","resolveEasing","tweenNumber","require_easing","require_motion","require_tween","options","signal","duration","onFrame","onComplete","count","totalDuration","stagger","startTime","rafId","cancelled","timestamp","elapsed","easing","lane","motion","config","targets","target","eased","progress","attr","from","to"],"sources":["../../src/animation/transition.ts"],"sourcesContent":["import type { TransitionConfig } from '../types';\nimport type { EasingFn } from './easing';\nimport { resolveEasing } from './easing';\nimport { resolveMotion } from './motion';\nimport { tweenNumber } from './tween';\n\nexport interface AnimationTarget {\n attrs: Record<string, { from: number; to: number }>;\n el: SVGElement;\n}\n\nexport interface TweenOptions {\n /** Number of staggered lanes; the loop runs until the last lane finishes. */\n count: number;\n /** Milliseconds per lane. A non-positive value completes synchronously. */\n duration: number;\n easing: EasingFn;\n onComplete?: () => void;\n /**\n * Runs once per frame (and once synchronously for a zero-length tween). Receives a\n * `progress(lane)` resolver returning that lane's eased 0-1 value, so callers\n * interpolate their own values without re-deriving elapsed time.\n */\n onFrame: (progress: (lane: number) => number) => void;\n /** Aborted when the owning chart is disposed: cancels the in-flight frame. */\n signal?: AbortSignal;\n /** Per-lane delay in milliseconds; each lane starts `stagger` ms after the previous. */\n stagger?: number;\n}\n\n/**\n * The package's single `requestAnimationFrame` tween loop. Every animated surface\n * (bar, line, area, pie, radar, sparkline) drives its transition through here, so\n * disposal-correctness is enforced in exactly one place: an aborted `signal` cancels\n * the in-flight frame and stops rescheduling.\n *\n * Elapsed time comes from the timestamp the browser passes to the frame callback,\n * never a captured `performance.now()`. Returns a `cancel()` function for superseding\n * a tween before it ends.\n */\nexport function startTween(options: TweenOptions): () => void {\n const { count, duration, easing, stagger = 0, signal, onFrame, onComplete } = options;\n\n if (signal?.aborted) return () => {};\n\n // A zero-length (or reduced-motion) tween applies its final frame synchronously: no rAF.\n if (duration <= 0) {\n onFrame(() => 1);\n onComplete?.();\n\n return () => {};\n }\n\n if (count === 0) {\n onComplete?.();\n\n return () => {};\n }\n\n const totalDuration = duration + stagger * (count - 1);\n let startTime: number | null = null;\n let rafId: number | null = null;\n let cancelled = false;\n\n const cancel = (): void => {\n cancelled = true;\n\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n\n signal?.removeEventListener('abort', cancel);\n };\n\n const frame = (timestamp: number): void => {\n if (cancelled || signal?.aborted) return;\n\n if (startTime === null) startTime = timestamp;\n\n const elapsed = timestamp - startTime;\n\n onFrame((lane) => easing(Math.max(0, Math.min(1, (elapsed - lane * stagger) / duration))));\n\n if (elapsed < totalDuration) {\n rafId = requestAnimationFrame(frame);\n } else {\n rafId = null;\n signal?.removeEventListener('abort', cancel);\n onComplete?.();\n }\n };\n\n signal?.addEventListener('abort', cancel, { once: true });\n rafId = requestAnimationFrame(frame);\n\n return cancel;\n}\n\n/**\n * Runs a batch of numeric-attribute tweens through {@link startTween}, sharing one\n * `requestAnimationFrame` loop. Returns the loop's `cancel()` function.\n */\nexport function animate(\n targets: AnimationTarget[],\n config?: TransitionConfig,\n onComplete?: () => void,\n signal?: AbortSignal,\n): () => void {\n const motion = resolveMotion(config);\n\n return startTween({\n count: targets.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete,\n onFrame: (progress) => {\n for (const [lane, target] of targets.entries()) {\n const eased = progress(lane);\n\n for (const [attr, { from, to }] of Object.entries(target.attrs)) {\n target.el.setAttribute(attr, String(tweenNumber(from, to, eased)));\n }\n }\n },\n signal,\n stagger: motion.stagger,\n });\n}\n"],"mappings":"A,mFAwCA,SAAgB,WAAW,EAAmC,CAC5D,GAAM,CAAE,QAAO,WAAU,SAAQ,UAAU,EAAG,SAAQ,UAAS,cAAeM,EAE9E,GAAIC,GAAQ,QAAS,UAAa,CAAC,EAGnC,GAAIC,GAAY,EAId,OAHAC,MAAc,CAAC,EACfC,IAAa,MAEA,CAAC,EAGhB,GAAIC,IAAU,EAGZ,OAFAD,IAAa,MAEA,CAAC,EAGhB,IAAME,EAAgBJ,EAAWK,GAAWF,EAAQ,GAChDG,EAA2B,KAC3BC,EAAuB,KACvBC,EAAY,GAEV,WAAqB,CACzB,EAAY,GAERD,IAAU,OACZ,qBAAqBA,CAAK,EAC1B,EAAQ,MAGVR,GAAQ,oBAAoB,QAAS,MAAM,CAC7C,EAEM,MAAS,GAA4B,CACzC,GAAIS,GAAaT,GAAQ,QAAS,OAE9BO,IAAc,OAAM,EAAYG,GAEpC,IAAMC,EAAUD,EAAYH,EAE5BL,EAAS,GAASU,EAAO,KAAK,IAAI,EAAG,KAAK,IAAI,GAAID,EAAUE,EAAOP,GAAWL,CAAQ,CAAC,CAAC,CAAC,EAErFU,EAAUN,EACZ,EAAQ,sBAAsB,KAAK,GAEnC,EAAQ,KACRL,GAAQ,oBAAoB,QAAS,MAAM,EAC3CG,IAAa,EAEjB,EAKA,OAHAH,GAAQ,iBAAiB,QAAS,OAAQ,CAAE,KAAM,EAAK,CAAC,EACxD,EAAQ,sBAAsB,KAAK,EAE5B,MACT,CAMA,SAAgB,QACd,EACA,EACA,EACA,EACY,CACZ,IAAMc,EAASrB,EAAAA,cAAcsB,CAAM,EAEnC,OAAO,WAAW,CAChB,MAAOC,EAAQ,OACf,SAAUF,EAAO,SACjB,OAAQpB,EAAAA,cAAcoB,EAAO,MAAM,EACnC,aACA,QAAU,GAAa,CACrB,IAAK,GAAM,CAACD,EAAMI,KAAWD,EAAQ,QAAQ,EAAG,CAC9C,IAAME,EAAQC,EAASN,CAAI,EAE3B,IAAK,GAAM,CAACO,EAAM,CAAE,OAAM,SAAS,OAAO,QAAQH,EAAO,KAAK,EAC5DA,EAAO,GAAG,aAAaG,EAAM,OAAOzB,EAAAA,YAAY0B,EAAMC,EAAIJ,CAAK,CAAC,CAAC,CAErE,CACF,EACA,SACA,QAASJ,EAAO,OAClB,CAAC,CACH,C"}
|
|
@@ -1,2 +1,40 @@
|
|
|
1
|
-
import{resolveEasing as e}
|
|
1
|
+
import { resolveEasing as e } from "./easing.js";
|
|
2
|
+
import { resolveMotion as t } from "./motion.js";
|
|
3
|
+
import { tweenNumber as n } from "./tween.js";
|
|
4
|
+
//#region src/animation/transition.ts
|
|
5
|
+
function startTween(e) {
|
|
6
|
+
let { count: t, duration: n, easing: r, stagger: i = 0, signal: a, onFrame: o, onComplete: s } = e;
|
|
7
|
+
if (a?.aborted) return () => {};
|
|
8
|
+
if (n <= 0) return o(() => 1), s?.(), () => {};
|
|
9
|
+
if (t === 0) return s?.(), () => {};
|
|
10
|
+
let c = n + i * (t - 1), l = null, u = null, d = !1, cancel = () => {
|
|
11
|
+
d = !0, u !== null && (cancelAnimationFrame(u), u = null), a?.removeEventListener("abort", cancel);
|
|
12
|
+
}, frame = (e) => {
|
|
13
|
+
if (d || a?.aborted) return;
|
|
14
|
+
l === null && (l = e);
|
|
15
|
+
let t = e - l;
|
|
16
|
+
o((e) => r(Math.max(0, Math.min(1, (t - e * i) / n)))), t < c ? u = requestAnimationFrame(frame) : (u = null, a?.removeEventListener("abort", cancel), s?.());
|
|
17
|
+
};
|
|
18
|
+
return a?.addEventListener("abort", cancel, { once: !0 }), u = requestAnimationFrame(frame), cancel;
|
|
19
|
+
}
|
|
20
|
+
function animate(r, i, a, o) {
|
|
21
|
+
let s = t(i);
|
|
22
|
+
return startTween({
|
|
23
|
+
count: r.length,
|
|
24
|
+
duration: s.duration,
|
|
25
|
+
easing: e(s.easing),
|
|
26
|
+
onComplete: a,
|
|
27
|
+
onFrame: (e) => {
|
|
28
|
+
for (let [t, i] of r.entries()) {
|
|
29
|
+
let r = e(t);
|
|
30
|
+
for (let [e, { from: t, to: a }] of Object.entries(i.attrs)) i.el.setAttribute(e, String(n(t, a, r)));
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
signal: o,
|
|
34
|
+
stagger: s.stagger
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { animate, startTween };
|
|
39
|
+
|
|
2
40
|
//# sourceMappingURL=transition.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition.js","names":[],"sources":["../../src/animation/transition.ts"],"sourcesContent":["import type { TransitionConfig } from '../types';\nimport type { EasingFn } from './easing';\nimport { resolveEasing } from './easing';\nimport { resolveMotion } from './motion';\nimport { tweenNumber } from './tween';\n\nexport interface AnimationTarget {\n attrs: Record<string, { from: number; to: number }>;\n el: SVGElement;\n}\n\nexport interface TweenOptions {\n /** Number of staggered lanes; the loop runs until the last lane finishes. */\n count: number;\n /** Milliseconds per lane. A non-positive value completes synchronously. */\n duration: number;\n easing: EasingFn;\n onComplete?: () => void;\n /**\n * Runs once per frame (and once synchronously for a zero-length tween). Receives a\n * `progress(lane)` resolver returning that lane's eased 0-1 value, so callers\n * interpolate their own values without re-deriving elapsed time.\n */\n onFrame: (progress: (lane: number) => number) => void;\n /** Aborted when the owning chart is disposed: cancels the in-flight frame. */\n signal?: AbortSignal;\n /** Per-lane delay in milliseconds; each lane starts `stagger` ms after the previous. */\n stagger?: number;\n}\n\n/**\n * The package's single `requestAnimationFrame` tween loop. Every animated surface\n * (bar, line, area, pie, radar, sparkline) drives its transition through here, so\n * disposal-correctness is enforced in exactly one place: an aborted `signal` cancels\n * the in-flight frame and stops rescheduling.\n *\n * Elapsed time comes from the timestamp the browser passes to the frame callback,\n * never a captured `performance.now()`. Returns a `cancel()` function for superseding\n * a tween before it ends.\n */\nexport function startTween(options: TweenOptions): () => void {\n const { count, duration, easing, stagger = 0, signal, onFrame, onComplete } = options;\n\n if (signal?.aborted) return () => {};\n\n // A zero-length (or reduced-motion) tween applies its final frame synchronously: no rAF.\n if (duration <= 0) {\n onFrame(() => 1);\n onComplete?.();\n\n return () => {};\n }\n\n if (count === 0) {\n onComplete?.();\n\n return () => {};\n }\n\n const totalDuration = duration + stagger * (count - 1);\n let startTime: number | null = null;\n let rafId: number | null = null;\n let cancelled = false;\n\n const cancel = (): void => {\n cancelled = true;\n\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n\n signal?.removeEventListener('abort', cancel);\n };\n\n const frame = (timestamp: number): void => {\n if (cancelled || signal?.aborted) return;\n\n if (startTime === null) startTime = timestamp;\n\n const elapsed = timestamp - startTime;\n\n onFrame((lane) => easing(Math.max(0, Math.min(1, (elapsed - lane * stagger) / duration))));\n\n if (elapsed < totalDuration) {\n rafId = requestAnimationFrame(frame);\n } else {\n rafId = null;\n signal?.removeEventListener('abort', cancel);\n onComplete?.();\n }\n };\n\n signal?.addEventListener('abort', cancel, { once: true });\n rafId = requestAnimationFrame(frame);\n\n return cancel;\n}\n\n/**\n * Runs a batch of numeric-attribute tweens through {@link startTween}, sharing one\n * `requestAnimationFrame` loop. Returns the loop's `cancel()` function.\n */\nexport function animate(\n targets: AnimationTarget[],\n config?: TransitionConfig,\n onComplete?: () => void,\n signal?: AbortSignal,\n): () => void {\n const motion = resolveMotion(config);\n\n return startTween({\n count: targets.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete,\n onFrame: (progress) => {\n for (const [lane, target] of targets.entries()) {\n const eased = progress(lane);\n\n for (const [attr, { from, to }] of Object.entries(target.attrs)) {\n target.el.setAttribute(attr, String(tweenNumber(from, to, eased)));\n }\n }\n },\n signal,\n stagger: motion.stagger,\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"transition.js","names":["options","signal","duration","onFrame","onComplete","count","totalDuration","stagger","startTime","rafId","cancelled","timestamp","elapsed","easing","lane","motion","resolveMotion","config","targets","resolveEasing","target","eased","progress","attr","tweenNumber","from","to"],"sources":["../../src/animation/transition.ts"],"sourcesContent":["import type { TransitionConfig } from '../types';\nimport type { EasingFn } from './easing';\nimport { resolveEasing } from './easing';\nimport { resolveMotion } from './motion';\nimport { tweenNumber } from './tween';\n\nexport interface AnimationTarget {\n attrs: Record<string, { from: number; to: number }>;\n el: SVGElement;\n}\n\nexport interface TweenOptions {\n /** Number of staggered lanes; the loop runs until the last lane finishes. */\n count: number;\n /** Milliseconds per lane. A non-positive value completes synchronously. */\n duration: number;\n easing: EasingFn;\n onComplete?: () => void;\n /**\n * Runs once per frame (and once synchronously for a zero-length tween). Receives a\n * `progress(lane)` resolver returning that lane's eased 0-1 value, so callers\n * interpolate their own values without re-deriving elapsed time.\n */\n onFrame: (progress: (lane: number) => number) => void;\n /** Aborted when the owning chart is disposed: cancels the in-flight frame. */\n signal?: AbortSignal;\n /** Per-lane delay in milliseconds; each lane starts `stagger` ms after the previous. */\n stagger?: number;\n}\n\n/**\n * The package's single `requestAnimationFrame` tween loop. Every animated surface\n * (bar, line, area, pie, radar, sparkline) drives its transition through here, so\n * disposal-correctness is enforced in exactly one place: an aborted `signal` cancels\n * the in-flight frame and stops rescheduling.\n *\n * Elapsed time comes from the timestamp the browser passes to the frame callback,\n * never a captured `performance.now()`. Returns a `cancel()` function for superseding\n * a tween before it ends.\n */\nexport function startTween(options: TweenOptions): () => void {\n const { count, duration, easing, stagger = 0, signal, onFrame, onComplete } = options;\n\n if (signal?.aborted) return () => {};\n\n // A zero-length (or reduced-motion) tween applies its final frame synchronously: no rAF.\n if (duration <= 0) {\n onFrame(() => 1);\n onComplete?.();\n\n return () => {};\n }\n\n if (count === 0) {\n onComplete?.();\n\n return () => {};\n }\n\n const totalDuration = duration + stagger * (count - 1);\n let startTime: number | null = null;\n let rafId: number | null = null;\n let cancelled = false;\n\n const cancel = (): void => {\n cancelled = true;\n\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n\n signal?.removeEventListener('abort', cancel);\n };\n\n const frame = (timestamp: number): void => {\n if (cancelled || signal?.aborted) return;\n\n if (startTime === null) startTime = timestamp;\n\n const elapsed = timestamp - startTime;\n\n onFrame((lane) => easing(Math.max(0, Math.min(1, (elapsed - lane * stagger) / duration))));\n\n if (elapsed < totalDuration) {\n rafId = requestAnimationFrame(frame);\n } else {\n rafId = null;\n signal?.removeEventListener('abort', cancel);\n onComplete?.();\n }\n };\n\n signal?.addEventListener('abort', cancel, { once: true });\n rafId = requestAnimationFrame(frame);\n\n return cancel;\n}\n\n/**\n * Runs a batch of numeric-attribute tweens through {@link startTween}, sharing one\n * `requestAnimationFrame` loop. Returns the loop's `cancel()` function.\n */\nexport function animate(\n targets: AnimationTarget[],\n config?: TransitionConfig,\n onComplete?: () => void,\n signal?: AbortSignal,\n): () => void {\n const motion = resolveMotion(config);\n\n return startTween({\n count: targets.length,\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete,\n onFrame: (progress) => {\n for (const [lane, target] of targets.entries()) {\n const eased = progress(lane);\n\n for (const [attr, { from, to }] of Object.entries(target.attrs)) {\n target.el.setAttribute(attr, String(tweenNumber(from, to, eased)));\n }\n }\n },\n signal,\n stagger: motion.stagger,\n });\n}\n"],"mappings":";;;;AAwCA,SAAgB,WAAW,GAAmC;CAC5D,IAAM,EAAE,UAAO,aAAU,WAAQ,aAAU,GAAG,WAAQ,YAAS,kBAAeA;CAE9E,IAAIC,GAAQ,SAAS,aAAa,CAAC;CAGnC,IAAIC,KAAY,GAId,OAHAC,QAAc,CAAC,GACfC,IAAa,SAEA,CAAC;CAGhB,IAAIC,MAAU,GAGZ,OAFAD,IAAa,SAEA,CAAC;CAGhB,IAAME,IAAgBJ,IAAWK,KAAWF,IAAQ,IAChDG,IAA2B,MAC3BC,IAAuB,MACvBC,IAAY,IAEV,eAAqB;EAQzB,AAPA,IAAY,IAERD,MAAU,SACZ,qBAAqBA,CAAK,GAC1B,IAAQ,OAGVR,GAAQ,oBAAoB,SAAS,MAAM;CAC7C,GAEM,SAAS,MAA4B;EACzC,IAAIS,KAAaT,GAAQ,SAAS;EAElC,AAAIO,MAAc,SAAM,IAAYG;EAEpC,IAAMC,IAAUD,IAAYH;EAI5B,AAFAL,GAAS,MAASU,EAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAID,IAAUE,IAAOP,KAAWL,CAAQ,CAAC,CAAC,CAAC,GAErFU,IAAUN,IACZ,IAAQ,sBAAsB,KAAK,KAEnC,IAAQ,MACRL,GAAQ,oBAAoB,SAAS,MAAM,GAC3CG,IAAa;CAEjB;CAKA,OAHAH,GAAQ,iBAAiB,SAAS,QAAQ,EAAE,MAAM,GAAK,CAAC,GACxD,IAAQ,sBAAsB,KAAK,GAE5B;AACT;AAMA,SAAgB,QACd,GACA,GACA,GACA,GACY;CACZ,IAAMc,IAASC,EAAcC,CAAM;CAEnC,OAAO,WAAW;EAChB,OAAOC,EAAQ;EACf,UAAUH,EAAO;EACjB,QAAQI,EAAcJ,EAAO,MAAM;EACnC;EACA,UAAU,MAAa;GACrB,KAAK,IAAM,CAACD,GAAMM,MAAWF,EAAQ,QAAQ,GAAG;IAC9C,IAAMG,IAAQC,EAASR,CAAI;IAE3B,KAAK,IAAM,CAACS,GAAM,EAAE,SAAM,YAAS,OAAO,QAAQH,EAAO,KAAK,GAC5D,EAAO,GAAG,aAAaG,GAAM,OAAOC,EAAYC,GAAMC,GAAIL,CAAK,CAAC,CAAC;GAErE;EACF;EACA;EACA,SAASN,EAAO;CAClB,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tween.cjs","names":[],"sources":["../../src/animation/tween.ts"],"sourcesContent":["export function tweenNumber(from: number, to: number, t: number): number {\n return from + (to - from) * t;\n}\n"],"mappings":"AAAA,SAAgB,YAAY,EAAc,EAAY,EAAmB,CACvE,
|
|
1
|
+
{"version":3,"file":"tween.cjs","names":["from","to","t"],"sources":["../../src/animation/tween.ts"],"sourcesContent":["export function tweenNumber(from: number, to: number, t: number): number {\n return from + (to - from) * t;\n}\n"],"mappings":"AAAA,SAAgB,YAAY,EAAc,EAAY,EAAmB,CACvE,OAAOA,GAAQC,EAAKD,GAAQE,CAC9B,C"}
|
package/dist/animation/tween.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tween.js","names":[],"sources":["../../src/animation/tween.ts"],"sourcesContent":["export function tweenNumber(from: number, to: number, t: number): number {\n return from + (to - from) * t;\n}\n"],"mappings":"AAAA,SAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"tween.js","names":["from","to","t"],"sources":["../../src/animation/tween.ts"],"sourcesContent":["export function tweenNumber(from: number, to: number, t: number): number {\n return from + (to - from) * t;\n}\n"],"mappings":";AAAA,SAAgB,YAAY,GAAc,GAAY,GAAmB;CACvE,OAAOA,KAAQC,IAAKD,KAAQE;AAC9B"}
|