@vielzeug/prism 26.10.0 → 26.10.2
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/README.md +2 -2
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +1 -1
- package/dist/_dev.js.map +1 -1
- package/dist/animation/easing.cjs.map +1 -1
- package/dist/animation/easing.js.map +1 -1
- package/dist/axes/axis.cjs +1 -1
- package/dist/axes/axis.cjs.map +1 -1
- package/dist/axes/axis.d.ts +2 -2
- package/dist/axes/axis.d.ts.map +1 -1
- package/dist/axes/axis.js +1 -1
- package/dist/axes/axis.js.map +1 -1
- package/dist/axes/scale-utils.cjs.map +1 -1
- package/dist/axes/scale-utils.d.ts +1 -1
- package/dist/axes/scale-utils.js.map +1 -1
- package/dist/charts/area/area-chart.cjs +1 -1
- package/dist/charts/area/area-chart.cjs.map +1 -1
- package/dist/charts/area/area-chart.d.ts.map +1 -1
- package/dist/charts/area/area-chart.js +1 -1
- package/dist/charts/area/area-chart.js.map +1 -1
- package/dist/charts/area/area-renderer.cjs +1 -1
- package/dist/charts/area/area-renderer.cjs.map +1 -1
- package/dist/charts/area/area-renderer.d.ts +7 -2
- package/dist/charts/area/area-renderer.d.ts.map +1 -1
- package/dist/charts/area/area-renderer.js +1 -1
- package/dist/charts/area/area-renderer.js.map +1 -1
- package/dist/charts/bar/bar-chart.cjs +1 -1
- package/dist/charts/bar/bar-chart.cjs.map +1 -1
- package/dist/charts/bar/bar-chart.d.ts.map +1 -1
- package/dist/charts/bar/bar-chart.js +1 -1
- package/dist/charts/bar/bar-chart.js.map +1 -1
- package/dist/charts/bar/bar-hit-test.cjs +1 -1
- package/dist/charts/bar/bar-hit-test.cjs.map +1 -1
- package/dist/charts/bar/bar-hit-test.d.ts +0 -5
- package/dist/charts/bar/bar-hit-test.d.ts.map +1 -1
- package/dist/charts/bar/bar-hit-test.js +1 -1
- package/dist/charts/bar/bar-hit-test.js.map +1 -1
- package/dist/charts/bar/bar-renderer.cjs +1 -1
- package/dist/charts/bar/bar-renderer.cjs.map +1 -1
- package/dist/charts/bar/bar-renderer.d.ts +3 -1
- package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
- package/dist/charts/bar/bar-renderer.js +1 -1
- package/dist/charts/bar/bar-renderer.js.map +1 -1
- package/dist/charts/line/line-chart.cjs +1 -1
- package/dist/charts/line/line-chart.cjs.map +1 -1
- package/dist/charts/line/line-chart.d.ts.map +1 -1
- package/dist/charts/line/line-chart.js +1 -1
- package/dist/charts/line/line-chart.js.map +1 -1
- package/dist/charts/line/line-renderer.cjs +1 -1
- package/dist/charts/line/line-renderer.cjs.map +1 -1
- package/dist/charts/line/line-renderer.d.ts +6 -2
- package/dist/charts/line/line-renderer.d.ts.map +1 -1
- package/dist/charts/line/line-renderer.js +1 -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.d.ts.map +1 -1
- package/dist/charts/pie/pie-chart.js +1 -1
- package/dist/charts/pie/pie-chart.js.map +1 -1
- package/dist/charts/pie/pie-renderer.cjs +1 -1
- package/dist/charts/pie/pie-renderer.cjs.map +1 -1
- package/dist/charts/pie/pie-renderer.d.ts.map +1 -1
- package/dist/charts/pie/pie-renderer.js +1 -1
- package/dist/charts/pie/pie-renderer.js.map +1 -1
- package/dist/charts/radar/index.d.ts +2 -0
- package/dist/charts/radar/index.d.ts.map +1 -0
- package/dist/charts/radar/radar-chart.cjs +2 -0
- package/dist/charts/radar/radar-chart.cjs.map +1 -0
- package/dist/charts/radar/radar-chart.d.ts +3 -0
- package/dist/charts/radar/radar-chart.d.ts.map +1 -0
- package/dist/charts/radar/radar-chart.js +2 -0
- package/dist/charts/radar/radar-chart.js.map +1 -0
- package/dist/charts/radar/radar-geometry.cjs +2 -0
- package/dist/charts/radar/radar-geometry.cjs.map +1 -0
- package/dist/charts/radar/radar-geometry.d.ts +22 -0
- package/dist/charts/radar/radar-geometry.d.ts.map +1 -0
- package/dist/charts/radar/radar-geometry.js +2 -0
- package/dist/charts/radar/radar-geometry.js.map +1 -0
- package/dist/charts/sparkline/sparkline.cjs +1 -1
- package/dist/charts/sparkline/sparkline.cjs.map +1 -1
- package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
- package/dist/charts/sparkline/sparkline.js +1 -1
- package/dist/charts/sparkline/sparkline.js.map +1 -1
- package/dist/core/cartesian-scales.cjs +1 -1
- package/dist/core/cartesian-scales.cjs.map +1 -1
- package/dist/core/cartesian-scales.js +1 -1
- package/dist/core/cartesian-scales.js.map +1 -1
- package/dist/core/chart-base.cjs +1 -1
- package/dist/core/chart-base.cjs.map +1 -1
- package/dist/core/chart-base.d.ts +9 -0
- package/dist/core/chart-base.d.ts.map +1 -1
- package/dist/core/chart-base.js +1 -1
- package/dist/core/chart-base.js.map +1 -1
- package/dist/core/chart-scaffold.cjs +1 -1
- package/dist/core/chart-scaffold.cjs.map +1 -1
- package/dist/core/chart-scaffold.d.ts +7 -3
- package/dist/core/chart-scaffold.d.ts.map +1 -1
- package/dist/core/chart-scaffold.js +1 -1
- package/dist/core/chart-scaffold.js.map +1 -1
- package/dist/core/datum-style.cjs +2 -0
- package/dist/core/datum-style.cjs.map +1 -0
- package/dist/core/datum-style.d.ts +18 -0
- package/dist/core/datum-style.d.ts.map +1 -0
- package/dist/core/datum-style.js +2 -0
- package/dist/core/datum-style.js.map +1 -0
- package/dist/core/ids.cjs +2 -0
- package/dist/core/ids.cjs.map +1 -0
- package/dist/core/ids.d.ts +3 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +2 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/polar.cjs +2 -0
- package/dist/core/polar.cjs.map +1 -0
- package/dist/core/polar.d.ts +5 -0
- package/dist/core/polar.d.ts.map +1 -0
- package/dist/core/polar.js +2 -0
- package/dist/core/polar.js.map +1 -0
- package/dist/core/series-id.cjs +2 -0
- package/dist/core/series-id.cjs.map +1 -0
- package/dist/core/series-id.d.ts +8 -0
- package/dist/core/series-id.d.ts.map +1 -0
- package/dist/core/series-id.js +2 -0
- package/dist/core/series-id.js.map +1 -0
- package/dist/devtools/index.d.ts +1 -1
- package/dist/devtools.cjs.map +1 -1
- package/dist/devtools.js.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/interaction/announcer.cjs +2 -0
- package/dist/interaction/announcer.cjs.map +1 -0
- package/dist/interaction/announcer.d.ts +13 -0
- package/dist/interaction/announcer.d.ts.map +1 -0
- package/dist/interaction/announcer.js +2 -0
- package/dist/interaction/announcer.js.map +1 -0
- package/dist/interaction/crosshair.cjs +1 -1
- package/dist/interaction/crosshair.cjs.map +1 -1
- package/dist/interaction/crosshair.d.ts +1 -5
- package/dist/interaction/crosshair.d.ts.map +1 -1
- package/dist/interaction/crosshair.js +1 -1
- package/dist/interaction/crosshair.js.map +1 -1
- package/dist/interaction/series-interaction.cjs +1 -1
- package/dist/interaction/series-interaction.cjs.map +1 -1
- package/dist/interaction/series-interaction.d.ts +11 -1
- package/dist/interaction/series-interaction.d.ts.map +1 -1
- package/dist/interaction/series-interaction.js +1 -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.d.ts +12 -1
- package/dist/interaction/tooltip.d.ts.map +1 -1
- package/dist/interaction/tooltip.js +1 -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 +1 -1
- package/dist/prism.js.map +1 -1
- package/dist/scales/band.cjs.map +1 -1
- package/dist/scales/band.js.map +1 -1
- package/dist/scales/linear.cjs.map +1 -1
- package/dist/scales/linear.js.map +1 -1
- package/dist/scales/time.cjs.map +1 -1
- package/dist/scales/time.js.map +1 -1
- package/dist/svg/element.cjs.map +1 -1
- package/dist/svg/element.js.map +1 -1
- package/dist/svg/text.cjs +1 -1
- package/dist/svg/text.cjs.map +1 -1
- package/dist/svg/text.d.ts +1 -0
- package/dist/svg/text.d.ts.map +1 -1
- package/dist/svg/text.js +1 -1
- package/dist/svg/text.js.map +1 -1
- package/dist/theme/index.cjs.map +1 -1
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/prism.css +214 -7
- package/dist/types.d.ts +102 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"series-id.d.ts","sourceRoot":"","sources":["../../src/core/series-id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAElG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"series-id.js","names":[],"sources":["../../src/core/series-id.ts"],"sourcesContent":["import type { Series } from '../types';\n\n/**\n * Stable `data-series-id` value for a series group: the sanitized explicit\n * `id`, else the positional `series-<index>` fallback. Characters outside\n * `[A-Za-z0-9_-]` become `-` so the value is always attribute-safe.\n */\nexport function seriesDomId(series: Pick<Series, 'id' | 'name'> | undefined, index: number): string {\n return series?.id ? series.id.replace(/[^A-Za-z0-9_-]/g, '-') : `series-${index}`;\n}\n"],"mappings":"AAOA,SAAgB,YAAY,EAAiD,EAAuB,CAClG,OAAO,GAAQ,GAAK,EAAO,GAAG,QAAQ,kBAAmB,GAAG,EAAI,UAAU,GAC5E"}
|
package/dist/devtools/index.d.ts
CHANGED
package/dist/devtools.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.cjs","names":[],"sources":["../src/devtools/index.ts"],"sourcesContent":["/**\n * @vielzeug/prism
|
|
1
|
+
{"version":3,"file":"devtools.cjs","names":[],"sources":["../src/devtools/index.ts"],"sourcesContent":["/**\n * @vielzeug/prism: debug utilities for chart visualisation.\n *\n * Import from the dedicated sub-path so debug code is tree-shaken from\n * production bundles:\n * ```ts\n * import { debugChart } from '@vielzeug/prism/devtools';\n * ```\n *\n * Internal validation warnings (misuse of the public API) are emitted\n * automatically in development builds and live in the private `src/_dev.ts`\n * module. They are not part of this sub-path.\n */\n\nimport type { ChartHandle } from '../types';\n\n/** Options for {@link debugChart}. */\nexport interface DebugChartOptions {\n /**\n * Label used in log prefixes. Defaults to `'chart'`, producing `[prism:chart]`.\n * Useful when debugging multiple charts on the same page so their log output\n * can be distinguished:\n * ```ts\n * debugChart(createLineChart(el, config), { label: 'revenue' });\n * // [prism:revenue] mounted\n * ```\n */\n label?: string;\n}\n\n/**\n * Wraps an already-created {@link ChartHandle} with lifecycle logging pre-wired to\n * `console.debug`, imported from a dedicated sub-path so `console.debug` references\n * and the `ResizeObserver` it uses are tree-shaken from production bundles when this\n * sub-path is not imported.\n *\n * Logs the chart's mount, every resize (via its own `ResizeObserver` on `handle.el`,\n * independent of the chart's internal one), and disposal, each with `[prism:<label>]`\n * prefixes. Returns the same handle unchanged so it can wrap any `create*Chart()` call\n * in place.\n *\n * @example\n * ```ts\n * import { createLineChart } from '@vielzeug/prism';\n * import { debugChart } from '@vielzeug/prism/devtools';\n *\n * const chart = debugChart(createLineChart(container, config), { label: 'revenue' });\n * // [prism:revenue] mounted\n * // [prism:revenue] resized 600×300\n * chart.dispose();\n * // [prism:revenue] disposed\n * ```\n */\nexport function debugChart<T extends ChartHandle>(handle: T, options?: DebugChartOptions): T {\n const prefix = `[prism:${options?.label ?? 'chart'}]`;\n\n console.debug(`${prefix} mounted`);\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n\n if (entry) {\n const { height, width } = entry.contentRect;\n\n console.debug(`${prefix} resized ${Math.round(width)}×${Math.round(height)}`);\n }\n });\n\n resizeObserver.observe(handle.el);\n\n handle.disposalSignal.addEventListener(\n 'abort',\n () => {\n resizeObserver.disconnect();\n console.debug(`${prefix} disposed`);\n },\n { once: true },\n );\n\n return handle;\n}\n"],"mappings":"mEAqDA,SAAgB,WAAkC,EAAW,EAAgC,CAC3F,IAAM,EAAS,UAAU,GAAS,OAAS,QAAQ,GAEnD,QAAQ,MAAM,GAAG,EAAO,SAAS,EAEjC,IAAM,EAAiB,IAAI,eAAgB,GAAY,CACrD,IAAM,EAAQ,EAAQ,GAEtB,GAAI,EAAO,CACT,GAAM,CAAE,SAAQ,SAAU,EAAM,YAEhC,QAAQ,MAAM,GAAG,EAAO,YAAY,KAAK,MAAM,CAAK,EAAE,GAAG,KAAK,MAAM,CAAM,GAAG,CAC/E,CACF,CAAC,EAaD,OAXA,EAAe,QAAQ,EAAO,EAAE,EAEhC,EAAO,eAAe,iBACpB,YACM,CACJ,EAAe,WAAW,EAC1B,QAAQ,MAAM,GAAG,EAAO,UAAU,CACpC,EACA,CAAE,KAAM,EAAK,CACf,EAEO,CACT"}
|
package/dist/devtools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.js","names":[],"sources":["../src/devtools/index.ts"],"sourcesContent":["/**\n * @vielzeug/prism
|
|
1
|
+
{"version":3,"file":"devtools.js","names":[],"sources":["../src/devtools/index.ts"],"sourcesContent":["/**\n * @vielzeug/prism: debug utilities for chart visualisation.\n *\n * Import from the dedicated sub-path so debug code is tree-shaken from\n * production bundles:\n * ```ts\n * import { debugChart } from '@vielzeug/prism/devtools';\n * ```\n *\n * Internal validation warnings (misuse of the public API) are emitted\n * automatically in development builds and live in the private `src/_dev.ts`\n * module. They are not part of this sub-path.\n */\n\nimport type { ChartHandle } from '../types';\n\n/** Options for {@link debugChart}. */\nexport interface DebugChartOptions {\n /**\n * Label used in log prefixes. Defaults to `'chart'`, producing `[prism:chart]`.\n * Useful when debugging multiple charts on the same page so their log output\n * can be distinguished:\n * ```ts\n * debugChart(createLineChart(el, config), { label: 'revenue' });\n * // [prism:revenue] mounted\n * ```\n */\n label?: string;\n}\n\n/**\n * Wraps an already-created {@link ChartHandle} with lifecycle logging pre-wired to\n * `console.debug`, imported from a dedicated sub-path so `console.debug` references\n * and the `ResizeObserver` it uses are tree-shaken from production bundles when this\n * sub-path is not imported.\n *\n * Logs the chart's mount, every resize (via its own `ResizeObserver` on `handle.el`,\n * independent of the chart's internal one), and disposal, each with `[prism:<label>]`\n * prefixes. Returns the same handle unchanged so it can wrap any `create*Chart()` call\n * in place.\n *\n * @example\n * ```ts\n * import { createLineChart } from '@vielzeug/prism';\n * import { debugChart } from '@vielzeug/prism/devtools';\n *\n * const chart = debugChart(createLineChart(container, config), { label: 'revenue' });\n * // [prism:revenue] mounted\n * // [prism:revenue] resized 600×300\n * chart.dispose();\n * // [prism:revenue] disposed\n * ```\n */\nexport function debugChart<T extends ChartHandle>(handle: T, options?: DebugChartOptions): T {\n const prefix = `[prism:${options?.label ?? 'chart'}]`;\n\n console.debug(`${prefix} mounted`);\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n\n if (entry) {\n const { height, width } = entry.contentRect;\n\n console.debug(`${prefix} resized ${Math.round(width)}×${Math.round(height)}`);\n }\n });\n\n resizeObserver.observe(handle.el);\n\n handle.disposalSignal.addEventListener(\n 'abort',\n () => {\n resizeObserver.disconnect();\n console.debug(`${prefix} disposed`);\n },\n { once: true },\n );\n\n return handle;\n}\n"],"mappings":"AAqDA,SAAgB,WAAkC,EAAW,EAAgC,CAC3F,IAAM,EAAS,UAAU,GAAS,OAAS,QAAQ,GAEnD,QAAQ,MAAM,GAAG,EAAO,SAAS,EAEjC,IAAM,EAAiB,IAAI,eAAgB,GAAY,CACrD,IAAM,EAAQ,EAAQ,GAEtB,GAAI,EAAO,CACT,GAAM,CAAE,SAAQ,SAAU,EAAM,YAEhC,QAAQ,MAAM,GAAG,EAAO,YAAY,KAAK,MAAM,CAAK,EAAE,GAAG,KAAK,MAAM,CAAM,GAAG,CAC/E,CACF,CAAC,EAaD,OAXA,EAAe,QAAQ,EAAO,EAAE,EAEhC,EAAO,eAAe,iBACpB,YACM,CACJ,EAAe,WAAW,EAC1B,QAAQ,MAAM,GAAG,EAAO,UAAU,CACpC,EACA,CAAE,KAAM,EAAK,CACf,EAEO,CACT"}
|
package/dist/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all prism errors. Use `instanceof PrismError` to catch any prism-originated error. */\nexport class PrismError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a chart is given a structurally invalid configuration it cannot render at all (e.g. a non-Element `container`). Recoverable issues like empty or malformed data emit a dev-mode warning instead
|
|
1
|
+
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all prism errors. Use `instanceof PrismError` to catch any prism-originated error. */\nexport class PrismError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a chart is given a structurally invalid configuration it cannot render at all (e.g. a non-Element `container`). Recoverable issues like empty or malformed data emit a dev-mode warning instead: see the package docs for details. */\nexport class PrismRenderError extends PrismError {}\n"],"mappings":"AACA,IAAa,WAAb,cAAgC,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,iBAAb,cAAsC,UAAW,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export declare class PrismError extends Error {
|
|
3
3
|
constructor(message: string, opts?: ErrorOptions);
|
|
4
4
|
}
|
|
5
|
-
/** Thrown when a chart is given a structurally invalid configuration it cannot render at all (e.g. a non-Element `container`). Recoverable issues like empty or malformed data emit a dev-mode warning instead
|
|
5
|
+
/** Thrown when a chart is given a structurally invalid configuration it cannot render at all (e.g. a non-Element `container`). Recoverable issues like empty or malformed data emit a dev-mode warning instead: see the package docs for details. */
|
|
6
6
|
export declare class PrismRenderError extends PrismError {
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAKjD;AAED,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAKjD;AAED,qPAAqP;AACrP,qBAAa,gBAAiB,SAAQ,UAAU;CAAG"}
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all prism errors. Use `instanceof PrismError` to catch any prism-originated error. */\nexport class PrismError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a chart is given a structurally invalid configuration it cannot render at all (e.g. a non-Element `container`). Recoverable issues like empty or malformed data emit a dev-mode warning instead
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all prism errors. Use `instanceof PrismError` to catch any prism-originated error. */\nexport class PrismError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a chart is given a structurally invalid configuration it cannot render at all (e.g. a non-Element `container`). Recoverable issues like empty or malformed data emit a dev-mode warning instead: see the package docs for details. */\nexport class PrismRenderError extends PrismError {}\n"],"mappings":"AACA,IAAa,WAAb,cAAgC,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,iBAAb,cAAsC,UAAW,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./scales/linear.cjs"),t=require("./scales/time.cjs"),n=require("./errors.cjs"),r=require("./theme/index.cjs"),i=require("./charts/area/area-chart.cjs"),a=require("./scales/band.cjs"),o=require("./charts/bar/bar-chart.cjs"),s=require("./charts/line/line-chart.cjs"),c=require("./charts/pie/pie-chart.cjs"),l=require("./charts/sparkline/sparkline.cjs");exports.PrismError=n.PrismError,exports.PrismRenderError=n.PrismRenderError,exports.bandScale=a.bandScale,exports.createAreaChart=i.createAreaChart,exports.createBarChart=o.createBarChart,exports.createLineChart=s.createLineChart,exports.createPieChart=c.createPieChart,exports.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./scales/linear.cjs"),t=require("./scales/time.cjs"),n=require("./errors.cjs"),r=require("./theme/index.cjs"),i=require("./charts/area/area-chart.cjs"),a=require("./scales/band.cjs"),o=require("./charts/bar/bar-chart.cjs"),s=require("./charts/line/line-chart.cjs"),c=require("./charts/pie/pie-chart.cjs"),l=require("./charts/radar/radar-chart.cjs"),u=require("./charts/sparkline/sparkline.cjs");exports.PrismError=n.PrismError,exports.PrismRenderError=n.PrismRenderError,exports.bandScale=a.bandScale,exports.createAreaChart=i.createAreaChart,exports.createBarChart=o.createBarChart,exports.createLineChart=s.createLineChart,exports.createPieChart=c.createPieChart,exports.createRadarChart=l.createRadarChart,exports.createSparkline=u.createSparkline,exports.linearScale=e.linearScale,exports.resetTheme=r.resetTheme,exports.seriesColor=r.seriesColor,exports.setTheme=r.setTheme,exports.timeScale=t.timeScale;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { createAreaChart } from './charts/area';
|
|
|
3
3
|
export { createBarChart } from './charts/bar';
|
|
4
4
|
export { createLineChart } from './charts/line';
|
|
5
5
|
export { createPieChart } from './charts/pie';
|
|
6
|
+
export { createRadarChart } from './charts/radar';
|
|
6
7
|
export { createSparkline } from './charts/sparkline';
|
|
7
8
|
export { PrismError, PrismRenderError } from './errors';
|
|
8
9
|
export { bandScale } from './scales/band';
|
|
@@ -10,5 +11,5 @@ export { linearScale } from './scales/linear';
|
|
|
10
11
|
export { timeScale } from './scales/time';
|
|
11
12
|
export type { BandScaleConfig, LinearScaleConfig, TimeScaleConfig } from './scales/types';
|
|
12
13
|
export { resetTheme, seriesColor, setTheme } from './theme';
|
|
13
|
-
export type { AreaChartConfig, AreaSeriesConfig, AxisConfig, AxisPosition, BandScale, BarChartConfig, BarSeriesConfig, BarVariant, BaseChartConfig, ChartA11y, ChartDimensions, ChartEvent, ChartHandle, ChartMargin, ContinuousDatum, CrosshairConfig, Datum, GridConfig, HorizontalAxisPosition, LegendConfig, LegendPosition, LineChartConfig, LineSeriesConfig, PieChartConfig, PieSliceConfig, PieVariant, PrismTheme, Scale, Series, SparklineConfig, SparklineVariant, StackSegment, TooltipConfig, TransitionConfig, VerticalAxisPosition, XAxisConfig, YAxisConfig, } from './types';
|
|
14
|
+
export type { AreaChartConfig, AreaSeriesConfig, AxisConfig, AxisPosition, BandScale, BarChartConfig, BarSeriesConfig, BarVariant, BaseChartConfig, ChartA11y, ChartDimensions, ChartEvent, ChartHandle, ChartMargin, ContinuousDatum, CrosshairConfig, Datum, GridConfig, HorizontalAxisPosition, LegendConfig, LegendPosition, LineChartConfig, LineSeriesConfig, PieChartConfig, PieSliceConfig, PieVariant, PrismTheme, RadarAxisConfig, RadarAxisValue, RadarChartConfig, RadarEvent, RadarGridConfig, RadarSeriesConfig, Scale, Series, SeriesValue, SparklineConfig, SparklineVariant, StackSegment, TooltipConfig, TransitionConfig, VerticalAxisPosition, XAxisConfig, YAxisConfig, } from './types';
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,eAAe,EACf,UAAU,EACV,eAAe,EACf,SAAS,EACT,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EACf,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,KAAK,EACL,MAAM,EACN,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,WAAW,GACZ,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,eAAe,EACf,UAAU,EACV,eAAe,EACf,SAAS,EACT,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EACf,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,KAAK,EACL,MAAM,EACN,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,WAAW,GACZ,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{linearScale as e}from"./scales/linear.js";import{timeScale as t}from"./scales/time.js";import{PrismError as n,PrismRenderError as r}from"./errors.js";import{resetTheme as i,seriesColor as a,setTheme as o}from"./theme/index.js";import{createAreaChart as s}from"./charts/area/area-chart.js";import{bandScale as c}from"./scales/band.js";import{createBarChart as l}from"./charts/bar/bar-chart.js";import{createLineChart as u}from"./charts/line/line-chart.js";import{createPieChart as d}from"./charts/pie/pie-chart.js";import{
|
|
1
|
+
import{linearScale as e}from"./scales/linear.js";import{timeScale as t}from"./scales/time.js";import{PrismError as n,PrismRenderError as r}from"./errors.js";import{resetTheme as i,seriesColor as a,setTheme as o}from"./theme/index.js";import{createAreaChart as s}from"./charts/area/area-chart.js";import{bandScale as c}from"./scales/band.js";import{createBarChart as l}from"./charts/bar/bar-chart.js";import{createLineChart as u}from"./charts/line/line-chart.js";import{createPieChart as d}from"./charts/pie/pie-chart.js";import{createRadarChart as f}from"./charts/radar/radar-chart.js";import{createSparkline as p}from"./charts/sparkline/sparkline.js";export{n as PrismError,r as PrismRenderError,c as bandScale,s as createAreaChart,l as createBarChart,u as createLineChart,d as createPieChart,f as createRadarChart,p as createSparkline,e as linearScale,i as resetTheme,a as seriesColor,o as setTheme,t as timeScale};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../svg/element.cjs");function describeValues(e,t,n=String){return`${e}: ${t.map(({datum:e,series:t})=>`${t.name} ${e?n(e.value):`n/a`}`).join(`, `)}`}function createAnnouncer(t,n){let r=e.createSvgElement(`text`,{"aria-live":`polite`,class:n,role:`status`,x:-9999,y:-9999});return t.appendChild(r),{announce(e){r.textContent=e},clear(){r.textContent=``}}}exports.createAnnouncer=createAnnouncer,exports.describeValues=describeValues;
|
|
2
|
+
//# sourceMappingURL=announcer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announcer.cjs","names":[],"sources":["../../src/interaction/announcer.ts"],"sourcesContent":["import { createSvgElement } from '../svg/element';\nimport type { Datum, Series } from '../types';\n\nexport interface Announcer {\n announce(text: string): void;\n clear(): void;\n}\n\n/** \"Label: A 6, B 9\": the comparison text shared by tooltips and announcements. */\nexport function describeValues(\n label: string,\n values: readonly { datum: Datum | undefined; series: Series }[],\n format: (value: number) => string = String,\n): string {\n return `${label}: ${values.map(({ datum, series }) => `${series.name} ${datum ? format(datum.value) : 'n/a'}`).join(', ')}`;\n}\n\n/** Polite status region for charts whose visuals are aria-hidden. */\nexport function createAnnouncer(parent: SVGElement, className: string): Announcer {\n // Off-canvas rather than CSS-hidden so announcements work without prism's stylesheet.\n const region = createSvgElement('text', {\n 'aria-live': 'polite',\n class: className,\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(region);\n\n return {\n announce(text) {\n region.textContent = text;\n },\n clear() {\n region.textContent = '';\n },\n };\n}\n"],"mappings":"sCASA,SAAgB,eACd,EACA,EACA,EAAoC,OAC5B,CACR,MAAO,GAAG,EAAM,IAAI,EAAO,KAAK,CAAE,QAAO,YAAa,GAAG,EAAO,KAAK,GAAG,EAAQ,EAAO,EAAM,KAAK,EAAI,OAAO,CAAC,CAAC,KAAK,IAAI,GAC1H,CAGA,SAAgB,gBAAgB,EAAoB,EAA8B,CAEhF,IAAM,EAAS,EAAA,iBAAiB,OAAQ,CACtC,YAAa,SACb,MAAO,EACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAM,EAElB,CACL,SAAS,EAAM,CACb,EAAO,YAAc,CACvB,EACA,OAAQ,CACN,EAAO,YAAc,EACvB,CACF,CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Datum, Series } from '../types';
|
|
2
|
+
export interface Announcer {
|
|
3
|
+
announce(text: string): void;
|
|
4
|
+
clear(): void;
|
|
5
|
+
}
|
|
6
|
+
/** "Label: A 6, B 9": the comparison text shared by tooltips and announcements. */
|
|
7
|
+
export declare function describeValues(label: string, values: readonly {
|
|
8
|
+
datum: Datum | undefined;
|
|
9
|
+
series: Series;
|
|
10
|
+
}[], format?: (value: number) => string): string;
|
|
11
|
+
/** Polite status region for charts whose visuals are aria-hidden. */
|
|
12
|
+
export declare function createAnnouncer(parent: SVGElement, className: string): Announcer;
|
|
13
|
+
//# sourceMappingURL=announcer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announcer.d.ts","sourceRoot":"","sources":["../../src/interaction/announcer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS;IAAE,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,EAC/D,MAAM,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAe,GACzC,MAAM,CAER;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAoBhF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createSvgElement as e}from"../svg/element.js";function describeValues(e,t,n=String){return`${e}: ${t.map(({datum:e,series:t})=>`${t.name} ${e?n(e.value):`n/a`}`).join(`, `)}`}function createAnnouncer(t,n){let r=e(`text`,{"aria-live":`polite`,class:n,role:`status`,x:-9999,y:-9999});return t.appendChild(r),{announce(e){r.textContent=e},clear(){r.textContent=``}}}export{createAnnouncer,describeValues};
|
|
2
|
+
//# sourceMappingURL=announcer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announcer.js","names":[],"sources":["../../src/interaction/announcer.ts"],"sourcesContent":["import { createSvgElement } from '../svg/element';\nimport type { Datum, Series } from '../types';\n\nexport interface Announcer {\n announce(text: string): void;\n clear(): void;\n}\n\n/** \"Label: A 6, B 9\": the comparison text shared by tooltips and announcements. */\nexport function describeValues(\n label: string,\n values: readonly { datum: Datum | undefined; series: Series }[],\n format: (value: number) => string = String,\n): string {\n return `${label}: ${values.map(({ datum, series }) => `${series.name} ${datum ? format(datum.value) : 'n/a'}`).join(', ')}`;\n}\n\n/** Polite status region for charts whose visuals are aria-hidden. */\nexport function createAnnouncer(parent: SVGElement, className: string): Announcer {\n // Off-canvas rather than CSS-hidden so announcements work without prism's stylesheet.\n const region = createSvgElement('text', {\n 'aria-live': 'polite',\n class: className,\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(region);\n\n return {\n announce(text) {\n region.textContent = text;\n },\n clear() {\n region.textContent = '';\n },\n };\n}\n"],"mappings":"qDASA,SAAgB,eACd,EACA,EACA,EAAoC,OAC5B,CACR,MAAO,GAAG,EAAM,IAAI,EAAO,KAAK,CAAE,QAAO,YAAa,GAAG,EAAO,KAAK,GAAG,EAAQ,EAAO,EAAM,KAAK,EAAI,OAAO,CAAC,CAAC,KAAK,IAAI,GAC1H,CAGA,SAAgB,gBAAgB,EAAoB,EAA8B,CAEhF,IAAM,EAAS,EAAiB,OAAQ,CACtC,YAAa,SACb,MAAO,EACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAM,EAElB,CACL,SAAS,EAAM,CACb,EAAO,YAAc,CACvB,EACA,OAAQ,CACN,EAAO,YAAc,EACvB,CACF,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../svg/element.cjs");function createCrosshair(t,n){let r=n===!0||n?.vertical!==!1,i=n!==!0&&n?.horizontal===!0,a=n===!0||n?.snap!==!1,o=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-crosshair`,style:`display:none`}),s=r?e.createSvgElement(`line`,{class:`prism-crosshair-v`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null,c=i?e.createSvgElement(`line`,{class:`prism-crosshair-h`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null;s&&o.appendChild(s),c&&o.appendChild(c),t.appendChild(o)
|
|
1
|
+
const e=require("../svg/element.cjs");function createCrosshair(t,n){let r=n===!0||n?.vertical!==!1,i=n!==!0&&n?.horizontal===!0,a=n===!0||n?.snap!==!1,o=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-crosshair`,style:`display:none`}),s=r?e.createSvgElement(`line`,{class:`prism-crosshair-v`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null,c=i?e.createSvgElement(`line`,{class:`prism-crosshair-h`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null;return s&&o.appendChild(s),c&&o.appendChild(c),t.appendChild(o),{hide(){o.style.display=`none`},show(t,n,r,i){o.style.display=``,s&&e.setAttributes(s,{x1:t,x2:t,y1:0,y2:i}),c&&e.setAttributes(c,{x1:0,x2:r,y1:n,y2:n})},snap:a}}exports.createCrosshair=createCrosshair;
|
|
2
2
|
//# sourceMappingURL=crosshair.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crosshair.cjs","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n
|
|
1
|
+
{"version":3,"file":"crosshair.cjs","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n show(x: number, y: number, width: number, height: number): void;\n /** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */\n readonly snap: boolean;\n}\n\nexport function createCrosshair(parent: SVGGElement, config?: CrosshairConfig | true): CrosshairState {\n const showVertical = config === true || config?.vertical !== false;\n const showHorizontal = config !== true && config?.horizontal === true;\n const snap = config === true || config?.snap !== false;\n\n const group = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-crosshair', style: 'display:none' });\n\n const vLine = showVertical\n ? createSvgElement('line', { class: 'prism-crosshair-v', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n const hLine = showHorizontal\n ? createSvgElement('line', { class: 'prism-crosshair-h', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n\n if (vLine) group.appendChild(vLine);\n\n if (hLine) group.appendChild(hLine);\n\n parent.appendChild(group);\n\n return {\n hide() {\n group.style.display = 'none';\n },\n show(x: number, y: number, width: number, height: number) {\n group.style.display = '';\n\n if (vLine) setAttributes(vLine, { x1: x, x2: x, y1: 0, y2: height });\n\n if (hLine) setAttributes(hLine, { x1: 0, x2: width, y1: y, y2: y });\n },\n snap,\n };\n}\n"],"mappings":"sCAUA,SAAgB,gBAAgB,EAAqB,EAAiD,CACpG,IAAM,EAAe,IAAW,IAAQ,GAAQ,WAAa,GACvD,EAAiB,IAAW,IAAQ,GAAQ,aAAe,GAC3D,EAAO,IAAW,IAAQ,GAAQ,OAAS,GAE3C,EAAQ,EAAA,iBAAiB,IAAK,CAAE,cAAe,OAAQ,MAAO,kBAAmB,MAAO,cAAe,CAAC,EAExG,EAAQ,EACV,EAAA,iBAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KACE,EAAQ,EACV,EAAA,iBAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KAQJ,OANI,GAAO,EAAM,YAAY,CAAK,EAE9B,GAAO,EAAM,YAAY,CAAK,EAElC,EAAO,YAAY,CAAK,EAEjB,CACL,MAAO,CACL,EAAM,MAAM,QAAU,MACxB,EACA,KAAK,EAAW,EAAW,EAAe,EAAgB,CACxD,EAAM,MAAM,QAAU,GAElB,GAAO,EAAA,cAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,CAAO,CAAC,EAE/D,GAAO,EAAA,cAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAO,GAAI,EAAG,GAAI,CAAE,CAAC,CACpE,EACA,MACF,CACF"}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { CrosshairConfig } from '../types';
|
|
2
2
|
export interface CrosshairState {
|
|
3
3
|
hide(): void;
|
|
4
|
-
|
|
5
|
-
* @param announceText Optional text describing the value at the crosshair position,
|
|
6
|
-
* announced via the crosshair's ARIA live region — used when no tooltip is also shown.
|
|
7
|
-
*/
|
|
8
|
-
show(x: number, y: number, width: number, height: number, announceText?: string): void;
|
|
4
|
+
show(x: number, y: number, width: number, height: number): void;
|
|
9
5
|
/** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */
|
|
10
6
|
readonly snap: boolean;
|
|
11
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crosshair.d.ts","sourceRoot":"","sources":["../../src/interaction/crosshair.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,IAAI,CAAC;IACb
|
|
1
|
+
{"version":3,"file":"crosshair.d.ts","sourceRoot":"","sources":["../../src/interaction/crosshair.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChE,2GAA2G;IAC3G,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,GAAG,cAAc,CAiCpG"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createSvgElement as e,setAttributes as t}from"../svg/element.js";function createCrosshair(n,r){let i=r===!0||r?.vertical!==!1,a=r!==!0&&r?.horizontal===!0,o=r===!0||r?.snap!==!1,s=e(`g`,{"aria-hidden":`true`,class:`prism-crosshair`,style:`display:none`}),c=i?e(`line`,{class:`prism-crosshair-v`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null,l=a?e(`line`,{class:`prism-crosshair-h`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null;c&&s.appendChild(c),l&&s.appendChild(l),n.appendChild(s)
|
|
1
|
+
import{createSvgElement as e,setAttributes as t}from"../svg/element.js";function createCrosshair(n,r){let i=r===!0||r?.vertical!==!1,a=r!==!0&&r?.horizontal===!0,o=r===!0||r?.snap!==!1,s=e(`g`,{"aria-hidden":`true`,class:`prism-crosshair`,style:`display:none`}),c=i?e(`line`,{class:`prism-crosshair-v`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null,l=a?e(`line`,{class:`prism-crosshair-h`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null;return c&&s.appendChild(c),l&&s.appendChild(l),n.appendChild(s),{hide(){s.style.display=`none`},show(e,n,r,i){s.style.display=``,c&&t(c,{x1:e,x2:e,y1:0,y2:i}),l&&t(l,{x1:0,x2:r,y1:n,y2:n})},snap:o}}export{createCrosshair};
|
|
2
2
|
//# sourceMappingURL=crosshair.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crosshair.js","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n
|
|
1
|
+
{"version":3,"file":"crosshair.js","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n show(x: number, y: number, width: number, height: number): void;\n /** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */\n readonly snap: boolean;\n}\n\nexport function createCrosshair(parent: SVGGElement, config?: CrosshairConfig | true): CrosshairState {\n const showVertical = config === true || config?.vertical !== false;\n const showHorizontal = config !== true && config?.horizontal === true;\n const snap = config === true || config?.snap !== false;\n\n const group = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-crosshair', style: 'display:none' });\n\n const vLine = showVertical\n ? createSvgElement('line', { class: 'prism-crosshair-v', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n const hLine = showHorizontal\n ? createSvgElement('line', { class: 'prism-crosshair-h', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n\n if (vLine) group.appendChild(vLine);\n\n if (hLine) group.appendChild(hLine);\n\n parent.appendChild(group);\n\n return {\n hide() {\n group.style.display = 'none';\n },\n show(x: number, y: number, width: number, height: number) {\n group.style.display = '';\n\n if (vLine) setAttributes(vLine, { x1: x, x2: x, y1: 0, y2: height });\n\n if (hLine) setAttributes(hLine, { x1: 0, x2: width, y1: y, y2: y });\n },\n snap,\n };\n}\n"],"mappings":"wEAUA,SAAgB,gBAAgB,EAAqB,EAAiD,CACpG,IAAM,EAAe,IAAW,IAAQ,GAAQ,WAAa,GACvD,EAAiB,IAAW,IAAQ,GAAQ,aAAe,GAC3D,EAAO,IAAW,IAAQ,GAAQ,OAAS,GAE3C,EAAQ,EAAiB,IAAK,CAAE,cAAe,OAAQ,MAAO,kBAAmB,MAAO,cAAe,CAAC,EAExG,EAAQ,EACV,EAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KACE,EAAQ,EACV,EAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KAQJ,OANI,GAAO,EAAM,YAAY,CAAK,EAE9B,GAAO,EAAM,YAAY,CAAK,EAElC,EAAO,YAAY,CAAK,EAEjB,CACL,MAAO,CACL,EAAM,MAAM,QAAU,MACxB,EACA,KAAK,EAAW,EAAW,EAAe,EAAgB,CACxD,EAAM,MAAM,QAAU,GAElB,GAAO,EAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,CAAO,CAAC,EAE/D,GAAO,EAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAO,GAAI,EAAG,GAAI,CAAE,CAAC,CACpE,EACA,MACF,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../core/layout.cjs"),
|
|
1
|
+
const e=require("../svg/element.cjs"),t=require("./announcer.cjs"),n=require("./tooltip.cjs"),r=require("../core/layout.cjs"),i=require("../core/cartesian-model.cjs"),a=require("./events.cjs");var keyOrder=e=>e instanceof Date?e.getTime():Number(e);function keyLabel(e){return e instanceof Date?e.toLocaleDateString():String(e)}function findNearestKey(e,t,n){let r=null,i=1/0;for(let a=0;a<t.length;a++)for(let o=0;o<(t[a]?.length??0);o++){let s=e[a]?.[o],c=t[a]?.[o];if(!s||!c)continue;let l=Math.abs(c.x-n);l<i&&(i=l,r=s.key)}return r}function createSeriesInteraction(o){let s=-1,c=!1,renderedHit=e=>{let t=e.target;if(!(t instanceof SVGElement)||t.tagName.toLowerCase()!==`circle`||!o.seriesGroup.contains(t)||!t.parentElement)return null;let n=t.parentElement;for(;n&&n.parentNode!==o.seriesGroup;)n=n.parentElement;if(!n)return null;let r=[...o.seriesGroup.children].indexOf(n),i=[...t.parentElement.children].indexOf(t),a=o.getData()[r]?.[i],s=o.getPoints()[r]?.[i];return a&&s?{datum:a,point:s,seriesIndex:r}:null},entriesAt=e=>{let t=i.keyId(e),n=o.getPoints();return o.getData().map((e,r)=>{let a=e.findIndex(e=>i.keyId(e.key)===t);return a===-1?{datum:void 0,point:void 0}:{datum:e[a],point:n[r]?.[a]}})},nearestIndex=(e,t)=>{let n=-1,r=1/0;return e.forEach(({point:e},i)=>{if(!e)return;let a=Number.isFinite(t)?Math.abs(e.y-t):0;a<r&&(r=a,n=i)}),n},highlight=(t,n)=>{let r=o.colors();o.markers.replaceChildren(),t.forEach(({point:t},n)=>{t&&o.markers.appendChild(e.createSvgElement(`circle`,{class:`prism-active-point`,cx:t.x,cy:t.y,fill:r[n],r:4}))});let i=[...o.seriesGroup.children];o.seriesGroup.classList.toggle(`prism-series-focused`,n>=0&&i.length>1);for(let[e,t]of i.entries())t.classList.toggle(`prism-series-active`,e===n)},clear=()=>{o.crosshair?.hide(),o.tooltip?.hide(),o.announcer.clear(),highlight([],-1),c=!1,o.onHover?.(null)},eventFor=(e,t,n)=>{let r=entriesAt(e),i=renderedHit(n),a=i?.seriesIndex??nearestIndex(r,t);i&&(r[a]={datum:i.datum,point:i.point});let s=o.getSeriesList(),c=r[a]?.datum;if(a<0||!c)return null;let l=r.map((e,t)=>({datum:e.datum,series:s[t]}));return{entries:r,event:{datum:c,originalEvent:n,series:s[a],values:l},index:a}},focus=(e,i,a)=>{let s=eventFor(e,i?.y??NaN,a);if(!s)return;let{entries:l,event:u,index:d}=s,f=l[d].point,p=o.dims(),m=r.chartArea(p.width,p.height,p.margin),h=o.crosshair?.snap===!1&&i,g=keyLabel(e),_=u.values??[],v=o.colors();o.crosshair?.show(h?i.x:f.x,h?i.y:f.y,m.width,m.height),highlight(l,d);let y=t.describeValues(g,_);if(o.tooltip){let e=_.flatMap(({datum:e,series:t},n)=>e?[{color:v[n],name:t.name,value:String(e.value)}]:[]);o.tooltip.show(f.x+p.margin.left,f.y+p.margin.top,u.datum,u.series,n.comparisonContent(o.svg.ownerDocument,g,e,y))}else o.announcer.announce(y);c=!0,o.onHover?.(u)},pointerKey=e=>{let t=renderedHit(e);if(t)return{key:t.datum.key,pos:t.point};let n=o.getPoints();if(n.every(e=>e.length===0))return null;let i=o.dims(),s=a.getMousePosition(o.svg,e,i.margin.left,i.margin.top),c=r.chartArea(i.width,i.height,i.margin);if(s.x<0||s.x>c.width||s.y<0||s.y>c.height)return null;let l=findNearestKey(o.getData(),n,s.x);return l===null?null:{key:l,pos:s}},sortedKeys=()=>[...new Map(o.getData().flat().map(e=>[i.keyId(e.key),e.key])).values()].sort((e,t)=>keyOrder(e)-keyOrder(t)),onMouseMove=e=>{let t=pointerKey(e);t?focus(t.key,t.pos,e):c&&clear()},onClick=e=>{if(!o.onClick)return;let t=pointerKey(e),n=t&&eventFor(t.key,t.pos.y,e);n&&o.onClick(n.event)},onKeyDown=e=>{let t=sortedKeys();if(t.length===0)return;let n=t.length-1,r={ArrowLeft:s<0?n:Math.max(0,s-1),ArrowRight:s<0?0:Math.min(n,s+1),End:n,Home:0};if(e.key in r)e.preventDefault(),s=r[e.key],focus(t[s],null,e);else if((e.key===`Enter`||e.key===` `)&&s>=0&&o.onClick){e.preventDefault();let n=eventFor(t[s],NaN,e);n&&o.onClick(n.event)}else e.key===`Escape`&&(s=-1,clear())};return{onClick,onKeyDown,onMouseLeave:clear,onMouseMove}}function ensureMarkerGroup(t,n){if(n&&t.contains(n))return n;let r=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-active-points`,"pointer-events":`none`});return t.appendChild(r),r}exports.createSeriesInteraction=createSeriesInteraction,exports.ensureMarkerGroup=ensureMarkerGroup,exports.keyLabel=keyLabel;
|
|
2
2
|
//# sourceMappingURL=series-interaction.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"series-interaction.cjs","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series } from '../types';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport type { TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ntype SeriesPoint = { datum: Datum; point: Point; seriesIndex: number };\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nfunction findNearestSeries(\n allData: Datum[][],\n allPoints: Point[][],\n key: Datum['key'],\n posY: number,\n): SeriesPoint | null {\n const id = keyId(key);\n let nearest: { datum: Datum; point: Point; seriesIndex: number } | null = null;\n let minYDist = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n const datumIndex = allData[seriesIndex]?.findIndex((datum) => keyId(datum.key) === id) ?? -1;\n const datum = datumIndex === -1 ? undefined : allData[seriesIndex]?.[datumIndex];\n const point = datumIndex === -1 ? undefined : allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minYDist) {\n minYDist = distance;\n nearest = { datum, point, seriesIndex };\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = 0;\n\n const onMouseMove = (event: MouseEvent) => {\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n\n return;\n }\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n const crosshairX = opts.crosshair?.snap === false ? pos.x : (nearest?.point.x ?? pos.x);\n const crosshairY = opts.crosshair?.snap === false ? pos.y : (nearest?.point.y ?? pos.y);\n\n // When a tooltip is present it already carries role=\"status\" + aria-live=\"polite\",\n // so the crosshair's own live region must stay silent to avoid double-announcing.\n const announceText = !opts.tooltip && series && nearest ? `${series.name}: ${nearest.datum.value}` : undefined;\n\n opts.crosshair?.show(crosshairX, crosshairY, area.width, area.height, announceText);\n\n if (nearest && series) {\n opts.tooltip?.show(nearest.point.x + dims.margin.left, nearest.point.y + dims.margin.top, nearest.datum, series);\n opts.onHover?.({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onMouseLeave = () => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!opts.onClick) return;\n\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n\n if (nearest && series) {\n opts.onClick({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const allData = opts.getData();\n const allPoints = opts.getPoints();\n const domain = [...new Map(allData.flat().map((datum) => [keyId(datum.key), datum.key])).values()];\n\n if (domain.length === 0) return;\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n keyboardIndex = Math.max(0, Math.min(domain.length - 1, keyboardIndex + (event.key === 'ArrowLeft' ? -1 : 1)));\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (!candidate || !series) return;\n\n // Same dedup as onMouseMove — tooltip announces when present.\n const announceText = !opts.tooltip ? `${series.name}: ${candidate.datum.value}` : undefined;\n\n opts.crosshair?.show(candidate.point.x, candidate.point.y, opts.dims().width, opts.dims().height, announceText);\n opts.tooltip?.show(\n candidate.point.x + opts.dims().margin.left,\n candidate.point.y + opts.dims().margin.top,\n candidate.datum,\n series,\n );\n opts.onHover?.({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if ((event.key === 'Enter' || event.key === ' ') && opts.onClick) {\n event.preventDefault();\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (candidate && series) opts.onClick({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if (event.key === 'Escape') {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave, onMouseMove };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"series-interaction.cjs","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport { createSvgElement } from '../svg/element';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series, SeriesValue } from '../types';\nimport { type Announcer, describeValues } from './announcer';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport { comparisonContent, type TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n announcer: Announcer;\n colors: () => string[];\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n /** Receives one marker per series at the active key. */\n markers: SVGGElement;\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n /** Parent of the per-series groups; the nearest series is emphasised and the rest dim. */\n seriesGroup: SVGGElement;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ninterface KeyEntry {\n datum: Datum | undefined;\n point: Point | undefined;\n}\n\nconst keyOrder = (key: Datum['key']): number => (key instanceof Date ? key.getTime() : Number(key));\n\nexport function keyLabel(key: Datum['key']): string {\n return key instanceof Date ? key.toLocaleDateString() : String(key);\n}\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = -1;\n let active = false;\n\n const renderedHit = (event: Event): { datum: Datum; point: Point; seriesIndex: number } | null => {\n const target = event.target;\n if (\n !(target instanceof SVGElement) ||\n target.tagName.toLowerCase() !== 'circle' ||\n !opts.seriesGroup.contains(target) ||\n !target.parentElement\n )\n return null;\n let group: Element | null = target.parentElement;\n while (group && group.parentNode !== opts.seriesGroup) group = group.parentElement;\n if (!group) return null;\n const seriesIndex = [...opts.seriesGroup.children].indexOf(group);\n const datumIndex = [...target.parentElement.children].indexOf(target);\n const datum = opts.getData()[seriesIndex]?.[datumIndex];\n const point = opts.getPoints()[seriesIndex]?.[datumIndex];\n return datum && point ? { datum, point, seriesIndex } : null;\n };\n\n const entriesAt = (key: Datum['key']): KeyEntry[] => {\n const id = keyId(key);\n const allPoints = opts.getPoints();\n\n return opts.getData().map((data, seriesIndex) => {\n const datumIndex = data.findIndex((datum) => keyId(datum.key) === id);\n\n return datumIndex === -1\n ? { datum: undefined, point: undefined }\n : { datum: data[datumIndex], point: allPoints[seriesIndex]?.[datumIndex] };\n });\n };\n\n const nearestIndex = (entries: KeyEntry[], posY: number): number => {\n let best = -1;\n let minDistance = Infinity;\n\n entries.forEach(({ point }, index) => {\n if (!point) return;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minDistance) {\n minDistance = distance;\n best = index;\n }\n });\n\n return best;\n };\n\n const highlight = (entries: KeyEntry[], emphasised: number): void => {\n const colors = opts.colors();\n\n opts.markers.replaceChildren();\n entries.forEach(({ point }, index) => {\n if (!point) return;\n\n opts.markers.appendChild(\n createSvgElement('circle', {\n class: 'prism-active-point',\n cx: point.x,\n cy: point.y,\n fill: colors[index],\n r: 4,\n }),\n );\n });\n\n const groups = [...opts.seriesGroup.children];\n\n opts.seriesGroup.classList.toggle('prism-series-focused', emphasised >= 0 && groups.length > 1);\n for (const [index, group] of groups.entries()) group.classList.toggle('prism-series-active', index === emphasised);\n };\n\n const clear = (): void => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.announcer.clear();\n highlight([], -1);\n active = false;\n opts.onHover?.(null);\n };\n\n const eventFor = (\n key: Datum['key'],\n posY: number,\n originalEvent: Event,\n ): { entries: KeyEntry[]; event: ChartEvent; index: number } | null => {\n const entries = entriesAt(key);\n const hit = renderedHit(originalEvent);\n const index = hit?.seriesIndex ?? nearestIndex(entries, posY);\n if (hit) entries[index] = { datum: hit.datum, point: hit.point };\n const seriesList = opts.getSeriesList();\n const datum = entries[index]?.datum;\n\n if (index < 0 || !datum) return null;\n\n const values: SeriesValue[] = entries.map((entry, i) => ({ datum: entry.datum, series: seriesList[i] }));\n\n return { entries, event: { datum, originalEvent, series: seriesList[index], values }, index };\n };\n\n const focus = (key: Datum['key'], pos: Point | null, originalEvent: Event): void => {\n const found = eventFor(key, pos?.y ?? Number.NaN, originalEvent);\n\n if (!found) return;\n\n const { entries, event, index } = found;\n const point = entries[index].point!;\n const dims = opts.dims();\n const area = chartArea(dims.width, dims.height, dims.margin);\n const raw = opts.crosshair?.snap === false && pos;\n const label = keyLabel(key);\n const values = event.values ?? [];\n const colors = opts.colors();\n\n opts.crosshair?.show(raw ? pos.x : point.x, raw ? pos.y : point.y, area.width, area.height);\n highlight(entries, index);\n\n const spoken = describeValues(label, values);\n\n if (opts.tooltip) {\n const rows = values.flatMap(({ datum, series }, i) =>\n datum ? [{ color: colors[i], name: series.name, value: String(datum.value) }] : [],\n );\n\n opts.tooltip.show(\n point.x + dims.margin.left,\n point.y + dims.margin.top,\n event.datum,\n event.series,\n comparisonContent(opts.svg.ownerDocument, label, rows, spoken),\n );\n } else {\n opts.announcer.announce(spoken);\n }\n\n active = true;\n opts.onHover?.(event);\n };\n\n const pointerKey = (event: MouseEvent): { key: Datum['key']; pos: Point } | null => {\n const rendered = renderedHit(event);\n if (rendered) return { key: rendered.datum.key, pos: rendered.point };\n const allPoints = opts.getPoints();\n\n if (allPoints.every((points) => points.length === 0)) return null;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return null;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n return key === null ? null : { key, pos };\n };\n\n const sortedKeys = (): Datum['key'][] =>\n [\n ...new Map(\n opts\n .getData()\n .flat()\n .map((datum) => [keyId(datum.key), datum.key]),\n ).values(),\n ].sort((a, b) => keyOrder(a) - keyOrder(b));\n\n const onMouseMove = (event: MouseEvent): void => {\n const hit = pointerKey(event);\n\n if (hit) focus(hit.key, hit.pos, event);\n else if (active) clear();\n };\n\n const onClick = (event: MouseEvent): void => {\n if (!opts.onClick) return;\n\n const hit = pointerKey(event);\n const found = hit && eventFor(hit.key, hit.pos.y, event);\n\n if (found) opts.onClick(found.event);\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n const keys = sortedKeys();\n\n if (keys.length === 0) return;\n\n const last = keys.length - 1;\n const target: Record<string, number> = {\n ArrowLeft: keyboardIndex < 0 ? last : Math.max(0, keyboardIndex - 1),\n ArrowRight: keyboardIndex < 0 ? 0 : Math.min(last, keyboardIndex + 1),\n End: last,\n Home: 0,\n };\n\n if (event.key in target) {\n event.preventDefault();\n keyboardIndex = target[event.key];\n focus(keys[keyboardIndex], null, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && keyboardIndex >= 0 && opts.onClick) {\n event.preventDefault();\n\n const found = eventFor(keys[keyboardIndex], Number.NaN, event);\n\n if (found) opts.onClick(found.event);\n } else if (event.key === 'Escape') {\n keyboardIndex = -1;\n clear();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: clear, onMouseMove };\n}\n\n/** Group for the per-series active markers, reused across renders. */\nexport function ensureMarkerGroup(parent: SVGGElement, current: SVGGElement | null): SVGGElement {\n if (current && parent.contains(current)) return current;\n\n const group = createSvgElement('g', {\n 'aria-hidden': 'true',\n class: 'prism-active-points',\n 'pointer-events': 'none',\n });\n\n parent.appendChild(group);\n\n return group;\n}\n"],"mappings":"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"}
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import type { ChartEventHandlers } from '../core/chart-scaffold';
|
|
2
2
|
import type { Point } from '../svg/path';
|
|
3
3
|
import type { ChartDimensions, ChartEvent, Datum, Series } from '../types';
|
|
4
|
+
import { type Announcer } from './announcer';
|
|
4
5
|
import type { CrosshairState } from './crosshair';
|
|
5
|
-
import type
|
|
6
|
+
import { type TooltipState } from './tooltip';
|
|
6
7
|
export interface SeriesInteractionOptions {
|
|
8
|
+
announcer: Announcer;
|
|
9
|
+
colors: () => string[];
|
|
7
10
|
crosshair?: CrosshairState | null;
|
|
8
11
|
dims: () => ChartDimensions;
|
|
9
12
|
getData: () => Datum[][];
|
|
10
13
|
getPoints: () => Point[][];
|
|
11
14
|
getSeriesList: () => Series[];
|
|
15
|
+
/** Receives one marker per series at the active key. */
|
|
16
|
+
markers: SVGGElement;
|
|
12
17
|
onClick?: ((event: ChartEvent) => void) | undefined;
|
|
13
18
|
onHover?: ((event: ChartEvent | null) => void) | undefined;
|
|
19
|
+
/** Parent of the per-series groups; the nearest series is emphasised and the rest dim. */
|
|
20
|
+
seriesGroup: SVGGElement;
|
|
14
21
|
svg: SVGSVGElement;
|
|
15
22
|
tooltip?: TooltipState | null;
|
|
16
23
|
}
|
|
24
|
+
export declare function keyLabel(key: Datum['key']): string;
|
|
17
25
|
export declare function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers;
|
|
26
|
+
/** Group for the per-series active markers, reused across renders. */
|
|
27
|
+
export declare function ensureMarkerGroup(parent: SVGGElement, current: SVGGElement | null): SVGGElement;
|
|
18
28
|
//# sourceMappingURL=series-interaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"series-interaction.d.ts","sourceRoot":"","sources":["../../src/interaction/series-interaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"series-interaction.d.ts","sourceRoot":"","sources":["../../src/interaction/series-interaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAe,MAAM,UAAU,CAAC;AACxF,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,IAAI,EAAE,MAAM,eAAe,CAAC;IAC5B,OAAO,EAAE,MAAM,KAAK,EAAE,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,KAAK,EAAE,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,MAAM,EAAE,CAAC;IAC9B,wDAAwD;IACxD,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACpD,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3D,0FAA0F;IAC1F,WAAW,EAAE,WAAW,CAAC;IACzB,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC/B;AASD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,CAElD;AAyBD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG,kBAAkB,CA2N1F;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,WAAW,CAY/F"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{createSvgElement as e}from"../svg/element.js";import{describeValues as t}from"./announcer.js";import{comparisonContent as n}from"./tooltip.js";import{chartArea as r}from"../core/layout.js";import{keyId as i}from"../core/cartesian-model.js";import{getMousePosition as a}from"./events.js";var keyOrder=e=>e instanceof Date?e.getTime():Number(e);function keyLabel(e){return e instanceof Date?e.toLocaleDateString():String(e)}function findNearestKey(e,t,n){let r=null,i=1/0;for(let a=0;a<t.length;a++)for(let o=0;o<(t[a]?.length??0);o++){let s=e[a]?.[o],c=t[a]?.[o];if(!s||!c)continue;let l=Math.abs(c.x-n);l<i&&(i=l,r=s.key)}return r}function createSeriesInteraction(o){let s=-1,c=!1,renderedHit=e=>{let t=e.target;if(!(t instanceof SVGElement)||t.tagName.toLowerCase()!==`circle`||!o.seriesGroup.contains(t)||!t.parentElement)return null;let n=t.parentElement;for(;n&&n.parentNode!==o.seriesGroup;)n=n.parentElement;if(!n)return null;let r=[...o.seriesGroup.children].indexOf(n),i=[...t.parentElement.children].indexOf(t),a=o.getData()[r]?.[i],s=o.getPoints()[r]?.[i];return a&&s?{datum:a,point:s,seriesIndex:r}:null},entriesAt=e=>{let t=i(e),n=o.getPoints();return o.getData().map((e,r)=>{let a=e.findIndex(e=>i(e.key)===t);return a===-1?{datum:void 0,point:void 0}:{datum:e[a],point:n[r]?.[a]}})},nearestIndex=(e,t)=>{let n=-1,r=1/0;return e.forEach(({point:e},i)=>{if(!e)return;let a=Number.isFinite(t)?Math.abs(e.y-t):0;a<r&&(r=a,n=i)}),n},highlight=(t,n)=>{let r=o.colors();o.markers.replaceChildren(),t.forEach(({point:t},n)=>{t&&o.markers.appendChild(e(`circle`,{class:`prism-active-point`,cx:t.x,cy:t.y,fill:r[n],r:4}))});let i=[...o.seriesGroup.children];o.seriesGroup.classList.toggle(`prism-series-focused`,n>=0&&i.length>1);for(let[e,t]of i.entries())t.classList.toggle(`prism-series-active`,e===n)},clear=()=>{o.crosshair?.hide(),o.tooltip?.hide(),o.announcer.clear(),highlight([],-1),c=!1,o.onHover?.(null)},eventFor=(e,t,n)=>{let r=entriesAt(e),i=renderedHit(n),a=i?.seriesIndex??nearestIndex(r,t);i&&(r[a]={datum:i.datum,point:i.point});let s=o.getSeriesList(),c=r[a]?.datum;if(a<0||!c)return null;let l=r.map((e,t)=>({datum:e.datum,series:s[t]}));return{entries:r,event:{datum:c,originalEvent:n,series:s[a],values:l},index:a}},focus=(e,i,a)=>{let s=eventFor(e,i?.y??NaN,a);if(!s)return;let{entries:l,event:u,index:d}=s,f=l[d].point,p=o.dims(),m=r(p.width,p.height,p.margin),h=o.crosshair?.snap===!1&&i,g=keyLabel(e),_=u.values??[],v=o.colors();o.crosshair?.show(h?i.x:f.x,h?i.y:f.y,m.width,m.height),highlight(l,d);let y=t(g,_);if(o.tooltip){let e=_.flatMap(({datum:e,series:t},n)=>e?[{color:v[n],name:t.name,value:String(e.value)}]:[]);o.tooltip.show(f.x+p.margin.left,f.y+p.margin.top,u.datum,u.series,n(o.svg.ownerDocument,g,e,y))}else o.announcer.announce(y);c=!0,o.onHover?.(u)},pointerKey=e=>{let t=renderedHit(e);if(t)return{key:t.datum.key,pos:t.point};let n=o.getPoints();if(n.every(e=>e.length===0))return null;let i=o.dims(),s=a(o.svg,e,i.margin.left,i.margin.top),c=r(i.width,i.height,i.margin);if(s.x<0||s.x>c.width||s.y<0||s.y>c.height)return null;let l=findNearestKey(o.getData(),n,s.x);return l===null?null:{key:l,pos:s}},sortedKeys=()=>[...new Map(o.getData().flat().map(e=>[i(e.key),e.key])).values()].sort((e,t)=>keyOrder(e)-keyOrder(t)),onMouseMove=e=>{let t=pointerKey(e);t?focus(t.key,t.pos,e):c&&clear()},onClick=e=>{if(!o.onClick)return;let t=pointerKey(e),n=t&&eventFor(t.key,t.pos.y,e);n&&o.onClick(n.event)},onKeyDown=e=>{let t=sortedKeys();if(t.length===0)return;let n=t.length-1,r={ArrowLeft:s<0?n:Math.max(0,s-1),ArrowRight:s<0?0:Math.min(n,s+1),End:n,Home:0};if(e.key in r)e.preventDefault(),s=r[e.key],focus(t[s],null,e);else if((e.key===`Enter`||e.key===` `)&&s>=0&&o.onClick){e.preventDefault();let n=eventFor(t[s],NaN,e);n&&o.onClick(n.event)}else e.key===`Escape`&&(s=-1,clear())};return{onClick,onKeyDown,onMouseLeave:clear,onMouseMove}}function ensureMarkerGroup(t,n){if(n&&t.contains(n))return n;let r=e(`g`,{"aria-hidden":`true`,class:`prism-active-points`,"pointer-events":`none`});return t.appendChild(r),r}export{createSeriesInteraction,ensureMarkerGroup,keyLabel};
|
|
2
2
|
//# sourceMappingURL=series-interaction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"series-interaction.js","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series } from '../types';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport type { TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ntype SeriesPoint = { datum: Datum; point: Point; seriesIndex: number };\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nfunction findNearestSeries(\n allData: Datum[][],\n allPoints: Point[][],\n key: Datum['key'],\n posY: number,\n): SeriesPoint | null {\n const id = keyId(key);\n let nearest: { datum: Datum; point: Point; seriesIndex: number } | null = null;\n let minYDist = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n const datumIndex = allData[seriesIndex]?.findIndex((datum) => keyId(datum.key) === id) ?? -1;\n const datum = datumIndex === -1 ? undefined : allData[seriesIndex]?.[datumIndex];\n const point = datumIndex === -1 ? undefined : allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minYDist) {\n minYDist = distance;\n nearest = { datum, point, seriesIndex };\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = 0;\n\n const onMouseMove = (event: MouseEvent) => {\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n\n return;\n }\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n const crosshairX = opts.crosshair?.snap === false ? pos.x : (nearest?.point.x ?? pos.x);\n const crosshairY = opts.crosshair?.snap === false ? pos.y : (nearest?.point.y ?? pos.y);\n\n // When a tooltip is present it already carries role=\"status\" + aria-live=\"polite\",\n // so the crosshair's own live region must stay silent to avoid double-announcing.\n const announceText = !opts.tooltip && series && nearest ? `${series.name}: ${nearest.datum.value}` : undefined;\n\n opts.crosshair?.show(crosshairX, crosshairY, area.width, area.height, announceText);\n\n if (nearest && series) {\n opts.tooltip?.show(nearest.point.x + dims.margin.left, nearest.point.y + dims.margin.top, nearest.datum, series);\n opts.onHover?.({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onMouseLeave = () => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!opts.onClick) return;\n\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n\n if (nearest && series) {\n opts.onClick({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const allData = opts.getData();\n const allPoints = opts.getPoints();\n const domain = [...new Map(allData.flat().map((datum) => [keyId(datum.key), datum.key])).values()];\n\n if (domain.length === 0) return;\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n keyboardIndex = Math.max(0, Math.min(domain.length - 1, keyboardIndex + (event.key === 'ArrowLeft' ? -1 : 1)));\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (!candidate || !series) return;\n\n // Same dedup as onMouseMove — tooltip announces when present.\n const announceText = !opts.tooltip ? `${series.name}: ${candidate.datum.value}` : undefined;\n\n opts.crosshair?.show(candidate.point.x, candidate.point.y, opts.dims().width, opts.dims().height, announceText);\n opts.tooltip?.show(\n candidate.point.x + opts.dims().margin.left,\n candidate.point.y + opts.dims().margin.top,\n candidate.datum,\n series,\n );\n opts.onHover?.({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if ((event.key === 'Enter' || event.key === ' ') && opts.onClick) {\n event.preventDefault();\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (candidate && series) opts.onClick({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if (event.key === 'Escape') {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave, onMouseMove };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"series-interaction.js","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport { createSvgElement } from '../svg/element';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series, SeriesValue } from '../types';\nimport { type Announcer, describeValues } from './announcer';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport { comparisonContent, type TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n announcer: Announcer;\n colors: () => string[];\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n /** Receives one marker per series at the active key. */\n markers: SVGGElement;\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n /** Parent of the per-series groups; the nearest series is emphasised and the rest dim. */\n seriesGroup: SVGGElement;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ninterface KeyEntry {\n datum: Datum | undefined;\n point: Point | undefined;\n}\n\nconst keyOrder = (key: Datum['key']): number => (key instanceof Date ? key.getTime() : Number(key));\n\nexport function keyLabel(key: Datum['key']): string {\n return key instanceof Date ? key.toLocaleDateString() : String(key);\n}\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = -1;\n let active = false;\n\n const renderedHit = (event: Event): { datum: Datum; point: Point; seriesIndex: number } | null => {\n const target = event.target;\n if (\n !(target instanceof SVGElement) ||\n target.tagName.toLowerCase() !== 'circle' ||\n !opts.seriesGroup.contains(target) ||\n !target.parentElement\n )\n return null;\n let group: Element | null = target.parentElement;\n while (group && group.parentNode !== opts.seriesGroup) group = group.parentElement;\n if (!group) return null;\n const seriesIndex = [...opts.seriesGroup.children].indexOf(group);\n const datumIndex = [...target.parentElement.children].indexOf(target);\n const datum = opts.getData()[seriesIndex]?.[datumIndex];\n const point = opts.getPoints()[seriesIndex]?.[datumIndex];\n return datum && point ? { datum, point, seriesIndex } : null;\n };\n\n const entriesAt = (key: Datum['key']): KeyEntry[] => {\n const id = keyId(key);\n const allPoints = opts.getPoints();\n\n return opts.getData().map((data, seriesIndex) => {\n const datumIndex = data.findIndex((datum) => keyId(datum.key) === id);\n\n return datumIndex === -1\n ? { datum: undefined, point: undefined }\n : { datum: data[datumIndex], point: allPoints[seriesIndex]?.[datumIndex] };\n });\n };\n\n const nearestIndex = (entries: KeyEntry[], posY: number): number => {\n let best = -1;\n let minDistance = Infinity;\n\n entries.forEach(({ point }, index) => {\n if (!point) return;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minDistance) {\n minDistance = distance;\n best = index;\n }\n });\n\n return best;\n };\n\n const highlight = (entries: KeyEntry[], emphasised: number): void => {\n const colors = opts.colors();\n\n opts.markers.replaceChildren();\n entries.forEach(({ point }, index) => {\n if (!point) return;\n\n opts.markers.appendChild(\n createSvgElement('circle', {\n class: 'prism-active-point',\n cx: point.x,\n cy: point.y,\n fill: colors[index],\n r: 4,\n }),\n );\n });\n\n const groups = [...opts.seriesGroup.children];\n\n opts.seriesGroup.classList.toggle('prism-series-focused', emphasised >= 0 && groups.length > 1);\n for (const [index, group] of groups.entries()) group.classList.toggle('prism-series-active', index === emphasised);\n };\n\n const clear = (): void => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.announcer.clear();\n highlight([], -1);\n active = false;\n opts.onHover?.(null);\n };\n\n const eventFor = (\n key: Datum['key'],\n posY: number,\n originalEvent: Event,\n ): { entries: KeyEntry[]; event: ChartEvent; index: number } | null => {\n const entries = entriesAt(key);\n const hit = renderedHit(originalEvent);\n const index = hit?.seriesIndex ?? nearestIndex(entries, posY);\n if (hit) entries[index] = { datum: hit.datum, point: hit.point };\n const seriesList = opts.getSeriesList();\n const datum = entries[index]?.datum;\n\n if (index < 0 || !datum) return null;\n\n const values: SeriesValue[] = entries.map((entry, i) => ({ datum: entry.datum, series: seriesList[i] }));\n\n return { entries, event: { datum, originalEvent, series: seriesList[index], values }, index };\n };\n\n const focus = (key: Datum['key'], pos: Point | null, originalEvent: Event): void => {\n const found = eventFor(key, pos?.y ?? Number.NaN, originalEvent);\n\n if (!found) return;\n\n const { entries, event, index } = found;\n const point = entries[index].point!;\n const dims = opts.dims();\n const area = chartArea(dims.width, dims.height, dims.margin);\n const raw = opts.crosshair?.snap === false && pos;\n const label = keyLabel(key);\n const values = event.values ?? [];\n const colors = opts.colors();\n\n opts.crosshair?.show(raw ? pos.x : point.x, raw ? pos.y : point.y, area.width, area.height);\n highlight(entries, index);\n\n const spoken = describeValues(label, values);\n\n if (opts.tooltip) {\n const rows = values.flatMap(({ datum, series }, i) =>\n datum ? [{ color: colors[i], name: series.name, value: String(datum.value) }] : [],\n );\n\n opts.tooltip.show(\n point.x + dims.margin.left,\n point.y + dims.margin.top,\n event.datum,\n event.series,\n comparisonContent(opts.svg.ownerDocument, label, rows, spoken),\n );\n } else {\n opts.announcer.announce(spoken);\n }\n\n active = true;\n opts.onHover?.(event);\n };\n\n const pointerKey = (event: MouseEvent): { key: Datum['key']; pos: Point } | null => {\n const rendered = renderedHit(event);\n if (rendered) return { key: rendered.datum.key, pos: rendered.point };\n const allPoints = opts.getPoints();\n\n if (allPoints.every((points) => points.length === 0)) return null;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return null;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n return key === null ? null : { key, pos };\n };\n\n const sortedKeys = (): Datum['key'][] =>\n [\n ...new Map(\n opts\n .getData()\n .flat()\n .map((datum) => [keyId(datum.key), datum.key]),\n ).values(),\n ].sort((a, b) => keyOrder(a) - keyOrder(b));\n\n const onMouseMove = (event: MouseEvent): void => {\n const hit = pointerKey(event);\n\n if (hit) focus(hit.key, hit.pos, event);\n else if (active) clear();\n };\n\n const onClick = (event: MouseEvent): void => {\n if (!opts.onClick) return;\n\n const hit = pointerKey(event);\n const found = hit && eventFor(hit.key, hit.pos.y, event);\n\n if (found) opts.onClick(found.event);\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n const keys = sortedKeys();\n\n if (keys.length === 0) return;\n\n const last = keys.length - 1;\n const target: Record<string, number> = {\n ArrowLeft: keyboardIndex < 0 ? last : Math.max(0, keyboardIndex - 1),\n ArrowRight: keyboardIndex < 0 ? 0 : Math.min(last, keyboardIndex + 1),\n End: last,\n Home: 0,\n };\n\n if (event.key in target) {\n event.preventDefault();\n keyboardIndex = target[event.key];\n focus(keys[keyboardIndex], null, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && keyboardIndex >= 0 && opts.onClick) {\n event.preventDefault();\n\n const found = eventFor(keys[keyboardIndex], Number.NaN, event);\n\n if (found) opts.onClick(found.event);\n } else if (event.key === 'Escape') {\n keyboardIndex = -1;\n clear();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: clear, onMouseMove };\n}\n\n/** Group for the per-series active markers, reused across renders. */\nexport function ensureMarkerGroup(parent: SVGGElement, current: SVGGElement | null): SVGGElement {\n if (current && parent.contains(current)) return current;\n\n const group = createSvgElement('g', {\n 'aria-hidden': 'true',\n class: 'prism-active-points',\n 'pointer-events': 'none',\n });\n\n parent.appendChild(group);\n\n return group;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
let e=require("@vielzeug/orbit");function createTooltip(t,n){let r=t.style.position,i=getComputedStyle(t).position===`static`;i&&(t.style.position=`relative`);let a=t.ownerDocument.createElement(`div`);a.className=`prism-tooltip`,a.style.position=`absolute`,a.style.pointerEvents=`none`,a.style.top=`0`,a.style.left=`0`,a.setAttribute(`role`,`status`),a.setAttribute(`aria-live`,`polite`),t.appendChild(a);let o=n!==!0&&n?.offset||8,s=n===!0?void 0:n?.render,c=null,l=null,u=!1,cancelClear=()=>{l!==null&&(clearTimeout(l),l=null)},cancelReveal=()=>{c!==null&&(cancelAnimationFrame(c),c=null)},disposeHandle=()=>{cancelReveal(),cancelClear(),a.remove(),i&&t.style.position===`relative`&&(t.style.position=r)};return{dispose:disposeHandle,el:a,hide(){cancelReveal(),cancelClear(),u=!1,a.style.opacity=`0`,l=setTimeout(()=>{l=null,u||(a.textContent=``)},150)},show(n,r,i,l){if(!t.isConnected)return;
|
|
1
|
+
let e=require("@vielzeug/orbit");var t=`position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap`;function comparisonContent(e,n,r,i){let a=e.createElement(`div`),o=e.createElement(`span`),s=e.createElement(`div`),c=e.createElement(`div`);a.className=`prism-tooltip-body`,o.className=`prism-tooltip-sr`,o.style.cssText=t,o.textContent=i,s.setAttribute(`aria-hidden`,`true`),c.className=`prism-tooltip-title`,c.textContent=n,s.appendChild(c);for(let t of r){let n=e.createElement(`div`),r=e.createElement(`span`),i=e.createElement(`span`),a=e.createElement(`span`);n.className=`prism-tooltip-row`,r.className=`prism-tooltip-swatch`,r.style.setProperty(`--prism-swatch`,t.color),i.className=`prism-tooltip-name`,i.textContent=t.name,a.className=`prism-tooltip-value`,a.textContent=t.value,n.append(r,i,a),s.appendChild(n)}return a.append(o,s),a}function createTooltip(t,n){let r=t.style.position,i=getComputedStyle(t).position===`static`;i&&(t.style.position=`relative`);let a=t.ownerDocument.createElement(`div`);a.className=`prism-tooltip`,a.style.position=`absolute`,a.style.pointerEvents=`none`,a.style.top=`0`,a.style.left=`0`,a.setAttribute(`role`,`status`),a.setAttribute(`aria-live`,`polite`),t.appendChild(a);let o=n!==!0&&n?.offset||8,s=n===!0?void 0:n?.render,c=null,l=null,u=!1,cancelClear=()=>{l!==null&&(clearTimeout(l),l=null)},cancelReveal=()=>{c!==null&&(cancelAnimationFrame(c),c=null)},disposeHandle=()=>{cancelReveal(),cancelClear(),a.remove(),i&&t.style.position===`relative`&&(t.style.position=r)};return{dispose:disposeHandle,el:a,hide(){cancelReveal(),cancelClear(),u=!1,a.style.opacity=`0`,l=setTimeout(()=>{l=null,u||(a.textContent=``)},150)},show(n,r,i,l,d){if(!t.isConnected)return;cancelClear();let f=s?s(i,l):d??`${l.name}: ${i.value}`;typeof f==`string`?a.textContent=f:a.replaceChildren(f);let{x:p,y:m}=(0,e.computePosition)({getBoundingClientRect:()=>{let e=t.getBoundingClientRect();return{bottom:e.top+r,height:0,left:e.left+n,right:e.left+n,top:e.top+r,width:0,x:e.left+n,y:e.top+r}}},a,{containingBlock:t,middleware:[(0,e.offset)(o),(0,e.flip)(),(0,e.shift)({padding:8})],placement:`top`});if(a.style.left=`${p}px`,a.style.top=`${m}px`,u){c===null&&(a.style.opacity=`1`);return}u=!0,a.style.opacity=`0`,c=requestAnimationFrame(()=>{c=null,u&&(a.style.opacity=`1`)})},[Symbol.dispose]:disposeHandle}}exports.comparisonContent=comparisonContent,exports.createTooltip=createTooltip;
|
|
2
2
|
//# sourceMappingURL=tooltip.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.cjs","names":[],"sources":["../../src/interaction/tooltip.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport type { Datum, Series, TooltipConfig } from '../types';\n\nexport interface TooltipState {\n dispose(): void;\n el: HTMLDivElement | null;\n hide(): void;\n show(x: number, y: number, datum: Datum, series: Series): void;\n [Symbol.dispose](): void;\n}\n\nexport function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState {\n const previousPosition = container.style.position;\n const changedPosition = getComputedStyle(container).position === 'static';\n\n if (changedPosition) container.style.position = 'relative';\n\n const el = container.ownerDocument.createElement('div');\n\n el.className = 'prism-tooltip';\n el.style.position = 'absolute';\n el.style.pointerEvents = 'none';\n el.style.top = '0';\n el.style.left = '0';\n // Non-modal status text
|
|
1
|
+
{"version":3,"file":"tooltip.cjs","names":[],"sources":["../../src/interaction/tooltip.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport type { Datum, Series, TooltipConfig } from '../types';\n\nexport interface TooltipRow {\n color: string;\n name: string;\n value: string;\n}\n\n/** Inline so the spoken text stays hidden even without prism's stylesheet. */\nconst SCREEN_READER_ONLY =\n 'position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap';\n\n/**\n * Title plus one swatch row per series; text only, so data is never parsed as HTML.\n * `spoken` is what the tooltip's live region announces; the visual rows are aria-hidden.\n */\nexport function comparisonContent(\n doc: Document,\n title: string,\n rows: readonly TooltipRow[],\n spoken: string,\n): HTMLElement {\n const body = doc.createElement('div');\n const sr = doc.createElement('span');\n const visual = doc.createElement('div');\n const head = doc.createElement('div');\n\n body.className = 'prism-tooltip-body';\n sr.className = 'prism-tooltip-sr';\n sr.style.cssText = SCREEN_READER_ONLY;\n sr.textContent = spoken;\n visual.setAttribute('aria-hidden', 'true');\n head.className = 'prism-tooltip-title';\n head.textContent = title;\n visual.appendChild(head);\n\n for (const row of rows) {\n const line = doc.createElement('div');\n const swatch = doc.createElement('span');\n const name = doc.createElement('span');\n const value = doc.createElement('span');\n\n line.className = 'prism-tooltip-row';\n swatch.className = 'prism-tooltip-swatch';\n swatch.style.setProperty('--prism-swatch', row.color);\n name.className = 'prism-tooltip-name';\n name.textContent = row.name;\n value.className = 'prism-tooltip-value';\n value.textContent = row.value;\n line.append(swatch, name, value);\n visual.appendChild(line);\n }\n\n body.append(sr, visual);\n\n return body;\n}\n\nexport interface TooltipState {\n dispose(): void;\n el: HTMLDivElement | null;\n hide(): void;\n /** `content` replaces the default `series: value` body when no custom `render` is configured. */\n show(x: number, y: number, datum: Datum, series: Series, content?: Node | string): void;\n [Symbol.dispose](): void;\n}\n\nexport function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState {\n const previousPosition = container.style.position;\n const changedPosition = getComputedStyle(container).position === 'static';\n\n if (changedPosition) container.style.position = 'relative';\n\n const el = container.ownerDocument.createElement('div');\n\n el.className = 'prism-tooltip';\n el.style.position = 'absolute';\n el.style.pointerEvents = 'none';\n el.style.top = '0';\n el.style.left = '0';\n // Non-modal status text: announced by assistive tech whenever content/hide state changes.\n el.setAttribute('role', 'status');\n el.setAttribute('aria-live', 'polite');\n container.appendChild(el);\n\n const tooltipOffset: number = (config !== true && config?.offset) || 8;\n const render = config !== true ? config?.render : undefined;\n\n let revealFrame: number | null = null;\n let clearTimer: ReturnType<typeof setTimeout> | null = null;\n let visible = false;\n\n const cancelClear = (): void => {\n if (clearTimer === null) return;\n\n clearTimeout(clearTimer);\n clearTimer = null;\n };\n\n const cancelReveal = (): void => {\n if (revealFrame === null) return;\n\n cancelAnimationFrame(revealFrame);\n revealFrame = null;\n };\n\n const disposeHandle = (): void => {\n cancelReveal();\n cancelClear();\n el.remove();\n if (changedPosition && container.style.position === 'relative') container.style.position = previousPosition;\n };\n\n return {\n dispose: disposeHandle,\n el,\n hide() {\n cancelReveal();\n cancelClear();\n visible = false;\n el.style.opacity = '0';\n clearTimer = setTimeout(() => {\n clearTimer = null;\n\n if (!visible) el.textContent = '';\n }, 150);\n },\n show(x: number, y: number, datum: Datum, series: Series, content?: Node | string) {\n if (!container.isConnected) return;\n\n cancelClear();\n\n const body = render ? render(datum, series) : (content ?? `${series.name}: ${datum.value}`);\n\n if (typeof body === 'string') el.textContent = body;\n else el.replaceChildren(body);\n\n const virtualRef = {\n getBoundingClientRect: () => {\n const rect = container.getBoundingClientRect();\n\n return {\n bottom: rect.top + y,\n height: 0,\n left: rect.left + x,\n right: rect.left + x,\n top: rect.top + y,\n width: 0,\n x: rect.left + x,\n y: rect.top + y,\n };\n },\n };\n\n const { x: positionX, y: positionY } = computePosition(virtualRef, el, {\n containingBlock: container,\n middleware: [offset(tooltipOffset), flip(), shift({ padding: 8 })],\n placement: 'top',\n });\n\n el.style.left = `${positionX}px`;\n el.style.top = `${positionY}px`;\n\n if (visible) {\n if (revealFrame === null) el.style.opacity = '1';\n\n return;\n }\n\n visible = true;\n el.style.opacity = '0';\n revealFrame = requestAnimationFrame(() => {\n revealFrame = null;\n\n if (visible) el.style.opacity = '1';\n });\n },\n [Symbol.dispose]: disposeHandle,\n };\n}\n"],"mappings":"iCAUA,IAAM,EACJ,iGAMF,SAAgB,kBACd,EACA,EACA,EACA,EACa,CACb,IAAM,EAAO,EAAI,cAAc,KAAK,EAC9B,EAAK,EAAI,cAAc,MAAM,EAC7B,EAAS,EAAI,cAAc,KAAK,EAChC,EAAO,EAAI,cAAc,KAAK,EAEpC,EAAK,UAAY,qBACjB,EAAG,UAAY,mBACf,EAAG,MAAM,QAAU,EACnB,EAAG,YAAc,EACjB,EAAO,aAAa,cAAe,MAAM,EACzC,EAAK,UAAY,sBACjB,EAAK,YAAc,EACnB,EAAO,YAAY,CAAI,EAEvB,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAO,EAAI,cAAc,KAAK,EAC9B,EAAS,EAAI,cAAc,MAAM,EACjC,EAAO,EAAI,cAAc,MAAM,EAC/B,EAAQ,EAAI,cAAc,MAAM,EAEtC,EAAK,UAAY,oBACjB,EAAO,UAAY,uBACnB,EAAO,MAAM,YAAY,iBAAkB,EAAI,KAAK,EACpD,EAAK,UAAY,qBACjB,EAAK,YAAc,EAAI,KACvB,EAAM,UAAY,sBAClB,EAAM,YAAc,EAAI,MACxB,EAAK,OAAO,EAAQ,EAAM,CAAK,EAC/B,EAAO,YAAY,CAAI,CACzB,CAIA,OAFA,EAAK,OAAO,EAAI,CAAM,EAEf,CACT,CAWA,SAAgB,cAAc,EAAwB,EAA6C,CACjG,IAAM,EAAmB,EAAU,MAAM,SACnC,EAAkB,iBAAiB,CAAS,CAAC,CAAC,WAAa,SAE7D,IAAiB,EAAU,MAAM,SAAW,YAEhD,IAAM,EAAK,EAAU,cAAc,cAAc,KAAK,EAEtD,EAAG,UAAY,gBACf,EAAG,MAAM,SAAW,WACpB,EAAG,MAAM,cAAgB,OACzB,EAAG,MAAM,IAAM,IACf,EAAG,MAAM,KAAO,IAEhB,EAAG,aAAa,OAAQ,QAAQ,EAChC,EAAG,aAAa,YAAa,QAAQ,EACrC,EAAU,YAAY,CAAE,EAExB,IAAM,EAAyB,IAAW,IAAQ,GAAQ,QAAW,EAC/D,EAAS,IAAW,GAAwB,IAAA,GAAjB,GAAQ,OAErC,EAA6B,KAC7B,EAAmD,KACnD,EAAU,GAER,gBAA0B,CAC1B,IAAe,OAEnB,aAAa,CAAU,EACvB,EAAa,KACf,EAEM,iBAA2B,CAC3B,IAAgB,OAEpB,qBAAqB,CAAW,EAChC,EAAc,KAChB,EAEM,kBAA4B,CAChC,aAAa,EACb,YAAY,EACZ,EAAG,OAAO,EACN,GAAmB,EAAU,MAAM,WAAa,aAAY,EAAU,MAAM,SAAW,EAC7F,EAEA,MAAO,CACL,QAAS,cACT,KACA,MAAO,CACL,aAAa,EACb,YAAY,EACZ,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAa,eAAiB,CAC5B,EAAa,KAER,IAAS,EAAG,YAAc,GACjC,EAAG,GAAG,CACR,EACA,KAAK,EAAW,EAAW,EAAc,EAAgB,EAAyB,CAChF,GAAI,CAAC,EAAU,YAAa,OAE5B,YAAY,EAEZ,IAAM,EAAO,EAAS,EAAO,EAAO,CAAM,EAAK,GAAW,GAAG,EAAO,KAAK,IAAI,EAAM,QAE/E,OAAO,GAAS,SAAU,EAAG,YAAc,EAC1C,EAAG,gBAAgB,CAAI,EAmB5B,GAAM,CAAE,EAAG,EAAW,EAAG,IAAA,EAAc,EAAA,gBAAA,CAAgB,CAhBrD,0BAA6B,CAC3B,IAAM,EAAO,EAAU,sBAAsB,EAE7C,MAAO,CACL,OAAQ,EAAK,IAAM,EACnB,OAAQ,EACR,KAAM,EAAK,KAAO,EAClB,MAAO,EAAK,KAAO,EACnB,IAAK,EAAK,IAAM,EAChB,MAAO,EACP,EAAG,EAAK,KAAO,EACf,EAAG,EAAK,IAAM,CAChB,CACF,CAGqD,EAAY,EAAI,CACrE,gBAAiB,EACjB,WAAY,EAAC,EAAA,EAAA,OAAA,CAAO,CAAa,GAAG,EAAA,EAAA,KAAA,CAAK,GAAG,EAAA,EAAA,MAAA,CAAM,CAAE,QAAS,CAAE,CAAC,CAAC,EACjE,UAAW,KACb,CAAC,EAKD,GAHA,EAAG,MAAM,KAAO,GAAG,EAAU,IAC7B,EAAG,MAAM,IAAM,GAAG,EAAU,IAExB,EAAS,CACP,IAAgB,OAAM,EAAG,MAAM,QAAU,KAE7C,MACF,CAEA,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAc,0BAA4B,CACxC,EAAc,KAEV,IAAS,EAAG,MAAM,QAAU,IAClC,CAAC,CACH,GACC,OAAO,SAAU,aACpB,CACF"}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import type { Datum, Series, TooltipConfig } from '../types';
|
|
2
|
+
export interface TooltipRow {
|
|
3
|
+
color: string;
|
|
4
|
+
name: string;
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Title plus one swatch row per series; text only, so data is never parsed as HTML.
|
|
9
|
+
* `spoken` is what the tooltip's live region announces; the visual rows are aria-hidden.
|
|
10
|
+
*/
|
|
11
|
+
export declare function comparisonContent(doc: Document, title: string, rows: readonly TooltipRow[], spoken: string): HTMLElement;
|
|
2
12
|
export interface TooltipState {
|
|
3
13
|
dispose(): void;
|
|
4
14
|
el: HTMLDivElement | null;
|
|
5
15
|
hide(): void;
|
|
6
|
-
|
|
16
|
+
/** `content` replaces the default `series: value` body when no custom `render` is configured. */
|
|
17
|
+
show(x: number, y: number, datum: Datum, series: Series, content?: Node | string): void;
|
|
7
18
|
[Symbol.dispose](): void;
|
|
8
19
|
}
|
|
9
20
|
export declare function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/interaction/tooltip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/interaction/tooltip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,MAAM,EAAE,MAAM,GACb,WAAW,CAmCb;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;IACb,iGAAiG;IACjG,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACxF,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,YAAY,CAgHjG"}
|