@tanstack/charts
Version:
A chart grammar for TypeScript and JavaScript. Marks consume your data directly, channels describe visual encodings, and the engine compiles them into a renderer-neutral keyed scene. TanStack's compact scales cover common numeric and categorical mappings.
208 lines (207 loc) • 7.02 kB
JavaScript
import { __s as _$__s, bag2 as _$bag2, clone as _$clone, createElement as _$createElement, createPortal, hookSlots as _$hookSlots, memo, positionalChildren as _$positionalChildren, setStyle as _$setStyle, template as _$template, useId, useLayoutEffect, useMemo, useRef, useState } from "octane";
const _t$0 = /* @__PURE__ */ _$template('<span class="ts-chart-tooltip__swatch" aria-hidden="true"></span>');
const _hs$ = /* @__PURE__ */ _$hookSlots(12);
const _h$0 = /* @__PURE__ */ Symbol(_hs$);
const _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
const _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
const _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
const _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
const _h$5 = /* @__PURE__ */ Symbol(_hs$ + 5);
const _h$6 = /* @__PURE__ */ Symbol(_hs$ + 6);
const _h$7 = /* @__PURE__ */ Symbol(_hs$ + 7);
const _h$8 = /* @__PURE__ */ Symbol(_hs$ + 8);
const _h$9 = /* @__PURE__ */ Symbol(_hs$ + 9);
const _h$10 = /* @__PURE__ */ Symbol(_hs$ + 10);
const _h$11 = /* @__PURE__ */ Symbol(_hs$ + 11);
const _frag$0 = /* @__PURE__ */ _$__s(function _frag$02(props, __s, __extra) {
let _b = __s.slots[0];
if (_b === void 0) {
let _m1;
const _root = _$clone(_t$0);
_m1 = _root;
_b = _$bag2(__s, _root, void 0, _m1);
}
{
const _v = props.h0;
if (_b.a !== _v) {
_$setStyle(_b.b, _v, _b.a);
_b.a = _v;
}
}
});
import { createChartRendererAdapter } from "@tanstack/charts/adapter/renderer";
const ChartSurface = memo(
function ChartSurface2(props) {
return _$createElement("div", {
ref: props.containerRef,
class: "ts-chart-surface",
style: { width: "100%", height: "100%" },
dangerouslySetInnerHTML: { __html: props.markup }
});
},
() => true
);
function RendererChart(props) {
const containerRef = useRef(null, _h$0);
const adapterRef = useRef(null, _h$1);
const onFocusChangeRef = useRef(props.onFocusChange, _h$2);
onFocusChangeRef.current = props.onFocusChange;
const onSelectRef = useRef(props.onSelect, _h$3);
onSelectRef.current = props.onSelect;
const onFocusGroupChangeRef = useRef(props.onFocusGroupChange, _h$4);
onFocusGroupChangeRef.current = props.onFocusGroupChange;
const onRenderRef = useRef(props.onRender, _h$5);
onRenderRef.current = props.onRender;
const [tooltipBodyTarget, setTooltipBodyTarget] = useState(null, _h$6);
const initialWidth = props.initialWidth ?? 640;
const height = props.height;
const aspectRatio = typeof props.aspectRatio === "number" && Number.isFinite(props.aspectRatio) && props.aspectRatio > 0 ? props.aspectRatio : void 0;
const generatedId = useId(_h$7);
const idPrefix = props.idPrefix ?? `ts-chart-${generatedId.replaceAll(/[^a-zA-Z0-9_-]/g, "")}`;
const hostOptions = useMemo(
() => ({
renderer: props.renderer,
definition: props.definition,
ariaLabel: props.ariaLabel,
ariaDescription: props.ariaDescription,
height,
aspectRatio,
width: props.width,
initialWidth,
tabIndex: props.tabIndex,
idPrefix,
measureText: props.measureText,
onFocusChange: (point) => onFocusChangeRef.current?.(point),
onFocusGroupChange: (points) => onFocusGroupChangeRef.current?.(points),
onSelect: (point) => onSelectRef.current?.(point),
onRender: (context) => onRenderRef.current?.(context),
onTooltipBodyChange: props.renderTooltipBody ? setTooltipBodyTarget : void 0
}),
[
props.definition,
props.ariaLabel,
props.ariaDescription,
props.width,
height,
aspectRatio,
initialWidth,
props.tabIndex,
idPrefix,
props.renderer,
props.measureText,
Boolean(props.renderTooltipBody)
],
_h$8
);
adapterRef.current ??= createChartRendererAdapter(hostOptions);
const adapter = adapterRef.current;
const initialMarkupRef = useRef(null, _h$9);
initialMarkupRef.current ??= adapter.prerender();
useLayoutEffect(
() => {
const container = containerRef.current;
if (!container) return;
adapter.update(hostOptions);
adapter.mount(container);
return () => adapter.destroy();
},
[],
_h$10
);
useLayoutEffect(
() => {
adapter.update(hostOptions);
},
[adapter, hostOptions],
_h$11
);
const tooltipPortal = props.renderTooltipBody && tooltipBodyTarget ? createPortal(
props.renderTooltipBody({
points: tooltipBodyTarget.points,
content: tooltipBodyTarget.content,
pinned: tooltipBodyTarget.pinned,
dismiss: tooltipBodyTarget.dismiss,
defaultBody: _$createElement(DefaultTooltipBody, { content: tooltipBodyTarget.content })
}),
tooltipBodyTarget.element
) : null;
return _$positionalChildren([
_$createElement(
"div",
{
class: props.class ? `ts-chart-host ${props.class}` : "ts-chart-host",
style: {
position: "relative",
width: props.width === void 0 ? "100%" : props.width,
height: height ?? (aspectRatio ? void 0 : 320),
aspectRatio: height === void 0 ? aspectRatio : void 0,
...props.style
}
},
_$createElement(ChartSurface, { markup: initialMarkupRef.current, containerRef })
),
tooltipPortal
]);
}
function DefaultTooltipBody({ content }) {
if (typeof content === "string") return content ?? null;
return _$positionalChildren([
content.title ? _$createElement(
"div",
{
class: "ts-chart-tooltip__title",
style: {
display: "flex",
alignItems: "center",
gap: "0.4rem",
fontWeight: 650,
marginBottom: content.rows.length ? "0.3rem" : 0
}
},
content.color ? _$createElement(TooltipSwatch, { color: content.color }) : null,
content.title
) : null,
content.rows.length ? _$createElement("div", { class: "ts-chart-tooltip__rows", "aria-hidden": "true" }, content.rows.map((row, index) => _$createElement(
"div",
{
class: "ts-chart-tooltip__row",
key: `${row.label}\0${index}`,
style: {
display: "grid",
gridTemplateColumns: "0.55rem minmax(0,1fr) auto",
alignItems: "center",
columnGap: "0.4rem"
}
},
row.color ? _$createElement(TooltipSwatch, { color: row.color }) : _$createElement("span", {}),
_$createElement("span", {}, row.label),
_$createElement(
"span",
{
style: {
textAlign: "right",
fontVariantNumeric: "tabular-nums",
whiteSpace: "nowrap"
}
},
row.value
)
))) : null
]);
}
function TooltipSwatch({ color }) {
return _$createElement(_frag$0, {
h0: {
display: "block",
width: "0.55rem",
height: "0.55rem",
borderRadius: "0.15rem",
boxShadow: "inset 0 0 0 1px rgb(0 0 0/.12)",
background: color
}
});
}
TooltipSwatch.$$singleRoot = true;
export {
RendererChart
};