@typlog/ui 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addons.css +214 -92
- package/addons.d.ts +192 -35
- package/addons.js +1808 -480
- package/base.css +130 -0
- package/charts.css +161 -0
- package/charts.d.ts +233 -0
- package/charts.js +382 -0
- package/components.css +398 -0
- package/components.d.ts +1358 -886
- package/components.js +4904 -4376
- package/package.json +21 -2
- package/tailwind.css +1 -0
- package/util-lkbchXvM.js +42 -0
package/charts.js
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { r as useForwardPropsWithout, t as buildPropsClass } from "./util-lkbchXvM.js";
|
|
2
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, guardReactiveProps, h, mergeProps, normalizeClass, normalizeProps, normalizeStyle, onMounted, onUnmounted, openBlock, ref, render, renderList, renderSlot, toDisplayString, toRef, unref, useId, watch, withCtx } from "vue";
|
|
3
|
+
import { Primitive, createContext } from "reka-ui";
|
|
4
|
+
import { Icon, buildIcon, getIcon, loadIcons } from "@iconify/vue";
|
|
5
|
+
import { VisCrosshair, VisTooltip } from "@unovis/vue";
|
|
6
|
+
import { Donut, GroupedBar, StackedBar } from "@unovis/ts";
|
|
7
|
+
//#region src/charts/context.ts
|
|
8
|
+
var [injectChartContext, provideChartContext] = createContext("ui:Chart");
|
|
9
|
+
var defaultChartColors = [
|
|
10
|
+
"var(--accent-9)",
|
|
11
|
+
"var(--blue-9)",
|
|
12
|
+
"var(--ruby-9)",
|
|
13
|
+
"var(--green-9)",
|
|
14
|
+
"var(--amber-9)",
|
|
15
|
+
"var(--cyan-9)"
|
|
16
|
+
];
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/charts/util.ts
|
|
19
|
+
function getChartEntries(config) {
|
|
20
|
+
return Object.entries(config).filter((entry) => entry[1].role !== "x").map(([key, series], index) => ({
|
|
21
|
+
key,
|
|
22
|
+
series,
|
|
23
|
+
index
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
function getChartColors(config) {
|
|
27
|
+
return getChartEntries(config).map(({ series, index }) => series.color ?? defaultChartColors[index % defaultChartColors.length]);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/charts/ChartRoot.vue
|
|
31
|
+
var ChartRoot_default = /* @__PURE__ */ defineComponent({
|
|
32
|
+
__name: "ChartRoot",
|
|
33
|
+
props: {
|
|
34
|
+
config: {},
|
|
35
|
+
asChild: { type: Boolean },
|
|
36
|
+
as: { default: "div" }
|
|
37
|
+
},
|
|
38
|
+
setup(__props) {
|
|
39
|
+
const props = __props;
|
|
40
|
+
const forwarded = useForwardPropsWithout(props, ["config"]);
|
|
41
|
+
const config = toRef(props, "config");
|
|
42
|
+
const mounted = ref(false);
|
|
43
|
+
onMounted(() => {
|
|
44
|
+
mounted.value = true;
|
|
45
|
+
});
|
|
46
|
+
const series = computed(() => getChartEntries(config.value));
|
|
47
|
+
const colors = computed(() => getChartColors(config.value));
|
|
48
|
+
const chartStyle = computed(() => {
|
|
49
|
+
const style = {};
|
|
50
|
+
defaultChartColors.forEach((color, index) => {
|
|
51
|
+
style[`--chart-${index + 1}`] = color;
|
|
52
|
+
});
|
|
53
|
+
colors.value.forEach((color, index) => {
|
|
54
|
+
style[`--chart-${index + 1}`] = color;
|
|
55
|
+
style[`--vis-color${index}`] = color;
|
|
56
|
+
});
|
|
57
|
+
return style;
|
|
58
|
+
});
|
|
59
|
+
provideChartContext({
|
|
60
|
+
config,
|
|
61
|
+
series,
|
|
62
|
+
colors,
|
|
63
|
+
mounted
|
|
64
|
+
});
|
|
65
|
+
return (_ctx, _cache) => {
|
|
66
|
+
return openBlock(), createBlock(unref(Primitive), mergeProps(unref(forwarded), {
|
|
67
|
+
class: "ui-ChartRoot",
|
|
68
|
+
style: chartStyle.value
|
|
69
|
+
}), {
|
|
70
|
+
default: withCtx(() => [renderSlot(_ctx.$slots, "default", { mounted: mounted.value })]),
|
|
71
|
+
_: 3
|
|
72
|
+
}, 16, ["style"]);
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/charts/ChartTooltipContent.vue?vue&type=script&setup=true&lang.ts
|
|
78
|
+
var _hoisted_1$1 = { class: "ui-ChartTooltipContent" };
|
|
79
|
+
var _hoisted_2 = {
|
|
80
|
+
key: 0,
|
|
81
|
+
class: "ui-ChartTooltipLabel"
|
|
82
|
+
};
|
|
83
|
+
var _hoisted_3 = { class: "ui-ChartTooltipItems" };
|
|
84
|
+
var _hoisted_4 = ["innerHTML"];
|
|
85
|
+
var _hoisted_5 = { class: "ui-ChartTooltipSeries" };
|
|
86
|
+
var _hoisted_6 = { class: "ui-ChartTooltipSeriesLabel" };
|
|
87
|
+
var _hoisted_7 = { class: "ui-ChartTooltipValue" };
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/charts/ChartTooltipContent.vue
|
|
90
|
+
var ChartTooltipContent_default = /* @__PURE__ */ defineComponent({
|
|
91
|
+
__name: "ChartTooltipContent",
|
|
92
|
+
props: {
|
|
93
|
+
payload: { default: () => ({}) },
|
|
94
|
+
config: { default: () => ({}) },
|
|
95
|
+
x: {},
|
|
96
|
+
indicator: { default: "dot" },
|
|
97
|
+
hideLabel: { type: Boolean },
|
|
98
|
+
hideIndicator: { type: Boolean },
|
|
99
|
+
labelKey: {},
|
|
100
|
+
labelFormatter: {},
|
|
101
|
+
valueFormatter: {}
|
|
102
|
+
},
|
|
103
|
+
setup(__props) {
|
|
104
|
+
const props = __props;
|
|
105
|
+
const items = computed(() => Object.entries(props.payload).map(([key, value]) => ({
|
|
106
|
+
key,
|
|
107
|
+
value,
|
|
108
|
+
series: props.config[key]
|
|
109
|
+
})).filter((item) => Boolean(item.series) && item.series.role !== "x").map((item, index) => ({
|
|
110
|
+
...item,
|
|
111
|
+
index,
|
|
112
|
+
icon: buildSeriesIcon(item.series.icon)
|
|
113
|
+
})));
|
|
114
|
+
function buildSeriesIcon(name) {
|
|
115
|
+
const icon = name ? getIcon(name) : void 0;
|
|
116
|
+
return icon ? buildIcon(icon) : void 0;
|
|
117
|
+
}
|
|
118
|
+
const label = computed(() => {
|
|
119
|
+
if (props.hideLabel) return void 0;
|
|
120
|
+
const xKey = Object.entries(props.config).find(([_key, series]) => series.role === "x")?.[0];
|
|
121
|
+
const value = props.labelKey ? props.config[props.labelKey]?.label ?? props.payload[props.labelKey] ?? props.x : xKey ? props.payload[xKey] ?? props.x : props.x;
|
|
122
|
+
if (value === void 0 || value === null) return void 0;
|
|
123
|
+
const labelValue = typeof value === "string" || typeof value === "number" || value instanceof Date ? value : String(value);
|
|
124
|
+
return props.labelFormatter ? props.labelFormatter(labelValue) : String(labelValue);
|
|
125
|
+
});
|
|
126
|
+
function formatValue(value, key) {
|
|
127
|
+
if (props.valueFormatter) return props.valueFormatter(value, key);
|
|
128
|
+
if (typeof value === "number") return value.toLocaleString();
|
|
129
|
+
return String(value ?? "—");
|
|
130
|
+
}
|
|
131
|
+
return (_ctx, _cache) => {
|
|
132
|
+
return openBlock(), createElementBlock("div", _hoisted_1$1, [renderSlot(_ctx.$slots, "default", {
|
|
133
|
+
items: items.value,
|
|
134
|
+
label: label.value
|
|
135
|
+
}, () => [label.value ? (openBlock(), createElementBlock("div", _hoisted_2, toDisplayString(label.value), 1)) : createCommentVNode("", true), createElementVNode("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (item) => {
|
|
136
|
+
return openBlock(), createElementBlock("div", {
|
|
137
|
+
key: item.key,
|
|
138
|
+
class: "ui-ChartTooltipItem"
|
|
139
|
+
}, [
|
|
140
|
+
item.icon ? (openBlock(), createElementBlock("svg", mergeProps({
|
|
141
|
+
key: 0,
|
|
142
|
+
ref_for: true
|
|
143
|
+
}, item.icon.attributes, {
|
|
144
|
+
class: "ui-ChartTooltipIcon",
|
|
145
|
+
"aria-hidden": "true",
|
|
146
|
+
focusable: "false",
|
|
147
|
+
innerHTML: item.icon.body
|
|
148
|
+
}), null, 16, _hoisted_4)) : !props.hideIndicator && props.indicator !== "none" ? (openBlock(), createElementBlock("span", {
|
|
149
|
+
key: 1,
|
|
150
|
+
class: normalizeClass(["ui-ChartTooltipIndicator", `r-indicator-${props.indicator}`]),
|
|
151
|
+
style: normalizeStyle({ "--chart-tooltip-color": item.series.color ?? `var(--chart-${item.index + 1})` })
|
|
152
|
+
}, null, 6)) : createCommentVNode("", true),
|
|
153
|
+
createElementVNode("span", _hoisted_5, [createElementVNode("span", _hoisted_6, toDisplayString(item.series.label), 1)]),
|
|
154
|
+
createElementVNode("span", _hoisted_7, toDisplayString(formatValue(item.value, item.key)), 1)
|
|
155
|
+
]);
|
|
156
|
+
}), 128))])])]);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/charts/tooltip.ts
|
|
162
|
+
/** Creates a synchronous Unovis template callback from a Vue tooltip component. */
|
|
163
|
+
function createChartTooltipTemplate(config, component, props = {}) {
|
|
164
|
+
return (rawPayload, x) => {
|
|
165
|
+
if (typeof document === "undefined") return "";
|
|
166
|
+
const payload = unwrapPayload(rawPayload, config);
|
|
167
|
+
const container = document.createElement("div");
|
|
168
|
+
const vnode = h(component, {
|
|
169
|
+
...props,
|
|
170
|
+
payload,
|
|
171
|
+
config,
|
|
172
|
+
x
|
|
173
|
+
});
|
|
174
|
+
render(vnode, container);
|
|
175
|
+
const html = container.innerHTML;
|
|
176
|
+
render(null, container);
|
|
177
|
+
return html;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function unwrapPayload(payload, config) {
|
|
181
|
+
if (isRecord(payload) && isRecord(payload.data)) return unwrapPayload(payload.data, config);
|
|
182
|
+
if (!isRecord(payload)) return {};
|
|
183
|
+
const configured = Object.keys(config).filter((key) => key in payload);
|
|
184
|
+
if (configured.length) return Object.fromEntries(configured.map((key) => [key, payload[key]]));
|
|
185
|
+
return payload;
|
|
186
|
+
}
|
|
187
|
+
function isRecord(value) {
|
|
188
|
+
return typeof value === "object" && value !== null;
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region src/charts/ChartCrosshair.vue
|
|
192
|
+
var ChartCrosshair_default = /* @__PURE__ */ defineComponent({
|
|
193
|
+
__name: "ChartCrosshair",
|
|
194
|
+
props: {
|
|
195
|
+
contentComponent: { default: ChartTooltipContent_default },
|
|
196
|
+
contentProps: { default: () => ({}) }
|
|
197
|
+
},
|
|
198
|
+
setup(__props) {
|
|
199
|
+
const props = __props;
|
|
200
|
+
const context = injectChartContext();
|
|
201
|
+
const forwarded = useForwardPropsWithout(props, [
|
|
202
|
+
"contentComponent",
|
|
203
|
+
"contentProps",
|
|
204
|
+
"template"
|
|
205
|
+
]);
|
|
206
|
+
const icons = computed(() => context.series.value.flatMap((entry) => entry.series.icon ? [entry.series.icon] : []));
|
|
207
|
+
let cancelIconLoad;
|
|
208
|
+
watch(icons, (value) => {
|
|
209
|
+
cancelIconLoad?.();
|
|
210
|
+
cancelIconLoad = value.length ? loadIcons(value) : void 0;
|
|
211
|
+
}, { immediate: true });
|
|
212
|
+
onUnmounted(() => cancelIconLoad?.());
|
|
213
|
+
const color = computed(() => {
|
|
214
|
+
return context.series.value.map((d) => `var(--chart-${d.index + 1})`);
|
|
215
|
+
});
|
|
216
|
+
const template = computed(() => createChartTooltipTemplate(context.config.value, props.contentComponent, props.contentProps));
|
|
217
|
+
return (_ctx, _cache) => {
|
|
218
|
+
return openBlock(), createBlock(unref(VisCrosshair), normalizeProps(guardReactiveProps({
|
|
219
|
+
...unref(forwarded),
|
|
220
|
+
color: color.value,
|
|
221
|
+
template: template.value
|
|
222
|
+
})), null, 16);
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/charts/ChartTooltip.vue
|
|
228
|
+
var ChartTooltip_default = /* @__PURE__ */ defineComponent({
|
|
229
|
+
__name: "ChartTooltip",
|
|
230
|
+
props: {
|
|
231
|
+
targets: {},
|
|
232
|
+
contentComponent: { default: ChartTooltipContent_default },
|
|
233
|
+
contentProps: { default: () => ({}) }
|
|
234
|
+
},
|
|
235
|
+
setup(__props) {
|
|
236
|
+
const props = __props;
|
|
237
|
+
const context = injectChartContext();
|
|
238
|
+
const forwarded = useForwardPropsWithout(props, [
|
|
239
|
+
"targets",
|
|
240
|
+
"contentComponent",
|
|
241
|
+
"contentProps",
|
|
242
|
+
"triggers"
|
|
243
|
+
]);
|
|
244
|
+
const tooltipClass = computed(() => ["ui-ChartTooltip", props.className].filter(Boolean).join(" "));
|
|
245
|
+
const template = computed(() => createChartTooltipTemplate(context.config.value, props.contentComponent, props.contentProps));
|
|
246
|
+
const generatedTriggers = computed(() => {
|
|
247
|
+
const triggers = {};
|
|
248
|
+
for (const target of props.targets ?? []) {
|
|
249
|
+
const { primitive, payload } = typeof target === "function" ? { primitive: target } : target;
|
|
250
|
+
if (primitive === Donut) triggers[Donut.selectors.segment] = (arc, index) => {
|
|
251
|
+
const mapped = payload ? payload(arc, index) : donutPayload(arc, index);
|
|
252
|
+
return template.value(mapped);
|
|
253
|
+
};
|
|
254
|
+
if (primitive === GroupedBar) triggers[GroupedBar.selectors.bar] = (datum, index) => {
|
|
255
|
+
const mapped = payload ? payload(datum, index) : datum;
|
|
256
|
+
return template.value(mapped);
|
|
257
|
+
};
|
|
258
|
+
if (primitive === StackedBar) triggers[StackedBar.selectors.bar] = (datum, index) => {
|
|
259
|
+
const mapped = payload ? payload(datum, index) : unwrapStackedDatum(datum);
|
|
260
|
+
return template.value(mapped);
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return triggers;
|
|
264
|
+
});
|
|
265
|
+
const triggers = computed(() => ({
|
|
266
|
+
...generatedTriggers.value,
|
|
267
|
+
...props.triggers
|
|
268
|
+
}));
|
|
269
|
+
function donutPayload(value, callbackIndex) {
|
|
270
|
+
if (!isRecord(value)) return {};
|
|
271
|
+
const arcIndex = typeof value.index === "number" ? value.index : callbackIndex;
|
|
272
|
+
const entry = context.series.value[arcIndex];
|
|
273
|
+
if (!entry) return {};
|
|
274
|
+
return { [entry.key]: value.value };
|
|
275
|
+
}
|
|
276
|
+
function unwrapStackedDatum(value) {
|
|
277
|
+
if (!isRecord(value) || !isRecord(value.datum)) return value;
|
|
278
|
+
return {
|
|
279
|
+
...value,
|
|
280
|
+
...value.datum
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function isRecord(value) {
|
|
284
|
+
return typeof value === "object" && value !== null;
|
|
285
|
+
}
|
|
286
|
+
return (_ctx, _cache) => {
|
|
287
|
+
return openBlock(), createBlock(unref(VisTooltip), mergeProps({
|
|
288
|
+
...unref(forwarded),
|
|
289
|
+
triggers: triggers.value
|
|
290
|
+
}, { "class-name": tooltipClass.value }), null, 16, ["class-name"]);
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region src/charts/ChartAreaGradient.vue
|
|
296
|
+
var ChartAreaGradient_default = /* @__PURE__ */ defineComponent({
|
|
297
|
+
__name: "ChartAreaGradient",
|
|
298
|
+
setup(__props) {
|
|
299
|
+
const context = injectChartContext();
|
|
300
|
+
const instanceId = useId();
|
|
301
|
+
const gradients = computed(() => {
|
|
302
|
+
return context.series.value.map((d) => {
|
|
303
|
+
return {
|
|
304
|
+
id: `ui-chart-area-${instanceId}-${d.index + 1}`,
|
|
305
|
+
color: `var(--chart-${d.index + 1})`
|
|
306
|
+
};
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
const svgDefs = computed(() => gradients.value.map((item) => `
|
|
310
|
+
<linearGradient id="${item.id}" x1="0" y1="0" x2="0" y2="1">
|
|
311
|
+
<stop offset="5%" stop-color="${item.color}" stop-opacity="0.8" />
|
|
312
|
+
<stop offset="95%" stop-color="${item.color}" stop-opacity="0.1" />
|
|
313
|
+
</linearGradient>
|
|
314
|
+
`).join(""));
|
|
315
|
+
const areaColor = (_data, index) => {
|
|
316
|
+
const gradient = gradients.value[index];
|
|
317
|
+
return gradient ? `url(#${gradient.id})` : "none";
|
|
318
|
+
};
|
|
319
|
+
return (_ctx, _cache) => {
|
|
320
|
+
return renderSlot(_ctx.$slots, "default", {
|
|
321
|
+
color: areaColor,
|
|
322
|
+
svgDefs: svgDefs.value
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/charts/ChartLegend.vue?vue&type=script&setup=true&lang.ts
|
|
329
|
+
var _hoisted_1 = { class: "ui-ChartLegendLabel" };
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/charts/ChartLegend.vue
|
|
332
|
+
var ChartLegend_default = /* @__PURE__ */ defineComponent({
|
|
333
|
+
__name: "ChartLegend",
|
|
334
|
+
props: {
|
|
335
|
+
orientation: { default: "horizontal" },
|
|
336
|
+
align: { default: "start" },
|
|
337
|
+
ariaLabel: { default: "Chart legend" },
|
|
338
|
+
asChild: { type: Boolean },
|
|
339
|
+
as: { default: "div" }
|
|
340
|
+
},
|
|
341
|
+
setup(__props) {
|
|
342
|
+
const props = __props;
|
|
343
|
+
const forwarded = useForwardPropsWithout(props, [
|
|
344
|
+
"orientation",
|
|
345
|
+
"align",
|
|
346
|
+
"ariaLabel"
|
|
347
|
+
]);
|
|
348
|
+
const resetClass = buildPropsClass(props, ["orientation", "align"]);
|
|
349
|
+
const context = injectChartContext();
|
|
350
|
+
const entries = computed(() => context.series.value);
|
|
351
|
+
return (_ctx, _cache) => {
|
|
352
|
+
return openBlock(), createBlock(unref(Primitive), mergeProps(unref(forwarded), {
|
|
353
|
+
class: ["ui-ChartLegend", unref(resetClass)],
|
|
354
|
+
role: "list",
|
|
355
|
+
"aria-label": props.ariaLabel
|
|
356
|
+
}), {
|
|
357
|
+
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(entries.value, (entry) => {
|
|
358
|
+
return openBlock(), createElementBlock("div", {
|
|
359
|
+
key: entry.key,
|
|
360
|
+
class: "ui-ChartLegendItem",
|
|
361
|
+
role: "listitem"
|
|
362
|
+
}, [renderSlot(_ctx.$slots, "item", mergeProps({ ref_for: true }, entry), () => [
|
|
363
|
+
renderSlot(_ctx.$slots, "marker", mergeProps({ ref_for: true }, entry), () => [createElementVNode("span", {
|
|
364
|
+
class: "ui-ChartLegendMarker",
|
|
365
|
+
style: normalizeStyle({ backgroundColor: unref(context).colors.value[entry.index] })
|
|
366
|
+
}, null, 4)]),
|
|
367
|
+
entry.series.icon ? (openBlock(), createBlock(unref(Icon), {
|
|
368
|
+
key: 0,
|
|
369
|
+
icon: entry.series.icon,
|
|
370
|
+
class: "ui-ChartLegendIcon",
|
|
371
|
+
"aria-hidden": "true"
|
|
372
|
+
}, null, 8, ["icon"])) : createCommentVNode("", true),
|
|
373
|
+
createElementVNode("span", _hoisted_1, toDisplayString(entry.series.label), 1)
|
|
374
|
+
])]);
|
|
375
|
+
}), 128))]),
|
|
376
|
+
_: 3
|
|
377
|
+
}, 16, ["class", "aria-label"]);
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
//#endregion
|
|
382
|
+
export { ChartAreaGradient_default as ChartAreaGradient, ChartCrosshair_default as ChartCrosshair, ChartLegend_default as ChartLegend, ChartRoot_default as ChartRoot, ChartTooltip_default as ChartTooltip, ChartTooltipContent_default as ChartTooltipContent, createChartTooltipTemplate };
|