@dou-ui/chart 0.0.0-stage → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/chart.js +6 -0
- package/dist/chart.js.map +1 -0
- package/dist/chart.vue_vue_type_script_setup_true_lang.js +4245 -0
- package/dist/chart.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/area.js +6 -0
- package/dist/components/area.js.map +1 -0
- package/dist/components/area.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/area.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/axis.js +6 -0
- package/dist/components/axis.js.map +1 -0
- package/dist/components/axis.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/components/axis.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/bar.js +6 -0
- package/dist/components/bar.js.map +1 -0
- package/dist/components/bar.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/components/bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/boxplot.js +6 -0
- package/dist/components/boxplot.js.map +1 -0
- package/dist/components/boxplot.vue_vue_type_script_setup_true_lang.js +42 -0
- package/dist/components/boxplot.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/brush.js +6 -0
- package/dist/components/brush.js.map +1 -0
- package/dist/components/brush.vue_vue_type_script_setup_true_lang.js +42 -0
- package/dist/components/brush.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/funnel.js +6 -0
- package/dist/components/funnel.js.map +1 -0
- package/dist/components/funnel.vue_vue_type_script_setup_true_lang.js +41 -0
- package/dist/components/funnel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/gauge.js +6 -0
- package/dist/components/gauge.js.map +1 -0
- package/dist/components/gauge.vue_vue_type_script_setup_true_lang.js +91 -0
- package/dist/components/gauge.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/heatmap.js +6 -0
- package/dist/components/heatmap.js.map +1 -0
- package/dist/components/heatmap.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/components/heatmap.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/histogram.js +6 -0
- package/dist/components/histogram.js.map +1 -0
- package/dist/components/histogram.vue_vue_type_script_setup_true_lang.js +61 -0
- package/dist/components/histogram.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/line.js +6 -0
- package/dist/components/line.js.map +1 -0
- package/dist/components/line.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/components/line.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/marker.js +6 -0
- package/dist/components/marker.js.map +1 -0
- package/dist/components/marker.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/marker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/pie.js +6 -0
- package/dist/components/pie.js.map +1 -0
- package/dist/components/pie.vue_vue_type_script_setup_true_lang.js +42 -0
- package/dist/components/pie.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/radar.js +6 -0
- package/dist/components/radar.js.map +1 -0
- package/dist/components/radar.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/components/radar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/range.js +6 -0
- package/dist/components/range.js.map +1 -0
- package/dist/components/range.vue_vue_type_script_setup_true_lang.js +27 -0
- package/dist/components/range.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/scatter.js +6 -0
- package/dist/components/scatter.js.map +1 -0
- package/dist/components/scatter.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/components/scatter.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/sunburst.js +6 -0
- package/dist/components/sunburst.js.map +1 -0
- package/dist/components/sunburst.vue_vue_type_script_setup_true_lang.js +36 -0
- package/dist/components/sunburst.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tooltip.js +6 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/tooltip.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/treemap.js +6 -0
- package/dist/components/treemap.js.map +1 -0
- package/dist/components/treemap.vue_vue_type_script_setup_true_lang.js +33 -0
- package/dist/components/treemap.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/waterfall.js +6 -0
- package/dist/components/waterfall.js.map +1 -0
- package/dist/components/waterfall.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/components/waterfall.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/zoom.js +6 -0
- package/dist/components/zoom.js.map +1 -0
- package/dist/components/zoom.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/zoom.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/context.js +30 -0
- package/dist/context.js.map +1 -0
- package/dist/core/bar.js +223 -0
- package/dist/core/bar.js.map +1 -0
- package/dist/core/box.js +150 -0
- package/dist/core/box.js.map +1 -0
- package/dist/core/colors.js +58 -0
- package/dist/core/colors.js.map +1 -0
- package/dist/core/data.js +257 -0
- package/dist/core/data.js.map +1 -0
- package/dist/core/decimate.js +211 -0
- package/dist/core/decimate.js.map +1 -0
- package/dist/core/format.js +151 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/funnel.js +68 -0
- package/dist/core/funnel.js.map +1 -0
- package/dist/core/grid.js +87 -0
- package/dist/core/grid.js.map +1 -0
- package/dist/core/heatmap.js +187 -0
- package/dist/core/heatmap.js.map +1 -0
- package/dist/core/histogram.js +81 -0
- package/dist/core/histogram.js.map +1 -0
- package/dist/core/hit.js +115 -0
- package/dist/core/hit.js.map +1 -0
- package/dist/core/labels.js +141 -0
- package/dist/core/labels.js.map +1 -0
- package/dist/core/layout.js +1002 -0
- package/dist/core/layout.js.map +1 -0
- package/dist/core/line.js +230 -0
- package/dist/core/line.js.map +1 -0
- package/dist/core/marker.js +205 -0
- package/dist/core/marker.js.map +1 -0
- package/dist/core/model.js +391 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/painter.js +79 -0
- package/dist/core/painter.js.map +1 -0
- package/dist/core/pattern.js +102 -0
- package/dist/core/pattern.js.map +1 -0
- package/dist/core/pie.js +119 -0
- package/dist/core/pie.js.map +1 -0
- package/dist/core/radar.js +83 -0
- package/dist/core/radar.js.map +1 -0
- package/dist/core/scale.js +149 -0
- package/dist/core/scale.js.map +1 -0
- package/dist/core/scatter.js +263 -0
- package/dist/core/scatter.js.map +1 -0
- package/dist/core/svg.js +209 -0
- package/dist/core/svg.js.map +1 -0
- package/dist/core/sync.js +21 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/core/time.js +217 -0
- package/dist/core/time.js.map +1 -0
- package/dist/core/tree.js +348 -0
- package/dist/core/tree.js.map +1 -0
- package/dist/core/warn.js +11 -0
- package/dist/core/warn.js.map +1 -0
- package/dist/core/waterfall.js +134 -0
- package/dist/core/waterfall.js.map +1 -0
- package/dist/core/window.js +94 -0
- package/dist/core/window.js.map +1 -0
- package/dist/define.js +62 -0
- package/dist/define.js.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/locale.js +170 -0
- package/dist/locale.js.map +1 -0
- package/dist/overlay.js +6 -0
- package/dist/overlay.js.map +1 -0
- package/dist/overlay.vue_vue_type_script_setup_true_lang.js +207 -0
- package/dist/overlay.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/pointer.js +6 -0
- package/dist/pointer.js.map +1 -0
- package/dist/pointer.vue_vue_type_script_setup_true_lang.js +136 -0
- package/dist/pointer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/static.js +6 -0
- package/dist/static.js.map +1 -0
- package/dist/static.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/static.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +3 -0
- package/dist/table.js +6 -0
- package/dist/table.js.map +1 -0
- package/dist/table.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/table.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/types/chart.vue.d.ts +24 -0
- package/dist/types/components/area.vue.d.ts +16 -0
- package/dist/types/components/axis.vue.d.ts +8 -0
- package/dist/types/components/bar.vue.d.ts +14 -0
- package/dist/types/components/boxplot.vue.d.ts +14 -0
- package/dist/types/components/brush.vue.d.ts +22 -0
- package/dist/types/components/funnel.vue.d.ts +14 -0
- package/dist/types/components/gauge.vue.d.ts +17 -0
- package/dist/types/components/heatmap.vue.d.ts +14 -0
- package/dist/types/components/histogram.vue.d.ts +14 -0
- package/dist/types/components/line.vue.d.ts +16 -0
- package/dist/types/components/marker.vue.d.ts +6 -0
- package/dist/types/components/pie.vue.d.ts +23 -0
- package/dist/types/components/radar.vue.d.ts +16 -0
- package/dist/types/components/range.vue.d.ts +12 -0
- package/dist/types/components/scatter.vue.d.ts +14 -0
- package/dist/types/components/sunburst.vue.d.ts +17 -0
- package/dist/types/components/tooltip.vue.d.ts +13 -0
- package/dist/types/components/treemap.vue.d.ts +8 -0
- package/dist/types/components/waterfall.vue.d.ts +16 -0
- package/dist/types/components/zoom.vue.d.ts +18 -0
- package/dist/types/context.d.ts +87 -0
- package/dist/types/core/bar.d.ts +38 -0
- package/dist/types/core/box.d.ts +25 -0
- package/dist/types/core/colors.d.ts +16 -0
- package/dist/types/core/data.d.ts +72 -0
- package/dist/types/core/decimate.d.ts +39 -0
- package/dist/types/core/format.d.ts +33 -0
- package/dist/types/core/funnel.d.ts +15 -0
- package/dist/types/core/grid.d.ts +18 -0
- package/dist/types/core/heatmap.d.ts +17 -0
- package/dist/types/core/histogram.d.ts +23 -0
- package/dist/types/core/hit.d.ts +31 -0
- package/dist/types/core/labels.d.ts +45 -0
- package/dist/types/core/layout.d.ts +259 -0
- package/dist/types/core/line.d.ts +36 -0
- package/dist/types/core/marker.d.ts +67 -0
- package/dist/types/core/model.d.ts +86 -0
- package/dist/types/core/painter.d.ts +34 -0
- package/dist/types/core/pattern.d.ts +14 -0
- package/dist/types/core/pie.d.ts +66 -0
- package/dist/types/core/radar.d.ts +12 -0
- package/dist/types/core/scale.d.ts +60 -0
- package/dist/types/core/scatter.d.ts +16 -0
- package/dist/types/core/series.d.ts +228 -0
- package/dist/types/core/svg.d.ts +63 -0
- package/dist/types/core/sync.d.ts +8 -0
- package/dist/types/core/time.d.ts +20 -0
- package/dist/types/core/tree.d.ts +84 -0
- package/dist/types/core/warn.d.ts +4 -0
- package/dist/types/core/waterfall.d.ts +24 -0
- package/dist/types/core/window.d.ts +36 -0
- package/dist/types/define.d.ts +115 -0
- package/dist/types/index.d.ts +363 -0
- package/dist/types/locale.d.ts +100 -0
- package/dist/types/overlay.vue.d.ts +95 -0
- package/dist/types/pointer.vue.d.ts +53 -0
- package/dist/types/static.vue.d.ts +24 -0
- package/dist/types/table.vue.d.ts +19 -0
- package/dist/types/types.d.ts +555 -0
- package/dist/types/zoom-layer.vue.d.ts +41 -0
- package/dist/zoom-layer.js +6 -0
- package/dist/zoom-layer.js.map +1 -0
- package/dist/zoom-layer.vue_vue_type_script_setup_true_lang.js +210 -0
- package/dist/zoom-layer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/package.json +53 -4
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { DouSpinner, DouTooltip, useNamespace } from "dou-ui";
|
|
2
|
+
import { Fragment, Transition, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, renderList, toDisplayString, unref, useId, withCtx } from "vue";
|
|
3
|
+
// src/overlay.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var _hoisted_1 = [
|
|
5
|
+
"aria-pressed",
|
|
6
|
+
"aria-describedby",
|
|
7
|
+
"onClick",
|
|
8
|
+
"onKeydown",
|
|
9
|
+
"onPointerdown",
|
|
10
|
+
"onPointerenter",
|
|
11
|
+
"onFocus"
|
|
12
|
+
];
|
|
13
|
+
var _hoisted_2 = ["id"];
|
|
14
|
+
var HOLD = 500;
|
|
15
|
+
var LEGEND_PAD = 4;
|
|
16
|
+
var overlay_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
17
|
+
name: "DouChartOverlay",
|
|
18
|
+
__name: "overlay",
|
|
19
|
+
props: { state: {} },
|
|
20
|
+
setup(__props) {
|
|
21
|
+
const ns = useNamespace("chart");
|
|
22
|
+
const { shown, labels, titles, legend, legendBox, hole, toggle, isolate, hint, focus, markers, data, dataShown, dataFocus, empty, loading } = __props.state;
|
|
23
|
+
const Center = () => __props.state.center();
|
|
24
|
+
const hintId = useId();
|
|
25
|
+
/** How long a finger stays on an entry to show only it, in ms. */
|
|
26
|
+
let holdTimer;
|
|
27
|
+
/** A hold just showed one entry alone: the click that ends it isn't a toggle. */
|
|
28
|
+
let held = false;
|
|
29
|
+
function holdLegend(index) {
|
|
30
|
+
letGo();
|
|
31
|
+
held = false;
|
|
32
|
+
holdTimer = setTimeout(() => {
|
|
33
|
+
holdTimer = void 0;
|
|
34
|
+
held = true;
|
|
35
|
+
isolate(index);
|
|
36
|
+
}, HOLD);
|
|
37
|
+
}
|
|
38
|
+
function letGo() {
|
|
39
|
+
if (holdTimer) clearTimeout(holdTimer);
|
|
40
|
+
holdTimer = void 0;
|
|
41
|
+
}
|
|
42
|
+
function onLegendClick(event, index) {
|
|
43
|
+
if (held) {
|
|
44
|
+
held = false;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (event.altKey) isolate(index);
|
|
48
|
+
else toggle(index);
|
|
49
|
+
}
|
|
50
|
+
function onLegendKey(event, index) {
|
|
51
|
+
if (!event.altKey || event.key !== "Enter" && event.key !== " ") return;
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
isolate(index);
|
|
54
|
+
}
|
|
55
|
+
/** No callout menu over an entry while it is held down. */
|
|
56
|
+
function noMenu(event) {
|
|
57
|
+
if (holdTimer || held) event.preventDefault();
|
|
58
|
+
}
|
|
59
|
+
onBeforeUnmount(letGo);
|
|
60
|
+
/** Room around the legend's entries in its box, so a focus ring isn't cut off where it scrolls. */
|
|
61
|
+
const Empty = () => __props.state.emptyContent();
|
|
62
|
+
const focusVisible = (e) => e.target.matches(":focus-visible");
|
|
63
|
+
return (_ctx, _cache) => {
|
|
64
|
+
return openBlock(), createElementBlock(Fragment, null, [
|
|
65
|
+
unref(shown) ? (openBlock(), createElementBlock("div", {
|
|
66
|
+
key: 0,
|
|
67
|
+
class: normalizeClass(unref(ns).e("labels")),
|
|
68
|
+
"aria-hidden": "true"
|
|
69
|
+
}, [
|
|
70
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(labels), (tick) => {
|
|
71
|
+
return openBlock(), createElementBlock("span", {
|
|
72
|
+
key: tick.key,
|
|
73
|
+
class: normalizeClass([
|
|
74
|
+
unref(ns).e("tick"),
|
|
75
|
+
unref(ns).is(tick.axis),
|
|
76
|
+
unref(ns).is("clipped", !!tick.clipped)
|
|
77
|
+
]),
|
|
78
|
+
style: normalizeStyle({
|
|
79
|
+
transform: `translate(${tick.left}px, ${tick.top}px)`,
|
|
80
|
+
width: tick.clipped ? `${tick.width}px` : void 0
|
|
81
|
+
})
|
|
82
|
+
}, [createElementVNode("span", { class: normalizeClass(unref(ns).e("text")) }, toDisplayString(tick.text), 3)], 6);
|
|
83
|
+
}), 128)),
|
|
84
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(titles), (title) => {
|
|
85
|
+
return openBlock(), createElementBlock("span", {
|
|
86
|
+
key: title.key,
|
|
87
|
+
class: normalizeClass([unref(ns).e("title"), unref(ns).is("end", title.align === "end")]),
|
|
88
|
+
style: normalizeStyle({ transform: `translate(${title.left}px, ${title.top}px)` })
|
|
89
|
+
}, [createElementVNode("span", { class: normalizeClass(unref(ns).e("text")) }, toDisplayString(title.text), 3)], 6);
|
|
90
|
+
}), 128)),
|
|
91
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(markers), (marker) => {
|
|
92
|
+
return openBlock(), createElementBlock("span", {
|
|
93
|
+
key: marker.key,
|
|
94
|
+
class: normalizeClass([
|
|
95
|
+
unref(ns).e("marker"),
|
|
96
|
+
unref(ns).is(marker.tone),
|
|
97
|
+
unref(ns).is(marker.align),
|
|
98
|
+
unref(ns).is("backdrop", marker.backdrop)
|
|
99
|
+
]),
|
|
100
|
+
style: normalizeStyle({ transform: `translate(${marker.left}px, ${marker.top}px)` })
|
|
101
|
+
}, [createElementVNode("span", { class: normalizeClass(unref(ns).e("text")) }, toDisplayString(marker.text), 3)], 6);
|
|
102
|
+
}), 128)),
|
|
103
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(data), (label) => {
|
|
104
|
+
return openBlock(), createElementBlock("span", {
|
|
105
|
+
key: `data:${label.key}`,
|
|
106
|
+
class: normalizeClass([
|
|
107
|
+
unref(ns).e("value"),
|
|
108
|
+
unref(ns).is(label.align),
|
|
109
|
+
unref(ns).is("inside", !!label.on),
|
|
110
|
+
unref(ns).is("hidden", !unref(dataShown)),
|
|
111
|
+
unref(ns).is("faded", unref(dataFocus) !== null && unref(dataFocus) !== label.series),
|
|
112
|
+
unref(ns).is("clipped", label.width !== void 0)
|
|
113
|
+
]),
|
|
114
|
+
style: normalizeStyle({
|
|
115
|
+
transform: `translate(${label.left}px, ${label.top}px)`,
|
|
116
|
+
color: label.ink,
|
|
117
|
+
width: label.width === void 0 ? void 0 : `${label.width}px`
|
|
118
|
+
})
|
|
119
|
+
}, [createElementVNode("span", { class: normalizeClass(unref(ns).e("text")) }, toDisplayString(label.text), 3)], 6);
|
|
120
|
+
}), 128))
|
|
121
|
+
], 2)) : createCommentVNode("", true),
|
|
122
|
+
unref(shown) && unref(legend).length && unref(legendBox) ? (openBlock(), createElementBlock("div", {
|
|
123
|
+
key: 1,
|
|
124
|
+
class: normalizeClass([unref(ns).e("legends"), unref(ns).is("scroll", unref(legendBox).scroll)]),
|
|
125
|
+
style: normalizeStyle({
|
|
126
|
+
left: `${unref(legendBox).x - LEGEND_PAD}px`,
|
|
127
|
+
top: `${unref(legendBox).y - LEGEND_PAD}px`,
|
|
128
|
+
width: `${unref(legendBox).width + 8}px`,
|
|
129
|
+
height: `${unref(legendBox).height + 8}px`
|
|
130
|
+
})
|
|
131
|
+
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(legend), (item) => {
|
|
132
|
+
return openBlock(), createBlock(unref(DouTooltip), {
|
|
133
|
+
key: `legend:${item.index}`,
|
|
134
|
+
content: item.text,
|
|
135
|
+
disabled: !item.clipped
|
|
136
|
+
}, {
|
|
137
|
+
default: withCtx(() => [createElementVNode("button", {
|
|
138
|
+
type: "button",
|
|
139
|
+
class: normalizeClass([
|
|
140
|
+
unref(ns).e("legend"),
|
|
141
|
+
unref(ns).is(item.kind),
|
|
142
|
+
unref(ns).is("dashed", item.dashed),
|
|
143
|
+
unref(ns).is("off", item.off),
|
|
144
|
+
unref(ns).is("locked", item.locked),
|
|
145
|
+
unref(ns).is("clipped", !!item.clipped)
|
|
146
|
+
]),
|
|
147
|
+
style: normalizeStyle({
|
|
148
|
+
transform: `translate(${item.left - unref(legendBox).x + LEGEND_PAD}px, ${item.top - unref(legendBox).y + LEGEND_PAD}px)`,
|
|
149
|
+
width: item.clipped ? `${item.width}px` : void 0
|
|
150
|
+
}),
|
|
151
|
+
"aria-pressed": !item.off,
|
|
152
|
+
"aria-describedby": unref(hintId),
|
|
153
|
+
"aria-keyshortcuts": "Alt+Enter",
|
|
154
|
+
onClick: (e) => onLegendClick(e, item.index),
|
|
155
|
+
onKeydown: (e) => onLegendKey(e, item.index),
|
|
156
|
+
onPointerdown: (e) => e.pointerType === "touch" && holdLegend(item.index),
|
|
157
|
+
onPointerup: letGo,
|
|
158
|
+
onPointercancel: letGo,
|
|
159
|
+
onContextmenu: noMenu,
|
|
160
|
+
onPointerenter: (e) => e.pointerType !== "touch" && !item.off && unref(focus)(item.index),
|
|
161
|
+
onPointerleave: _cache[0] || (_cache[0] = ($event) => (letGo(), unref(focus)(null))),
|
|
162
|
+
onFocus: (e) => focusVisible(e) && !item.off && unref(focus)(item.index),
|
|
163
|
+
onBlur: _cache[1] || (_cache[1] = ($event) => unref(focus)(null))
|
|
164
|
+
}, [createElementVNode("span", {
|
|
165
|
+
class: normalizeClass(unref(ns).e("swatch")),
|
|
166
|
+
style: normalizeStyle(item.scale ? {
|
|
167
|
+
width: `${item.swatch}px`,
|
|
168
|
+
background: `linear-gradient(to right, ${item.scale.join(", ")})`
|
|
169
|
+
} : item.pattern ? {
|
|
170
|
+
color: item.color,
|
|
171
|
+
backgroundImage: item.pattern.image,
|
|
172
|
+
backgroundSize: item.pattern.size
|
|
173
|
+
} : { color: item.color })
|
|
174
|
+
}, null, 6), createElementVNode("span", { class: normalizeClass(unref(ns).e("text")) }, toDisplayString(item.text), 3)], 46, _hoisted_1)]),
|
|
175
|
+
_: 2
|
|
176
|
+
}, 1032, ["content", "disabled"]);
|
|
177
|
+
}), 128)), createElementVNode("span", {
|
|
178
|
+
id: unref(hintId),
|
|
179
|
+
hidden: ""
|
|
180
|
+
}, toDisplayString(unref(hint)), 9, _hoisted_2)], 6)) : createCommentVNode("", true),
|
|
181
|
+
unref(hole) ? (openBlock(), createElementBlock("div", {
|
|
182
|
+
key: 2,
|
|
183
|
+
class: normalizeClass([unref(ns).e("center"), unref(ns).is("above", !!unref(hole).above)]),
|
|
184
|
+
style: normalizeStyle({
|
|
185
|
+
left: `${unref(hole).left}px`,
|
|
186
|
+
top: `${unref(hole).top}px`,
|
|
187
|
+
width: `${unref(hole).width}px`
|
|
188
|
+
})
|
|
189
|
+
}, [createVNode(Center)], 6)) : createCommentVNode("", true),
|
|
190
|
+
unref(empty) ? (openBlock(), createElementBlock("div", {
|
|
191
|
+
key: 3,
|
|
192
|
+
class: normalizeClass(unref(ns).e("empty"))
|
|
193
|
+
}, [createVNode(Empty)], 2)) : createCommentVNode("", true),
|
|
194
|
+
createVNode(Transition, { name: "dou-fade" }, {
|
|
195
|
+
default: withCtx(() => [unref(loading) ? (openBlock(), createElementBlock("div", {
|
|
196
|
+
key: 0,
|
|
197
|
+
class: normalizeClass(unref(ns).e("loading"))
|
|
198
|
+
}, [createVNode(unref(DouSpinner))], 2)) : createCommentVNode("", true)]),
|
|
199
|
+
_: 1
|
|
200
|
+
})
|
|
201
|
+
], 64);
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
export { overlay_vue_vue_type_script_setup_true_lang_default as default };
|
|
206
|
+
|
|
207
|
+
//# sourceMappingURL=overlay.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_unref","_normalizeClass","_renderList","_normalizeStyle","_createElementVNode","_toDisplayString","_createCommentVNode","_createBlock","_withCtx","_createVNode","_Transition"],"sources":["../src/overlay.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouSpinner, DouTooltip, useNamespace, type Tone } from 'dou-ui'\nimport { onBeforeUnmount, useId, type ComputedRef, type VNodeChild } from 'vue'\nimport type { TickLabel } from './core/layout'\nimport type { PlacedDataLabel } from './core/labels'\nimport type { LegendBox } from './core/layout'\nimport type { MarkerLabel } from './core/marker'\n\n/**\n * The text over the canvas: tick labels, titles, the legend and what goes\n * in a donut's hole. Kept apart from the chart, so laying it out again\n * doesn't render the chart's slot again: a part written with a new\n * function each render (`:format=\"(v) => …\"`) would otherwise be laid out\n * again and again.\n */\nexport interface OverlayState {\n shown: ComputedRef<boolean>\n labels: ComputedRef<Array<TickLabel & { key: string; axis: string }>>\n titles: ComputedRef<\n Array<{ key: string; text: string; left: number; top: number; align: 'start' | 'end' }>\n >\n legend: ComputedRef<\n Array<{\n index: number\n text: string\n left: number\n top: number\n color: string\n kind: string\n dashed: boolean\n /** Turned off. */\n off: boolean\n /** The last one shown: it can't be turned off. */\n locked: boolean\n /** The room it takes, swatch and name, in px. */\n width: number\n /** Its name is cut short to the room down the side. */\n clipped?: boolean\n /** A heatmap's scale: its colors, least to most, in a swatch `swatch` px wide. */\n scale?: string[]\n swatch?: number\n /** The pattern over its color, as a CSS background image and its size. */\n pattern?: { image: string; size?: string }\n }>\n >\n /** Where the legend shows; its entries scroll in it when they don't all fit. */\n legendBox: ComputedRef<LegendBox | undefined>\n /** Turns the series (or slice) at `index` on or off. */\n toggle: (index: number) => void\n /** Shows only the series (or slice) at `index`, or all again. */\n isolate: (index: number) => void\n /** How to show one entry alone, read out with each entry. */\n hint: ComputedRef<string>\n /** Brings the series at `index` forward while the pointer or focus is on its entry; `null` to stop. */\n focus: (index: number | null) => void\n /** Where the donut's hole is, if there is one to fill. */\n hole: ComputedRef<{ left: number; top: number; width: number; above?: boolean } | null>\n center: () => VNodeChild\n /** The markers' labels. */\n markers: ComputedRef<Array<MarkerLabel & { key: string; tone: Tone; backdrop: boolean }>>\n /** Data labels: values by the points and on the bars; `ink` is their color, when not the default. */\n data: ComputedRef<Array<PlacedDataLabel & { ink?: string; width?: number }>>\n /** Whether the data labels show (not while the series come in). */\n dataShown: ComputedRef<boolean>\n /** The series brought forward: the other series' labels are faded too. */\n dataFocus: ComputedRef<number | null>\n /** No series has a value: the empty message shows. */\n empty: ComputedRef<boolean>\n emptyContent: () => VNodeChild\n loading: ComputedRef<boolean>\n}\n\ndefineOptions({ name: 'DouChartOverlay' })\n\nconst { state } = defineProps<{ state: OverlayState }>()\nconst ns = useNamespace('chart')\nconst {\n shown,\n labels,\n titles,\n legend,\n legendBox,\n hole,\n toggle,\n isolate,\n hint,\n focus,\n markers,\n data,\n dataShown,\n dataFocus,\n empty,\n loading,\n} = state\nconst Center = () => state.center()\nconst hintId = useId()\n\n/* the legend: a click turns an entry on or off; with Alt, or held down on a touch screen, it shows only that one */\n\n/** How long a finger stays on an entry to show only it, in ms. */\nconst HOLD = 500\nlet holdTimer: ReturnType<typeof setTimeout> | undefined\n/** A hold just showed one entry alone: the click that ends it isn't a toggle. */\nlet held = false\n\nfunction holdLegend(index: number) {\n letGo()\n held = false\n holdTimer = setTimeout(() => {\n holdTimer = undefined\n held = true\n isolate(index)\n }, HOLD)\n}\n\nfunction letGo() {\n if (holdTimer) clearTimeout(holdTimer)\n holdTimer = undefined\n}\n\nfunction onLegendClick(event: MouseEvent, index: number) {\n if (held) {\n held = false\n return\n }\n if (event.altKey) isolate(index)\n else toggle(index)\n}\n\nfunction onLegendKey(event: KeyboardEvent, index: number) {\n if (!event.altKey || (event.key !== 'Enter' && event.key !== ' ')) return\n event.preventDefault()\n isolate(index)\n}\n/** No callout menu over an entry while it is held down. */\nfunction noMenu(event: Event) {\n if (holdTimer || held) event.preventDefault()\n}\nonBeforeUnmount(letGo)\n/** Room around the legend's entries in its box, so a focus ring isn't cut off where it scrolls. */\nconst LEGEND_PAD = 4\nconst Empty = () => state.emptyContent()\n// a click focuses the entry too: only keyboard focus brings its series forward\nconst focusVisible = (e: FocusEvent) => (e.target as Element).matches(':focus-visible')\n</script>\n\n<template>\n <div v-if=\"shown\" :class=\"ns.e('labels')\" aria-hidden=\"true\">\n <span\n v-for=\"tick in labels\"\n :key=\"tick.key\"\n :class=\"[ns.e('tick'), ns.is(tick.axis), ns.is('clipped', !!tick.clipped)]\"\n :style=\"{\n transform: `translate(${tick.left}px, ${tick.top}px)`,\n width: tick.clipped ? `${tick.width}px` : undefined,\n }\"\n ><span :class=\"ns.e('text')\">{{ tick.text }}</span></span\n >\n <span\n v-for=\"title in titles\"\n :key=\"title.key\"\n :class=\"[ns.e('title'), ns.is('end', title.align === 'end')]\"\n :style=\"{ transform: `translate(${title.left}px, ${title.top}px)` }\"\n ><span :class=\"ns.e('text')\">{{ title.text }}</span></span\n >\n <span\n v-for=\"marker in markers\"\n :key=\"marker.key\"\n :class=\"[\n ns.e('marker'),\n ns.is(marker.tone),\n ns.is(marker.align),\n ns.is('backdrop', marker.backdrop),\n ]\"\n :style=\"{ transform: `translate(${marker.left}px, ${marker.top}px)` }\"\n ><span :class=\"ns.e('text')\">{{ marker.text }}</span></span\n >\n <span\n v-for=\"label in data\"\n :key=\"`data:${label.key}`\"\n :class=\"[\n ns.e('value'),\n ns.is(label.align),\n ns.is('inside', !!label.on),\n ns.is('hidden', !dataShown),\n ns.is('faded', dataFocus !== null && dataFocus !== label.series),\n ns.is('clipped', label.width !== undefined),\n ]\"\n :style=\"{\n transform: `translate(${label.left}px, ${label.top}px)`,\n color: label.ink,\n width: label.width === undefined ? undefined : `${label.width}px`,\n }\"\n ><span :class=\"ns.e('text')\">{{ label.text }}</span></span\n >\n </div>\n <div\n v-if=\"shown && legend.length && legendBox\"\n :class=\"[ns.e('legends'), ns.is('scroll', legendBox.scroll)]\"\n :style=\"{\n left: `${legendBox.x - LEGEND_PAD}px`,\n top: `${legendBox.y - LEGEND_PAD}px`,\n width: `${legendBox.width + LEGEND_PAD * 2}px`,\n height: `${legendBox.height + LEGEND_PAD * 2}px`,\n }\"\n >\n <!-- a name cut short shows in full on hover and focus; on a phone the legend goes where names aren't cut -->\n <DouTooltip\n v-for=\"item in legend\"\n :key=\"`legend:${item.index}`\"\n :content=\"item.text\"\n :disabled=\"!item.clipped\"\n >\n <button\n type=\"button\"\n :class=\"[\n ns.e('legend'),\n ns.is(item.kind),\n ns.is('dashed', item.dashed),\n ns.is('off', item.off),\n ns.is('locked', item.locked),\n ns.is('clipped', !!item.clipped),\n ]\"\n :style=\"{\n transform: `translate(${item.left - legendBox.x + LEGEND_PAD}px, ${item.top - legendBox.y + LEGEND_PAD}px)`,\n width: item.clipped ? `${item.width}px` : undefined,\n }\"\n :aria-pressed=\"!item.off\"\n :aria-describedby=\"hintId\"\n aria-keyshortcuts=\"Alt+Enter\"\n @click=\"(e) => onLegendClick(e, item.index)\"\n @keydown=\"(e) => onLegendKey(e, item.index)\"\n @pointerdown=\"(e) => e.pointerType === 'touch' && holdLegend(item.index)\"\n @pointerup=\"letGo\"\n @pointercancel=\"letGo\"\n @contextmenu=\"noMenu\"\n @pointerenter=\"(e) => e.pointerType !== 'touch' && !item.off && focus(item.index)\"\n @pointerleave=\"(letGo(), focus(null))\"\n @focus=\"(e) => focusVisible(e) && !item.off && focus(item.index)\"\n @blur=\"focus(null)\"\n >\n <span\n :class=\"ns.e('swatch')\"\n :style=\"\n item.scale\n ? {\n width: `${item.swatch}px`,\n background: `linear-gradient(to right, ${item.scale.join(', ')})`,\n }\n : item.pattern\n ? {\n color: item.color,\n backgroundImage: item.pattern.image,\n backgroundSize: item.pattern.size,\n }\n : { color: item.color }\n \"\n /><span :class=\"ns.e('text')\">{{ item.text }}</span>\n </button>\n </DouTooltip>\n <span :id=\"hintId\" hidden>{{ hint }}</span>\n </div>\n <div\n v-if=\"hole\"\n :class=\"[ns.e('center'), ns.is('above', !!hole.above)]\"\n :style=\"{ left: `${hole.left}px`, top: `${hole.top}px`, width: `${hole.width}px` }\"\n >\n <Center />\n </div>\n <div v-if=\"empty\" :class=\"ns.e('empty')\"><Empty /></div>\n <Transition name=\"dou-fade\">\n <div v-if=\"loading\" :class=\"ns.e('loading')\"><DouSpinner /></div>\n </Transition>\n</template>\n"],"mappings":"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"}
|
package/dist/pointer.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import pointer_vue_vue_type_script_setup_true_lang_default from "./pointer.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
// src/pointer.vue
|
|
3
|
+
var pointer_default = pointer_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
export { pointer_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=pointer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer.js","names":["_sfc_main"],"sources":["../src/pointer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useNamespace } from 'dou-ui'\nimport { useTemplateRef, watchPostEffect, type ComputedRef, type Ref } from 'vue'\nimport type { Rect } from './core/painter'\nimport type { ChartTooltipItem, ChartTooltipSlots } from './types'\n\n/** What is shown for the point (or x) under the pointer. */\nexport interface Tip {\n title?: string\n items: ChartTooltipItem[]\n /** One of the items' series is under the pointer: the others are muted. */\n focused?: boolean\n /** Where the tooltip points from, in px from the chart's top left. */\n anchor: [number, number]\n /** A hairline across the plot at the x. */\n line?: Rect\n /** A shaded band over the x's room, for bars. */\n band?: Rect\n /** A ring around a heatmap's cell. */\n cell?: Rect\n /** Rings and dots on the points. */\n marks: Array<{\n left: number\n top: number\n color: string\n radius: number\n ring: boolean\n /** Its series is faded: another one is under the pointer. */\n faded?: boolean\n }>\n /** Above the anchor rather than below, out from under a finger. */\n above?: boolean\n /** A place to keep clear of (the x under a finger): the tooltip goes beside it. */\n clear?: Rect\n /** A line under the values (slices left out of a pie). */\n note?: string\n /** The x as given, for `select`. */\n x?: unknown\n}\n\nexport interface PointerState {\n tip: ComputedRef<Tip | null>\n /** The chart's size, to keep the tooltip inside it. */\n size: ComputedRef<{ width: number; height: number } | null>\n content: Ref<ChartTooltipSlots['default'] | undefined>\n /** Read out as the keys move. */\n live: ComputedRef<string>\n}\n\ndefineOptions({ name: 'DouChartPointer' })\n\nconst { state } = defineProps<{ state: PointerState }>()\nconst ns = useNamespace('chart')\nconst { tip, live } = state\nconst box = useTemplateRef<HTMLElement>('box')\n\n/** Room between the tooltip and what it points at, and the chart's edges. */\nconst GAP = 12\nconst EDGE = 4\n\n// placed after it renders, when its size is known: beside the anchor, on whichever side has room\nwatchPostEffect(() => {\n const el = box.value\n const t = tip.value\n const size = state.size.value\n if (!el || !t || !size) return\n const width = el.offsetWidth\n const height = el.offsetHeight\n const c = t.clear\n if (c) {\n const fits = (at: number, span: number, room: number) => at >= EDGE && at + span <= room - EDGE\n if (c.width < c.height) {\n // a column: to its right, or its left, at the top of the plot\n const right = c.x + c.width + GAP\n const left = c.x - GAP - width\n if (fits(right, width, size.width) || fits(left, width, size.width)) {\n const x = fits(right, width, size.width) ? right : left\n el.style.transform = `translate(${Math.round(x)}px, ${Math.round(Math.max(EDGE, c.y))}px)`\n return\n }\n } else {\n // a row: below it, or above it, at the start of the plot\n const below = c.y + c.height + GAP\n const above = c.y - GAP - height\n if (fits(below, height, size.height) || fits(above, height, size.height)) {\n const y = fits(below, height, size.height) ? below : above\n const x = Math.min(Math.max(EDGE, c.x), size.width - EDGE - width)\n el.style.transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`\n return\n }\n }\n }\n const [x, y] = t.anchor\n let left = x + GAP\n if (left + width > size.width - EDGE) left = x - GAP - width\n left = Math.max(EDGE, Math.min(left, size.width - EDGE - width))\n let top = t.above ? y - GAP - height : y + GAP\n if (t.above ? top < EDGE : top + height > size.height - EDGE)\n top = t.above ? y + GAP : y - GAP - height\n top = Math.max(EDGE, Math.min(top, size.height - EDGE - height))\n el.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`\n})\n\nconst px = (r: Rect) => ({\n transform: `translate(${r.x}px, ${r.y}px)`,\n width: `${r.width}px`,\n height: `${r.height}px`,\n})\n</script>\n\n<template>\n <div :class=\"ns.e('live')\" aria-live=\"polite\">{{ live }}</div>\n <div v-if=\"tip\" :class=\"ns.e('pointer')\" aria-hidden=\"true\">\n <div v-if=\"tip.band\" :class=\"ns.e('band')\" :style=\"px(tip.band)\" />\n <div v-if=\"tip.cell\" :class=\"ns.e('cell')\" :style=\"px(tip.cell)\" />\n <div v-if=\"tip.line\" :class=\"ns.e('crosshair')\" :style=\"px(tip.line)\" />\n <span\n v-for=\"(mark, i) in tip.marks\"\n :key=\"i\"\n :class=\"[ns.e('mark'), ns.is('ring', mark.ring), ns.is('faded', !!mark.faded)]\"\n :style=\"{\n transform: `translate(${mark.left - mark.radius}px, ${mark.top - mark.radius}px)`,\n width: `${mark.radius * 2}px`,\n height: `${mark.radius * 2}px`,\n color: mark.color,\n }\"\n />\n <div ref=\"box\" :class=\"ns.e('tooltip')\">\n <component\n :is=\"() => state.content.value!({ title: tip!.title, items: tip!.items, note: tip!.note })\"\n v-if=\"state.content.value\"\n />\n <template v-else>\n <div v-if=\"tip.title\" :class=\"ns.e('tooltip-title')\">\n <span :class=\"ns.e('text')\">{{ tip.title }}</span>\n </div>\n <div\n v-for=\"(item, i) in tip.items\"\n :key=\"i\"\n :class=\"[ns.e('tooltip-item'), ns.is('muted', tip.focused && !item.active)]\"\n >\n <span v-if=\"item.color\" :class=\"ns.e('tooltip-swatch')\" :style=\"{ color: item.color }\" />\n <span :class=\"[ns.e('tooltip-name'), ns.e('text')]\">{{ item.name }}</span>\n <span :class=\"[ns.e('tooltip-value'), ns.e('text')]\">{{ item.text }}</span>\n </div>\n <div v-if=\"tip.note\" :class=\"ns.e('tooltip-note')\">{{ tip.note }}</div>\n </template>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { useNamespace } from "dou-ui";
|
|
2
|
+
import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, resolveDynamicComponent, toDisplayString, unref, useTemplateRef, watchPostEffect } from "vue";
|
|
3
|
+
// src/pointer.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var GAP = 12;
|
|
5
|
+
var EDGE = 4;
|
|
6
|
+
var pointer_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
7
|
+
name: "DouChartPointer",
|
|
8
|
+
__name: "pointer",
|
|
9
|
+
props: { state: {} },
|
|
10
|
+
setup(__props) {
|
|
11
|
+
const ns = useNamespace("chart");
|
|
12
|
+
const { tip, live } = __props.state;
|
|
13
|
+
const box = useTemplateRef("box");
|
|
14
|
+
/** Room between the tooltip and what it points at, and the chart's edges. */
|
|
15
|
+
watchPostEffect(() => {
|
|
16
|
+
const el = box.value;
|
|
17
|
+
const t = tip.value;
|
|
18
|
+
const size = __props.state.size.value;
|
|
19
|
+
if (!el || !t || !size) return;
|
|
20
|
+
const width = el.offsetWidth;
|
|
21
|
+
const height = el.offsetHeight;
|
|
22
|
+
const c = t.clear;
|
|
23
|
+
if (c) {
|
|
24
|
+
const fits = (at, span, room) => at >= EDGE && at + span <= room - EDGE;
|
|
25
|
+
if (c.width < c.height) {
|
|
26
|
+
const right = c.x + c.width + GAP;
|
|
27
|
+
const left = c.x - GAP - width;
|
|
28
|
+
if (fits(right, width, size.width) || fits(left, width, size.width)) {
|
|
29
|
+
const x = fits(right, width, size.width) ? right : left;
|
|
30
|
+
el.style.transform = `translate(${Math.round(x)}px, ${Math.round(Math.max(EDGE, c.y))}px)`;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
const below = c.y + c.height + GAP;
|
|
35
|
+
const above = c.y - GAP - height;
|
|
36
|
+
if (fits(below, height, size.height) || fits(above, height, size.height)) {
|
|
37
|
+
const y = fits(below, height, size.height) ? below : above;
|
|
38
|
+
const x = Math.min(Math.max(EDGE, c.x), size.width - EDGE - width);
|
|
39
|
+
el.style.transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const [x, y] = t.anchor;
|
|
45
|
+
let left = x + GAP;
|
|
46
|
+
if (left + width > size.width - EDGE) left = x - GAP - width;
|
|
47
|
+
left = Math.max(EDGE, Math.min(left, size.width - EDGE - width));
|
|
48
|
+
let top = t.above ? y - GAP - height : y + GAP;
|
|
49
|
+
if (t.above ? top < EDGE : top + height > size.height - EDGE) top = t.above ? y + GAP : y - GAP - height;
|
|
50
|
+
top = Math.max(EDGE, Math.min(top, size.height - EDGE - height));
|
|
51
|
+
el.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
|
|
52
|
+
});
|
|
53
|
+
const px = (r) => ({
|
|
54
|
+
transform: `translate(${r.x}px, ${r.y}px)`,
|
|
55
|
+
width: `${r.width}px`,
|
|
56
|
+
height: `${r.height}px`
|
|
57
|
+
});
|
|
58
|
+
return (_ctx, _cache) => {
|
|
59
|
+
return openBlock(), createElementBlock(Fragment, null, [createElementVNode("div", {
|
|
60
|
+
class: normalizeClass(unref(ns).e("live")),
|
|
61
|
+
"aria-live": "polite"
|
|
62
|
+
}, toDisplayString(unref(live)), 3), unref(tip) ? (openBlock(), createElementBlock("div", {
|
|
63
|
+
key: 0,
|
|
64
|
+
class: normalizeClass(unref(ns).e("pointer")),
|
|
65
|
+
"aria-hidden": "true"
|
|
66
|
+
}, [
|
|
67
|
+
unref(tip).band ? (openBlock(), createElementBlock("div", {
|
|
68
|
+
key: 0,
|
|
69
|
+
class: normalizeClass(unref(ns).e("band")),
|
|
70
|
+
style: normalizeStyle(px(unref(tip).band))
|
|
71
|
+
}, null, 6)) : createCommentVNode("", true),
|
|
72
|
+
unref(tip).cell ? (openBlock(), createElementBlock("div", {
|
|
73
|
+
key: 1,
|
|
74
|
+
class: normalizeClass(unref(ns).e("cell")),
|
|
75
|
+
style: normalizeStyle(px(unref(tip).cell))
|
|
76
|
+
}, null, 6)) : createCommentVNode("", true),
|
|
77
|
+
unref(tip).line ? (openBlock(), createElementBlock("div", {
|
|
78
|
+
key: 2,
|
|
79
|
+
class: normalizeClass(unref(ns).e("crosshair")),
|
|
80
|
+
style: normalizeStyle(px(unref(tip).line))
|
|
81
|
+
}, null, 6)) : createCommentVNode("", true),
|
|
82
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(tip).marks, (mark, i) => {
|
|
83
|
+
return openBlock(), createElementBlock("span", {
|
|
84
|
+
key: i,
|
|
85
|
+
class: normalizeClass([
|
|
86
|
+
unref(ns).e("mark"),
|
|
87
|
+
unref(ns).is("ring", mark.ring),
|
|
88
|
+
unref(ns).is("faded", !!mark.faded)
|
|
89
|
+
]),
|
|
90
|
+
style: normalizeStyle({
|
|
91
|
+
transform: `translate(${mark.left - mark.radius}px, ${mark.top - mark.radius}px)`,
|
|
92
|
+
width: `${mark.radius * 2}px`,
|
|
93
|
+
height: `${mark.radius * 2}px`,
|
|
94
|
+
color: mark.color
|
|
95
|
+
})
|
|
96
|
+
}, null, 6);
|
|
97
|
+
}), 128)),
|
|
98
|
+
createElementVNode("div", {
|
|
99
|
+
ref_key: "box",
|
|
100
|
+
ref: box,
|
|
101
|
+
class: normalizeClass(unref(ns).e("tooltip"))
|
|
102
|
+
}, [__props.state.content.value ? (openBlock(), createBlock(resolveDynamicComponent(() => __props.state.content.value({
|
|
103
|
+
title: unref(tip).title,
|
|
104
|
+
items: unref(tip).items,
|
|
105
|
+
note: unref(tip).note
|
|
106
|
+
})), { key: 0 })) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
107
|
+
unref(tip).title ? (openBlock(), createElementBlock("div", {
|
|
108
|
+
key: 0,
|
|
109
|
+
class: normalizeClass(unref(ns).e("tooltip-title"))
|
|
110
|
+
}, [createElementVNode("span", { class: normalizeClass(unref(ns).e("text")) }, toDisplayString(unref(tip).title), 3)], 2)) : createCommentVNode("", true),
|
|
111
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(tip).items, (item, i) => {
|
|
112
|
+
return openBlock(), createElementBlock("div", {
|
|
113
|
+
key: i,
|
|
114
|
+
class: normalizeClass([unref(ns).e("tooltip-item"), unref(ns).is("muted", unref(tip).focused && !item.active)])
|
|
115
|
+
}, [
|
|
116
|
+
item.color ? (openBlock(), createElementBlock("span", {
|
|
117
|
+
key: 0,
|
|
118
|
+
class: normalizeClass(unref(ns).e("tooltip-swatch")),
|
|
119
|
+
style: normalizeStyle({ color: item.color })
|
|
120
|
+
}, null, 6)) : createCommentVNode("", true),
|
|
121
|
+
createElementVNode("span", { class: normalizeClass([unref(ns).e("tooltip-name"), unref(ns).e("text")]) }, toDisplayString(item.name), 3),
|
|
122
|
+
createElementVNode("span", { class: normalizeClass([unref(ns).e("tooltip-value"), unref(ns).e("text")]) }, toDisplayString(item.text), 3)
|
|
123
|
+
], 2);
|
|
124
|
+
}), 128)),
|
|
125
|
+
unref(tip).note ? (openBlock(), createElementBlock("div", {
|
|
126
|
+
key: 1,
|
|
127
|
+
class: normalizeClass(unref(ns).e("tooltip-note"))
|
|
128
|
+
}, toDisplayString(unref(tip).note), 3)) : createCommentVNode("", true)
|
|
129
|
+
], 64))], 2)
|
|
130
|
+
], 2)) : createCommentVNode("", true)], 64);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
export { pointer_vue_vue_type_script_setup_true_lang_default as default };
|
|
135
|
+
|
|
136
|
+
//# sourceMappingURL=pointer.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_createElementVNode","_normalizeClass","_unref","_toDisplayString","_normalizeStyle","_createCommentVNode","_renderList","_createBlock","_resolveDynamicComponent"],"sources":["../src/pointer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useNamespace } from 'dou-ui'\nimport { useTemplateRef, watchPostEffect, type ComputedRef, type Ref } from 'vue'\nimport type { Rect } from './core/painter'\nimport type { ChartTooltipItem, ChartTooltipSlots } from './types'\n\n/** What is shown for the point (or x) under the pointer. */\nexport interface Tip {\n title?: string\n items: ChartTooltipItem[]\n /** One of the items' series is under the pointer: the others are muted. */\n focused?: boolean\n /** Where the tooltip points from, in px from the chart's top left. */\n anchor: [number, number]\n /** A hairline across the plot at the x. */\n line?: Rect\n /** A shaded band over the x's room, for bars. */\n band?: Rect\n /** A ring around a heatmap's cell. */\n cell?: Rect\n /** Rings and dots on the points. */\n marks: Array<{\n left: number\n top: number\n color: string\n radius: number\n ring: boolean\n /** Its series is faded: another one is under the pointer. */\n faded?: boolean\n }>\n /** Above the anchor rather than below, out from under a finger. */\n above?: boolean\n /** A place to keep clear of (the x under a finger): the tooltip goes beside it. */\n clear?: Rect\n /** A line under the values (slices left out of a pie). */\n note?: string\n /** The x as given, for `select`. */\n x?: unknown\n}\n\nexport interface PointerState {\n tip: ComputedRef<Tip | null>\n /** The chart's size, to keep the tooltip inside it. */\n size: ComputedRef<{ width: number; height: number } | null>\n content: Ref<ChartTooltipSlots['default'] | undefined>\n /** Read out as the keys move. */\n live: ComputedRef<string>\n}\n\ndefineOptions({ name: 'DouChartPointer' })\n\nconst { state } = defineProps<{ state: PointerState }>()\nconst ns = useNamespace('chart')\nconst { tip, live } = state\nconst box = useTemplateRef<HTMLElement>('box')\n\n/** Room between the tooltip and what it points at, and the chart's edges. */\nconst GAP = 12\nconst EDGE = 4\n\n// placed after it renders, when its size is known: beside the anchor, on whichever side has room\nwatchPostEffect(() => {\n const el = box.value\n const t = tip.value\n const size = state.size.value\n if (!el || !t || !size) return\n const width = el.offsetWidth\n const height = el.offsetHeight\n const c = t.clear\n if (c) {\n const fits = (at: number, span: number, room: number) => at >= EDGE && at + span <= room - EDGE\n if (c.width < c.height) {\n // a column: to its right, or its left, at the top of the plot\n const right = c.x + c.width + GAP\n const left = c.x - GAP - width\n if (fits(right, width, size.width) || fits(left, width, size.width)) {\n const x = fits(right, width, size.width) ? right : left\n el.style.transform = `translate(${Math.round(x)}px, ${Math.round(Math.max(EDGE, c.y))}px)`\n return\n }\n } else {\n // a row: below it, or above it, at the start of the plot\n const below = c.y + c.height + GAP\n const above = c.y - GAP - height\n if (fits(below, height, size.height) || fits(above, height, size.height)) {\n const y = fits(below, height, size.height) ? below : above\n const x = Math.min(Math.max(EDGE, c.x), size.width - EDGE - width)\n el.style.transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`\n return\n }\n }\n }\n const [x, y] = t.anchor\n let left = x + GAP\n if (left + width > size.width - EDGE) left = x - GAP - width\n left = Math.max(EDGE, Math.min(left, size.width - EDGE - width))\n let top = t.above ? y - GAP - height : y + GAP\n if (t.above ? top < EDGE : top + height > size.height - EDGE)\n top = t.above ? y + GAP : y - GAP - height\n top = Math.max(EDGE, Math.min(top, size.height - EDGE - height))\n el.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`\n})\n\nconst px = (r: Rect) => ({\n transform: `translate(${r.x}px, ${r.y}px)`,\n width: `${r.width}px`,\n height: `${r.height}px`,\n})\n</script>\n\n<template>\n <div :class=\"ns.e('live')\" aria-live=\"polite\">{{ live }}</div>\n <div v-if=\"tip\" :class=\"ns.e('pointer')\" aria-hidden=\"true\">\n <div v-if=\"tip.band\" :class=\"ns.e('band')\" :style=\"px(tip.band)\" />\n <div v-if=\"tip.cell\" :class=\"ns.e('cell')\" :style=\"px(tip.cell)\" />\n <div v-if=\"tip.line\" :class=\"ns.e('crosshair')\" :style=\"px(tip.line)\" />\n <span\n v-for=\"(mark, i) in tip.marks\"\n :key=\"i\"\n :class=\"[ns.e('mark'), ns.is('ring', mark.ring), ns.is('faded', !!mark.faded)]\"\n :style=\"{\n transform: `translate(${mark.left - mark.radius}px, ${mark.top - mark.radius}px)`,\n width: `${mark.radius * 2}px`,\n height: `${mark.radius * 2}px`,\n color: mark.color,\n }\"\n />\n <div ref=\"box\" :class=\"ns.e('tooltip')\">\n <component\n :is=\"() => state.content.value!({ title: tip!.title, items: tip!.items, note: tip!.note })\"\n v-if=\"state.content.value\"\n />\n <template v-else>\n <div v-if=\"tip.title\" :class=\"ns.e('tooltip-title')\">\n <span :class=\"ns.e('text')\">{{ tip.title }}</span>\n </div>\n <div\n v-for=\"(item, i) in tip.items\"\n :key=\"i\"\n :class=\"[ns.e('tooltip-item'), ns.is('muted', tip.focused && !item.active)]\"\n >\n <span v-if=\"item.color\" :class=\"ns.e('tooltip-swatch')\" :style=\"{ color: item.color }\" />\n <span :class=\"[ns.e('tooltip-name'), ns.e('text')]\">{{ item.name }}</span>\n <span :class=\"[ns.e('tooltip-value'), ns.e('text')]\">{{ item.text }}</span>\n </div>\n <div v-if=\"tip.note\" :class=\"ns.e('tooltip-note')\">{{ tip.note }}</div>\n </template>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
package/dist/static.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import static_vue_vue_type_script_setup_true_lang_default from "./static.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
// src/static.vue
|
|
3
|
+
var static_default = static_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
export { static_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.js","names":["_sfc_main"],"sources":["../src/static.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useNamespace } from 'dou-ui'\nimport { computed, getCurrentInstance, type ComputedRef } from 'vue'\n\n/**\n * The chart drawn on the server, as an SVG filling the chart's box. Its own\n * component, after the chart's parts: on the server those are known only\n * once the chart's slot has rendered. In the browser it keeps the\n * server's drawing until the canvas has drawn.\n */\nexport interface StaticState {\n shown: ComputedRef<boolean>\n size: ComputedRef<{ width: number; height: number }>\n /** The drawing; empty in the browser, which takes the server's. */\n markup: ComputedRef<string>\n /** What the chart shows, read out. */\n label: ComputedRef<string>\n}\n\ndefineOptions({ name: 'DouChartStatic' })\n\nconst { state } = defineProps<{ state: StaticState }>()\nconst ns = useNamespace('chart')\nconst { shown, size, label } = state\n// taking over the server's page: its drawing, as the browser doesn't draw one\nconst taken = getCurrentInstance()?.vnode.el\nconst kept =\n typeof Element !== 'undefined' && taken instanceof Element && taken.matches(`.${ns.e('static')}`)\n ? taken.innerHTML\n : ''\nconst markup = computed(() => state.markup.value || kept)\n</script>\n\n<template>\n <svg\n v-if=\"shown\"\n :class=\"ns.e('static')\"\n xmlns=\"http://www.w3.org/2000/svg\"\n :viewBox=\"`0 0 ${size.width} ${size.height}`\"\n role=\"img\"\n :aria-label=\"label\"\n v-html=\"markup\"\n />\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useNamespace } from "dou-ui";
|
|
2
|
+
import { computed, createCommentVNode, createElementBlock, defineComponent, getCurrentInstance, normalizeClass, openBlock, unref } from "vue";
|
|
3
|
+
// src/static.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var _hoisted_1 = [
|
|
5
|
+
"viewBox",
|
|
6
|
+
"aria-label",
|
|
7
|
+
"innerHTML"
|
|
8
|
+
];
|
|
9
|
+
var static_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
10
|
+
name: "DouChartStatic",
|
|
11
|
+
__name: "static",
|
|
12
|
+
props: { state: {} },
|
|
13
|
+
setup(__props) {
|
|
14
|
+
const ns = useNamespace("chart");
|
|
15
|
+
const { shown, size, label } = __props.state;
|
|
16
|
+
const taken = getCurrentInstance()?.vnode.el;
|
|
17
|
+
const kept = typeof Element !== "undefined" && taken instanceof Element && taken.matches(`.${ns.e("static")}`) ? taken.innerHTML : "";
|
|
18
|
+
const markup = computed(() => __props.state.markup.value || kept);
|
|
19
|
+
return (_ctx, _cache) => {
|
|
20
|
+
return unref(shown) ? (openBlock(), createElementBlock("svg", {
|
|
21
|
+
key: 0,
|
|
22
|
+
class: normalizeClass(unref(ns).e("static")),
|
|
23
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
24
|
+
viewBox: `0 0 ${unref(size).width} ${unref(size).height}`,
|
|
25
|
+
role: "img",
|
|
26
|
+
"aria-label": unref(label),
|
|
27
|
+
innerHTML: markup.value
|
|
28
|
+
}, null, 10, _hoisted_1)) : createCommentVNode("", true);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
export { static_vue_vue_type_script_setup_true_lang_default as default };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=static.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.vue_vue_type_script_setup_true_lang.js","names":["_unref","_openBlock","_createElementBlock","_normalizeClass","_createCommentVNode"],"sources":["../src/static.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useNamespace } from 'dou-ui'\nimport { computed, getCurrentInstance, type ComputedRef } from 'vue'\n\n/**\n * The chart drawn on the server, as an SVG filling the chart's box. Its own\n * component, after the chart's parts: on the server those are known only\n * once the chart's slot has rendered. In the browser it keeps the\n * server's drawing until the canvas has drawn.\n */\nexport interface StaticState {\n shown: ComputedRef<boolean>\n size: ComputedRef<{ width: number; height: number }>\n /** The drawing; empty in the browser, which takes the server's. */\n markup: ComputedRef<string>\n /** What the chart shows, read out. */\n label: ComputedRef<string>\n}\n\ndefineOptions({ name: 'DouChartStatic' })\n\nconst { state } = defineProps<{ state: StaticState }>()\nconst ns = useNamespace('chart')\nconst { shown, size, label } = state\n// taking over the server's page: its drawing, as the browser doesn't draw one\nconst taken = getCurrentInstance()?.vnode.el\nconst kept =\n typeof Element !== 'undefined' && taken instanceof Element && taken.matches(`.${ns.e('static')}`)\n ? taken.innerHTML\n : ''\nconst markup = computed(() => state.markup.value || kept)\n</script>\n\n<template>\n <svg\n v-if=\"shown\"\n :class=\"ns.e('static')\"\n xmlns=\"http://www.w3.org/2000/svg\"\n :viewBox=\"`0 0 ${size.width} ${size.height}`\"\n role=\"img\"\n :aria-label=\"label\"\n v-html=\"markup\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;EAsBA,MAAM,KAAK,aAAa,OAAO;EAC/B,MAAM,EAAE,OAAO,MAAM,UAAU,QAAA;EAE/B,MAAM,QAAQ,mBAAmB,CAAC,EAAE,MAAM;EAC1C,MAAM,OACJ,OAAO,YAAY,eAAe,iBAAiB,WAAW,MAAM,QAAQ,IAAI,GAAG,EAAE,QAAQ,GAAG,IAC5F,MAAM,YACN;EACN,MAAM,SAAS,eAAe,QAAA,MAAM,OAAO,SAAS,IAAI;;GAK9C,OAAAA,MAAA,KAAA,KADRC,UAAA,GAAAC,mBAQE,OAAA;;IANC,OAAKC,eAAEH,MAAA,EAAA,CAAE,CAAC,EAAC,QAAA,CAAA;IACZ,OAAM;IACL,SAAO,OAASA,MAAA,IAAA,CAAI,CAAC,MAAK,GAAIA,MAAA,IAAA,CAAI,CAAC;IACpC,MAAK;IACJ,cAAYA,MAAA,KAAA;IACb,WAAQ,OAAA"}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer dou.components{.dou-chart{--dou-chart-surface:var(--dou-color-bg-surface);--dou-chart-grid:var(--dou-color-border-subtle);--dou-chart-baseline:var(--dou-color-border-strong);--dou-chart-label:var(--dou-color-text-tertiary);--dou-chart-title:var(--dou-color-text-secondary);--dou-chart-range-ink:var(--dou-color-text-tertiary);--dou-chart-marker:color-mix(in oklab,var(--dou-color-text)45%,transparent);--dou-chart-track:color-mix(in oklab,var(--dou-color-text)10%,transparent);position:relative;box-sizing:border-box;overflow:hidden;color:var(--dou-color-text);font-family:var(--dou-font-family);font-variant-numeric:tabular-nums;width:100%;min-width:0;font-size:12px;line-height:16px}.dou-chart__canvas{position:absolute;display:block;top:0;left:0}.dou-chart__static{position:absolute;display:block;width:100%;height:100%;font-size:12px;inset:0}.dou-chart__canvas,.dou-chart__static,.dou-chart__labels,.dou-chart__legends{transition:opacity var(--dou-motion-duration-fast)var(--dou-motion-easing)}.dou-chart.is-loading>:is(.dou-chart__canvas,.dou-chart__static,.dou-chart__labels,.dou-chart__legends){opacity:.4}.dou-chart__loading{position:absolute;display:flex;color:var(--dou-color-text-secondary);justify-content:center;align-items: center;inset:0}.dou-chart__labels{position:absolute;pointer-events:none;inset:0}.dou-chart__tick,.dou-chart__title{position:absolute;display:flex;white-space:nowrap;align-items: center;height:16px}.dou-chart__text{text-box:trim-both cap alphabetic}.dou-chart__tick{color:var(--dou-chart-label);will-change:transform;top:0;left:0}.dou-chart__tick.is-value{color:var(--dou-color-text-secondary);font-variant-numeric:tabular-nums}.dou-chart__tick.is-rate{font-variant-numeric:tabular-nums}.dou-chart__tick.is-clipped{pointer-events:auto}.dou-chart__tick.is-clipped>.dou-chart__text{overflow:hidden;text-overflow:ellipsis;text-box:normal;min-width:0;line-height:16px}.dou-chart__value{position:absolute;display:flex;color:var(--dou-color-text-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;transition:opacity var(--dou-motion-duration-fast)var(--dou-motion-easing);align-items: center;height:16px;top:0;left:0}.dou-chart__value.is-middle{translate:-50%}.dou-chart__value.is-end{translate:-100%}.dou-chart__value.is-inside{font-weight:var(--dou-font-weight-medium)}.dou-chart__value.is-faded{opacity:.24}.dou-chart__value.is-clipped{pointer-events:auto}.dou-chart__value.is-clipped>.dou-chart__text{overflow:hidden;text-overflow:ellipsis;text-box:normal;min-width:0;line-height:16px}.dou-chart__value.is-hidden{opacity:0;transition:none}.dou-chart__marker{position:absolute;display:flex;color:var(--dou-color-text-secondary);white-space:nowrap;align-items: center;height:16px;top:0;left:0}.dou-chart__marker.is-middle{translate:-50%}.dou-chart__marker.is-end{translate:-100%}.dou-chart__marker.is-backdrop{background-color:color-mix(in oklab,currentColor 10%,var(--dou-chart-surface));border-radius:4px;padding-inline-start:4px;padding-inline-end:4px}.dou-chart__marker.is-backdrop.is-start{margin-left:-4px}.dou-chart__marker.is-backdrop.is-end{margin-left:4px}.dou-chart__marker.is-primary{color:var(--dou-color-primary-text)}.dou-chart__marker.is-success{color:var(--dou-color-success-text)}.dou-chart__marker.is-warning{color:var(--dou-color-warning-text)}.dou-chart__marker.is-danger{color:var(--dou-color-danger-text)}.dou-chart__measure{visibility:hidden;contain:layout style}.dou-chart__title,.dou-chart__legend{top:0;left:0}.dou-chart.is-interactive:focus-visible{outline:2px solid var(--dou-color-focus);outline-offset:2px;border-radius:var(--dou-radius-control)}.dou-chart__legends{position:absolute;pointer-events:none}.dou-chart__legends.is-scroll{overflow-y:auto;overscroll-behavior:contain;pointer-events:auto;scrollbar-width:thin}.dou-chart__title{color:var(--dou-chart-title);font-weight:var(--dou-font-weight-medium)}.dou-chart__title.is-end{translate:-100%}.dou-chart__legend{position:absolute;display:flex;color:var(--dou-color-text-secondary);font:inherit;white-space:nowrap;cursor:pointer;pointer-events:auto;transition:color var(--dou-motion-duration-fast)var(--dou-motion-easing);-webkit-touch-callout:none;user-select:none;background:0 0;border:0;border-radius:2px;align-items: center;gap:6px;height:16px;padding:0}.dou-chart__legend:before{position:absolute;content:"";inset:-6px -4px}@media (pointer:coarse){.dou-chart__legend:before{inset:-12px -4px}}.dou-chart__legend:hover{color:var(--dou-color-text)}.dou-chart__legend:focus-visible{outline:2px solid var(--dou-color-focus);outline-offset:2px}.dou-chart__legend.is-clipped>.dou-chart__text{overflow:hidden;text-overflow:ellipsis;text-box:normal;min-width:0;line-height:16px}.dou-chart__legend.is-locked{cursor:default}.dou-chart__legend.is-locked:hover{color:var(--dou-color-text-secondary)}.dou-chart__legend.is-off{color:var(--dou-color-text-disabled)}.dou-chart__legend.is-off>.dou-chart__swatch{opacity:.32}.dou-chart__swatch{background-color:currentColor;border-radius:1px;flex-shrink:0;width:12px;height:2px}.is-area>.dou-chart__swatch{border-radius:2px;height:8px}.is-radar>.dou-chart__swatch{border-radius:2px;height:8px}.is-bar>.dou-chart__swatch{border-radius:2px;width:8px;height:8px;margin-inline-start:2px;margin-inline-end:2px}.is-pie>.dou-chart__swatch{border-radius:2px;width:8px;height:8px;margin-inline-start:2px;margin-inline-end:2px}.is-box>.dou-chart__swatch{box-sizing:border-box;background-color:color-mix(in srgb,currentColor 16%,transparent);border:1px solid;border-radius:1px;width:8px;height:10px;margin-inline-start:2px;margin-inline-end:2px}.is-scatter>.dou-chart__swatch{border-radius:50%;width:8px;height:8px;margin-inline-start:2px;margin-inline-end:2px}.is-heatmap>.dou-chart__swatch{box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--dou-color-text)8%,transparent);border-radius:2px;height:8px}.is-dashed>.dou-chart__swatch{background:repeating-linear-gradient(90deg,currentColor 0 4px,#0000 4px 7px)}.dou-chart__center{position:absolute;display:flex;text-align:center;flex-direction:column;justify-content:center;align-items: center;translate:-50% -50%}.dou-chart__center.is-above{translate:-50% calc(-100% - 4px)}.dou-chart__gauge-value{color:var(--dou-color-text);font-size:var(--dou-chart-gauge-value-size,28px);font-weight:var(--dou-font-weight-bold);font-variant-numeric:tabular-nums;line-height:1.3}.dou-chart__gauge-name{color:var(--dou-color-text-tertiary);font-size:var(--dou-font-size-sm);line-height:20px}.dou-chart__empty{position:absolute;display:flex;color:var(--dou-color-text-tertiary);font-size:var(--dou-font-size-sm);justify-content:center;align-items: center;inset:0}.dou-chart.is-table>:not(:-webkit-any(.dou-chart__table,.dou-chart__parts)){visibility:hidden}.dou-chart.is-table>:not(:-moz-any(.dou-chart__table,.dou-chart__parts)){visibility:hidden}.dou-chart.is-table>:not(:is(.dou-chart__table,.dou-chart__parts)){visibility:hidden}.dou-chart__table{position:absolute;overflow:auto;border:1px solid var(--dou-color-border);border-radius:var(--dou-radius-container);background-color:var(--dou-chart-surface);color:var(--dou-color-text);font-size:var(--dou-font-size-sm);overscroll-behavior:contain;line-height:1.5;inset:0}.dou-chart__table:focus-visible{outline:2px solid var(--dou-color-focus);outline-offset:2px}.dou-chart__table table{border-collapse:separate;border-spacing:0;font-variant-numeric:tabular-nums;width:100%}.dou-chart__table caption{position:absolute;overflow:hidden;clip-path:inset(50%);white-space:nowrap;width:1px;height:1px}.dou-chart__table th{box-sizing:border-box;border-bottom:1px solid var(--dou-color-border-subtle);text-align:end;white-space:nowrap;height:36px;padding:6px 10px}.dou-chart__table td{box-sizing:border-box;border-bottom:1px solid var(--dou-color-border-subtle);text-align:end;white-space:nowrap;height:36px;padding:6px 10px}.dou-chart__table th[scope=row]{text-align:start}.dou-chart__table thead th:first-child{text-align:start}.dou-chart__table th[scope=row]{font-weight:var(--dou-font-weight-regular)}.dou-chart__table thead th{position:sticky;z-index:1;border-bottom-color:var(--dou-color-border);background-color:color-mix(in oklab,var(--dou-color-text)2.5%,var(--dou-chart-surface));color:var(--dou-color-text-secondary);font-weight:var(--dou-font-weight-medium);height:32px;top:0}.dou-chart__table tbody tr:last-child>*{border-bottom:0}.dou-chart__table-more{border-top:1px solid var(--dou-color-border-subtle);color:var(--dou-color-text-tertiary);margin:0;padding:8px 10px}.dou-chart__pointer{position:absolute;pointer-events:none;inset:0}.dou-chart__crosshair,.dou-chart__band,.dou-chart__cell,.dou-chart__mark,.dou-chart__tooltip{position:absolute;top:0;left:0}.dou-chart__crosshair{background-color:var(--dou-chart-baseline)}.dou-chart__band{background-color:color-mix(in oklab,var(--dou-color-text)5%,transparent)}.dou-chart__cell{box-sizing:border-box;border:2px solid var(--dou-color-text);box-shadow:inset 0 0 0 1px var(--dou-chart-surface);border-radius:4px}.dou-chart__mark{box-sizing:border-box;border:2px solid var(--dou-chart-surface);box-shadow:0 0 0 1px color-mix(in oklab,currentColor 24%,transparent);background-color:currentColor;border-radius:50%}.dou-chart__mark.is-faded{opacity:.32}.dou-chart__mark.is-ring{box-shadow:0 0 0 1px var(--dou-chart-surface);background:0 0;border-color:currentColor}.dou-chart__tooltip{--dou-chart-tooltip-bg:color-mix(in oklab,var(--dou-color-text)calc(4%*var(--dou-scheme-dark)),var(--dou-color-bg-surface));box-sizing:border-box;border:1px solid var(--dou-color-border);border-radius:var(--dou-radius-container);background-color:var(--dou-chart-tooltip-bg);box-shadow:var(--dou-shadow-md);color:var(--dou-color-text-secondary);will-change:transform;min-width:120px;max-width:min(280px,100% - 8px);padding:8px 10px}.dou-chart__tooltip-title{display:flex;color:var(--dou-color-text);font-weight:var(--dou-font-weight-medium);align-items: center;min-height:16px;margin-bottom:6px}.dou-chart__tooltip-item{display:flex;align-items: center;gap:6px;min-height:16px}.dou-chart__tooltip-item+.dou-chart__tooltip-item{margin-top:4px}.dou-chart__tooltip-item.is-muted{color:var(--dou-color-text-tertiary)}.dou-chart__tooltip-item.is-muted>.dou-chart__tooltip-value{color:var(--dou-color-text-secondary)}.dou-chart__tooltip-swatch{box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--dou-color-text)8%,transparent);background-color:currentColor;border-radius:2px;flex-shrink:0;width:8px;height:8px}.dou-chart__tooltip-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-box:normal;flex:1;min-width:0;line-height:16px}.dou-chart__tooltip-value{color:var(--dou-color-text);font-weight:var(--dou-font-weight-medium);white-space:nowrap;margin-left:12px}.dou-chart__tooltip-note{color:var(--dou-color-text-tertiary);margin-top:6px;line-height:16px}.dou-chart__live{position:absolute;overflow:hidden;clip-path:inset(50%);white-space:nowrap;width:1px;height:1px}.dou-chart.is-zoomed{cursor:grab}.dou-chart.is-brushing{cursor:crosshair}.dou-chart__brush{position:absolute;box-sizing:border-box;border:1px solid color-mix(in oklab,var(--dou-color-text)28%,transparent);background-color:color-mix(in oklab,var(--dou-color-text)6%,transparent);pointer-events:none;top:0;left:0}.dou-chart__range{position:absolute;box-sizing:border-box;border-radius:var(--dou-radius-control);box-shadow:inset 0 0 0 1px var(--dou-color-border-subtle);cursor:pointer;touch-action:none;user-select:none;top:0;left:0}.dou-chart__range-canvas{position:absolute;display:block;opacity:.56;top:0;left:0}.dou-chart__range-shade,.dou-chart__range-window,.dou-chart__range-handle{position:absolute;top:0;left:0}.dou-chart__range-shade{background-color:color-mix(in oklab,var(--dou-chart-surface)72%,transparent)}.dou-chart__range-window{box-sizing:border-box;--dou-chart-range-edge:color-mix(in oklab,var(--dou-color-text)32%,transparent);border-block:1px solid var(--dou-chart-range-edge);background-color:color-mix(in oklab,var(--dou-color-text)6%,transparent);cursor:grab}.is-vertical>.dou-chart__range-window{border-block-start:none;border-block-end:none;border-inline:1px solid var(--dou-chart-range-edge)}.dou-chart__range-handle{box-sizing:border-box;border:1px solid var(--dou-color-border-strong);background-color:var(--dou-color-bg-surface);box-shadow:var(--dou-shadow-sm);outline:none;cursor:ew-resize;border-radius:4px;width:8px;height:20px;margin:6px 0 0 -4px}.dou-chart__range-handle:before{position:absolute;content:"";inset:-6px -8px}.dou-chart__range-handle:hover{border-color:var(--dou-color-text-tertiary)}.dou-chart__range-handle:focus-visible{outline:2px solid var(--dou-color-focus);outline-offset:2px}.is-vertical>.dou-chart__range-handle{cursor:ns-resize;width:20px;height:8px;margin:-4px 0 0 6px}.is-vertical>.dou-chart__range-handle:before{inset:-8px -6px}@media (pointer:coarse){.dou-chart__range-handle:before{inset:-10px -16px}.is-vertical>.dou-chart__range-handle:before{inset:-16px -10px}}}
|
package/dist/style.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/style.js
ADDED
package/dist/table.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import table_vue_vue_type_script_setup_true_lang_default from "./table.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
// src/table.vue
|
|
3
|
+
var table_default = table_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
export { table_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","names":["_sfc_main"],"sources":["../src/table.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useNamespace } from 'dou-ui'\nimport type { ComputedRef } from 'vue'\n\n/** The chart's data as a table, shown in its place. */\nexport interface TableState {\n shown: ComputedRef<boolean>\n caption: ComputedRef<string>\n head: ComputedRef<string[]>\n /** Each row's cells; the first is the row's head. */\n rows: ComputedRef<string[][]>\n /** A line under a table cut short. */\n more: ComputedRef<string>\n /** Escape in the table: back to the chart. */\n close: () => void\n}\n\ndefineOptions({ name: 'DouChartTable' })\n\nconst { state } = defineProps<{ state: TableState }>()\nconst ns = useNamespace('chart')\nconst { shown, caption, head, rows, more } = state\n\nfunction onKeydown(event: KeyboardEvent) {\n // the chart's own keys are for its tooltip\n event.stopPropagation()\n if (event.key === 'Escape') state.close()\n}\n</script>\n\n<template>\n <!-- scrolls on its own, so it can take focus and be scrolled with the keys -->\n <!-- oxlint-disable-next-line vuejs-accessibility/no-noninteractive-tabindex -->\n <div\n v-if=\"shown\"\n :class=\"ns.e('table')\"\n tabindex=\"0\"\n @keydown=\"onKeydown\"\n @pointerdown.stop\n @pointermove.stop\n @wheel.stop\n @dblclick.stop\n >\n <table>\n <caption>\n {{\n caption\n }}\n </caption>\n <thead>\n <tr>\n <th v-for=\"(cell, i) in head\" :key=\"i\" scope=\"col\">{{ cell }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, r) in rows\" :key=\"r\">\n <template v-for=\"(cell, i) in row\" :key=\"i\">\n <th v-if=\"i === 0\" scope=\"row\">{{ cell }}</th>\n <td v-else>{{ cell }}</td>\n </template>\n </tr>\n </tbody>\n </table>\n <p v-if=\"more\" :class=\"ns.e('table-more')\">{{ more }}</p>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useNamespace } from "dou-ui";
|
|
2
|
+
import { Fragment, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, withModifiers } from "vue";
|
|
3
|
+
// src/table.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var _hoisted_1 = {
|
|
5
|
+
key: 0,
|
|
6
|
+
scope: "row"
|
|
7
|
+
};
|
|
8
|
+
var _hoisted_2 = { key: 1 };
|
|
9
|
+
var table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
10
|
+
name: "DouChartTable",
|
|
11
|
+
__name: "table",
|
|
12
|
+
props: { state: {} },
|
|
13
|
+
setup(__props) {
|
|
14
|
+
const ns = useNamespace("chart");
|
|
15
|
+
const { shown, caption, head, rows, more } = __props.state;
|
|
16
|
+
function onKeydown(event) {
|
|
17
|
+
event.stopPropagation();
|
|
18
|
+
if (event.key === "Escape") __props.state.close();
|
|
19
|
+
}
|
|
20
|
+
return (_ctx, _cache) => {
|
|
21
|
+
return unref(shown) ? (openBlock(), createElementBlock("div", {
|
|
22
|
+
key: 0,
|
|
23
|
+
class: normalizeClass(unref(ns).e("table")),
|
|
24
|
+
tabindex: "0",
|
|
25
|
+
onKeydown,
|
|
26
|
+
onPointerdown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"])),
|
|
27
|
+
onPointermove: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"])),
|
|
28
|
+
onWheel: _cache[2] || (_cache[2] = withModifiers(() => {}, ["stop"])),
|
|
29
|
+
onDblclick: _cache[3] || (_cache[3] = withModifiers(() => {}, ["stop"]))
|
|
30
|
+
}, [createElementVNode("table", null, [
|
|
31
|
+
createElementVNode("caption", null, toDisplayString(unref(caption)), 1),
|
|
32
|
+
createElementVNode("thead", null, [createElementVNode("tr", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(head), (cell, i) => {
|
|
33
|
+
return openBlock(), createElementBlock("th", {
|
|
34
|
+
key: i,
|
|
35
|
+
scope: "col"
|
|
36
|
+
}, toDisplayString(cell), 1);
|
|
37
|
+
}), 128))])]),
|
|
38
|
+
createElementVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(rows), (row, r) => {
|
|
39
|
+
return openBlock(), createElementBlock("tr", { key: r }, [(openBlock(true), createElementBlock(Fragment, null, renderList(row, (cell, i) => {
|
|
40
|
+
return openBlock(), createElementBlock(Fragment, { key: i }, [i === 0 ? (openBlock(), createElementBlock("th", _hoisted_1, toDisplayString(cell), 1)) : (openBlock(), createElementBlock("td", _hoisted_2, toDisplayString(cell), 1))], 64);
|
|
41
|
+
}), 128))]);
|
|
42
|
+
}), 128))])
|
|
43
|
+
]), unref(more) ? (openBlock(), createElementBlock("p", {
|
|
44
|
+
key: 0,
|
|
45
|
+
class: normalizeClass(unref(ns).e("table-more"))
|
|
46
|
+
}, toDisplayString(unref(more)), 3)) : createCommentVNode("", true)], 34)) : createCommentVNode("", true);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
export { table_vue_vue_type_script_setup_true_lang_default as default };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=table.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.vue_vue_type_script_setup_true_lang.js","names":["_unref","_openBlock","_createElementBlock","_normalizeClass","_withModifiers","_createElementVNode","_toDisplayString","_Fragment","_renderList","_createCommentVNode"],"sources":["../src/table.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useNamespace } from 'dou-ui'\nimport type { ComputedRef } from 'vue'\n\n/** The chart's data as a table, shown in its place. */\nexport interface TableState {\n shown: ComputedRef<boolean>\n caption: ComputedRef<string>\n head: ComputedRef<string[]>\n /** Each row's cells; the first is the row's head. */\n rows: ComputedRef<string[][]>\n /** A line under a table cut short. */\n more: ComputedRef<string>\n /** Escape in the table: back to the chart. */\n close: () => void\n}\n\ndefineOptions({ name: 'DouChartTable' })\n\nconst { state } = defineProps<{ state: TableState }>()\nconst ns = useNamespace('chart')\nconst { shown, caption, head, rows, more } = state\n\nfunction onKeydown(event: KeyboardEvent) {\n // the chart's own keys are for its tooltip\n event.stopPropagation()\n if (event.key === 'Escape') state.close()\n}\n</script>\n\n<template>\n <!-- scrolls on its own, so it can take focus and be scrolled with the keys -->\n <!-- oxlint-disable-next-line vuejs-accessibility/no-noninteractive-tabindex -->\n <div\n v-if=\"shown\"\n :class=\"ns.e('table')\"\n tabindex=\"0\"\n @keydown=\"onKeydown\"\n @pointerdown.stop\n @pointermove.stop\n @wheel.stop\n @dblclick.stop\n >\n <table>\n <caption>\n {{\n caption\n }}\n </caption>\n <thead>\n <tr>\n <th v-for=\"(cell, i) in head\" :key=\"i\" scope=\"col\">{{ cell }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, r) in rows\" :key=\"r\">\n <template v-for=\"(cell, i) in row\" :key=\"i\">\n <th v-if=\"i === 0\" scope=\"row\">{{ cell }}</th>\n <td v-else>{{ cell }}</td>\n </template>\n </tr>\n </tbody>\n </table>\n <p v-if=\"more\" :class=\"ns.e('table-more')\">{{ more }}</p>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAoBA,MAAM,KAAK,aAAa,OAAO;EAC/B,MAAM,EAAE,OAAO,SAAS,MAAM,MAAM,SAAS,QAAA;EAE7C,SAAS,UAAU,OAAsB;GAEvC,MAAM,gBAAgB;GACtB,IAAI,MAAM,QAAQ,UAAU,QAAA,MAAM,MAAM;EAC1C;;GAOU,OAAAA,MAAA,KAAA,KADRC,UAAA,GAAAC,mBA+BM,OAAA;;IA7BH,OAAKC,eAAEH,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;IACZ,UAAS;IACC;IACT,eAAW,OAAA,OAAA,OAAA,KAAAI,oBAAZ,CAAA,GAAiB,CAAA,MAAA,CAAA;IAChB,eAAW,OAAA,OAAA,OAAA,KAAAA,oBAAZ,CAAA,GAAiB,CAAA,MAAA,CAAA;IAChB,SAAK,OAAA,OAAA,OAAA,KAAAA,oBAAN,CAAA,GAAW,CAAA,MAAA,CAAA;IACV,YAAQ,OAAA,OAAA,OAAA,KAAAA,oBAAT,CAAA,GAAc,CAAA,MAAA,CAAA;G,IAEdC,mBAmBQ,SAAA,MAAA;IAlBNA,mBAIU,WAAA,MAAAC,gBAFNN,MAAA,OAAA,CAAO,GAAA,CAAA;IAGXK,mBAIQ,SAAA,MAAA,CAHNA,mBAEK,MAAA,MAAA,EADHJ,UAAA,IAAA,GAAAC,mBAAkEK,UAAA,MAAAC,WAA1CR,MAAA,IAAA,IAAZ,MAAM,MAAC;KAAnB,OAAAC,UAAA,GAAAC,mBAAkE,MAAA;MAAnC,KAAK;MAAG,OAAM;KAAS,GAAAI,gBAAA,IAAI,GAAA,CAAA;;IAG9DD,mBAOQ,SAAA,MAAA,EANNJ,UAAA,IAAA,GAAAC,mBAKKK,UAAA,MAAAC,WALkBR,MAAA,IAAA,IAAX,KAAK,MAAC;KAAlB,OAAAC,UAAA,GAAAC,mBAKK,MAAA,EALyB,KAAK,EAAC,GAAA,EAClCD,UAAA,IAAA,GAAAC,mBAGWK,UAAA,MAAAC,WAHmB,MAAZ,MAAM,MAAC;MAAgB,OAAAP,UAAA,GAAAC,mBAAAK,UAAA,EAAA,KAAA,EAAC,GAAA,CAC9B,MAAC,KAAXN,UAAA,GAAAC,mBAA8C,MAA9C,YAA8CI,gBAAZ,IAAI,GAAA,CAAA,MACtCL,UAAA,GAAAC,mBAA0B,MAAA,YAAAI,gBAAZ,IAAI,GAAA,CAAA,E;;;G,IAKjBN,MAAA,IAAA,KAATC,UAAA,GAAAC,mBAAyD,KAAA;;IAAzC,OAAKC,eAAEH,MAAA,EAAA,CAAE,CAAC,EAAC,YAAA,CAAA;GAAmB,GAAAM,gBAAAN,MAAA,IAAA,CAAI,GAAA,CAAA,K"}
|