vue-chrts 0.1.0-beta.5 → 0.1.1-test.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ export declare function getOklchFromCssVariable(cssVariableName: any): {
2
+ l: number;
3
+ c: number;
4
+ h: number;
5
+ a: number;
6
+ } | null;
7
+ export declare function getColorValue(colorStr: any, oklch2web: any): any;
8
+ export declare function convertCategories(categories: any, oklch2web: any): {};
9
+ declare function oklch2web(l: any, c: any, h: any, a: any): string;
10
+ declare function extractHue(color: any): number;
11
+ export { extractHue, oklch2web };
package/dist/colors.js ADDED
@@ -0,0 +1,100 @@
1
+ function l(n) {
2
+ if (typeof window > "u") return null;
3
+ const e = getComputedStyle(document.documentElement).getPropertyValue(n).trim();
4
+ if (!e) return null;
5
+ const t = e.match(/oklch\(\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*\)/);
6
+ if (!t) return null;
7
+ const o = parseFloat(t[1]) * 100, s = parseFloat(t[2]), c = parseFloat(t[3]), u = parseFloat(t[4]);
8
+ return { l: o, c: s, h: c, a: u };
9
+ }
10
+ function f(n, r) {
11
+ const e = "#3b82f6";
12
+ if (n != null && n.includes("#")) return n;
13
+ const t = l(n);
14
+ return t ? r(t.l, t.c, t.h) : e;
15
+ }
16
+ function M(n, r) {
17
+ return Object.keys(n).reduce(
18
+ (e, t) => {
19
+ const o = n[t];
20
+ return e[t] = {
21
+ ...o,
22
+ color: f(o.color, r)
23
+ }, e;
24
+ },
25
+ {}
26
+ );
27
+ }
28
+ function h(n) {
29
+ const { l: r, c: e, h: t } = n;
30
+ return {
31
+ l: r,
32
+ a: e ? e * Math.cos(t / 180 * Math.PI) : 0,
33
+ b: e ? e * Math.sin(t / 180 * Math.PI) : 0
34
+ };
35
+ }
36
+ function b(n) {
37
+ const { l: r, a: e, b: t } = n, o = Math.pow(
38
+ r * 0.9999999984505198 + 0.39633779217376786 * e + 0.2158037580607588 * t,
39
+ 3
40
+ ), s = Math.pow(
41
+ r * 1.0000000088817609 - 0.10556134232365635 * e - 0.06385417477170591 * t,
42
+ 3
43
+ ), c = Math.pow(
44
+ r * 1.0000000546724108 - 0.08948418209496575 * e - 1.2914855378640917 * t,
45
+ 3
46
+ );
47
+ return {
48
+ r: 4.076741661347994 * o - 3.307711590408193 * s + 0.230969928729428 * c,
49
+ g: -1.2684380040921763 * o + 2.6097574006633715 * s - 0.3413193963102197 * c,
50
+ b: -0.004196086541837188 * o - 0.7034186144594493 * s + 1.7076147009309444 * c
51
+ };
52
+ }
53
+ function g(n) {
54
+ const r = (e) => {
55
+ const t = Math.abs(e);
56
+ return t > 31308e-7 ? (Math.sign(e) || 1) * (1.055 * Math.pow(t, 0.4166666666666667) - 0.055) : e * 12.92;
57
+ };
58
+ return { r: r(n.r) * 255, g: r(n.g) * 255, b: r(n.b) * 255 };
59
+ }
60
+ function a(n) {
61
+ return g(b(h(n)));
62
+ }
63
+ function p(n) {
64
+ let r = a(n);
65
+ const e = (t) => [t.r, t.g, t.b].some((o) => o < 0 || o > 255);
66
+ if (e(r) && !e(a({ ...n, c: 0 }))) {
67
+ let t = 0, o = n.c, s = 0;
68
+ const c = 0.4 / Math.pow(2, 13);
69
+ for (; o - t > c; ) {
70
+ const u = t + (o - t) * 0.5, i = a({ ...n, c: u });
71
+ e(i) ? o = u : (s = u, t = u);
72
+ }
73
+ r = a({ ...n, c: s });
74
+ }
75
+ return r;
76
+ }
77
+ function d(n, r, e) {
78
+ return `#${((1 << 24) + (n << 16) + (r << 8) + e).toString(16).slice(1)}`;
79
+ }
80
+ function m(n) {
81
+ const [r, e, t] = [n.r, n.g, n.b].map((o) => {
82
+ const s = Math.round(o);
83
+ return Math.min(Math.max(s, 0), 255);
84
+ });
85
+ return {
86
+ r,
87
+ g: e,
88
+ b: t
89
+ };
90
+ }
91
+ function w(n, r, e, t) {
92
+ const o = p({ l: n / 100, c: r, h: e }), { r: s, g: c, b: u } = m(o);
93
+ return t ? `rgba(${s},${c},${u},${t})` : d(s, c, u);
94
+ }
95
+ export {
96
+ M as convertCategories,
97
+ f as getColorValue,
98
+ l as getOklchFromCssVariable,
99
+ w as oklch2web
100
+ };
@@ -1,9 +1,10 @@
1
- import { defineComponent as E, ref as T, computed as g, createApp as F, onUnmounted as $, createElementBlock as p, openBlock as r, normalizeClass as L, createVNode as s, createCommentVNode as v, unref as o, withCtx as N, createBlock as h, Fragment as b, renderList as G, mergeProps as P } from "vue";
2
- import { Position as x, CurveType as C } from "@unovis/ts";
3
- import { VisXYContainer as U, VisTooltip as j, VisArea as I, VisLine as M, VisAxis as B, VisCrosshair as w, VisBulletLegend as z } from "@unovis/vue";
4
- import R from "../Tooltip.js";
5
- import { LegendPosition as X } from "../../types.js";
6
- const m = 24, A = 4, Y = 0.5, H = "#3b82f6", Z = /* @__PURE__ */ E({
1
+ import { defineComponent as G, ref as T, computed as L, createApp as M, onUnmounted as P, createElementBlock as m, openBlock as s, normalizeClass as h, createVNode as c, createCommentVNode as v, unref as o, withCtx as $, createBlock as C, Fragment as b, renderList as U, mergeProps as j } from "vue";
2
+ import { getColorValue as I, getOklchFromCssVariable as w, oklch2web as g, convertCategories as z } from "../../colors.js";
3
+ import { Position as x, CurveType as V } from "@unovis/ts";
4
+ import { VisXYContainer as H, VisTooltip as R, VisArea as X, VisLine as Y, VisAxis as B, VisCrosshair as S, VisBulletLegend as q } from "@unovis/vue";
5
+ import J from "../Tooltip.js";
6
+ import { LegendPosition as Q } from "../../types.js";
7
+ const p = 24, O = 4, W = 0.5, A = "#3b82f6", ne = /* @__PURE__ */ G({
7
8
  __name: "AreaChart",
8
9
  props: {
9
10
  data: {},
@@ -14,10 +15,10 @@ const m = 24, A = 4, Y = 0.5, H = "#3b82f6", Z = /* @__PURE__ */ E({
14
15
  xFormatter: {},
15
16
  yFormatter: {},
16
17
  curveType: {},
17
- xNumTicks: { default: (i) => i.data.length > m ? m / A : i.data.length - 1 },
18
+ xNumTicks: { default: (i) => i.data.length > p ? p / O : i.data.length - 1 },
18
19
  xExplicitTicks: {},
19
- minMaxTicksOnly: {},
20
- yNumTicks: { default: (i) => i.data.length > m ? m / A : i.data.length - 1 },
20
+ minMaxTicksOnly: { type: Boolean },
21
+ yNumTicks: { default: (i) => i.data.length > p ? p / O : i.data.length - 1 },
21
22
  hideLegend: { type: Boolean },
22
23
  hideTooltip: { type: Boolean },
23
24
  xGridLine: { type: Boolean },
@@ -28,77 +29,89 @@ const m = 24, A = 4, Y = 0.5, H = "#3b82f6", Z = /* @__PURE__ */ E({
28
29
  legendPosition: {}
29
30
  },
30
31
  setup(i) {
31
- const l = i, d = Object.values(l.categories).map((e) => e.color), n = T(null), a = T(null), D = g(() => (e) => {
32
- if (typeof window > "u" || typeof document > "u")
33
- return "";
34
- try {
35
- if (a.value || (a.value = document.createElement("div")), !n.value)
36
- n.value = F(R, {
37
- data: e,
38
- categories: l.categories
39
- }), n.value.mount(a.value);
40
- else {
41
- const t = n.value._instance;
42
- t != null && t.proxy && (t.proxy.$props.data = e, t.proxy.$props.categories = l.categories);
43
- }
44
- return a.value.innerHTML;
45
- } catch (t) {
46
- return console.error("Error generating tooltip:", t), "";
47
- }
32
+ const a = i, d = Object.values(a.categories).map(
33
+ (e) => I(e.color, g)
34
+ ), D = Object.values(a.categories).map((e) => {
35
+ var n;
36
+ if ((n = e.color) != null && n.includes("#")) return e;
37
+ const t = w(e.color);
38
+ return t ? {
39
+ ...e,
40
+ color: g(
41
+ t.l,
42
+ t.c,
43
+ t.h,
44
+ t.a
45
+ )
46
+ } : { ...e, color: A };
48
47
  });
49
- $(() => {
50
- n.value && (n.value.unmount(), n.value = null), a.value && (a.value = null);
51
- });
52
- function O(e) {
48
+ function F(e) {
53
49
  var t;
54
50
  return {
55
- y: (c) => Number(c[e]),
56
- color: ((t = l.categories[e]) == null ? void 0 : t.color) ?? H
51
+ y: (n) => Number(n[e]),
52
+ color: ((t = a.categories[e]) == null ? void 0 : t.color) ?? A
57
53
  };
58
54
  }
59
- const V = g(
60
- () => d.map(
61
- (e, t) => `
55
+ const r = T(null), l = T(null), E = L(() => (e) => {
56
+ if (typeof window > "u") return "";
57
+ l.value || (l.value = document.createElement("div"));
58
+ const t = z(a.categories, g);
59
+ try {
60
+ if (!r.value)
61
+ return r.value = M(J, {
62
+ data: e,
63
+ categories: t
64
+ }), r.value.mount(l.value), l.value.innerHTML;
65
+ const n = r.value._instance;
66
+ return n != null && n.proxy, l.value.innerHTML;
67
+ } catch (n) {
68
+ return console.error("Error generating tooltip:", n), "";
69
+ }
70
+ });
71
+ P(() => {
72
+ r.value && (r.value.unmount(), r.value = null), l.value = null;
73
+ });
74
+ const N = d.map(
75
+ (e, t) => `
62
76
  <linearGradient id="gradient${t}-${e}" gradientTransform="rotate(90)">
63
77
  <stop offset="0%" stop-color="${e}" stop-opacity="1" />
64
78
  <stop offset="100%" stop-color="${e}" stop-opacity="0" />
65
79
  </linearGradient>
66
80
  `
67
- ).join("")
68
- ), k = g(
69
- () => l.legendPosition === X.Top
81
+ ).join(""), k = L(
82
+ () => a.legendPosition === Q.Top
70
83
  );
71
- return (e, t) => (r(), p("div", {
72
- class: L(["flex flex-col space-y-4", { "flex-col-reverse": k.value }])
84
+ return (e, t) => (s(), m("div", {
85
+ class: h(["flex flex-col space-y-4", { "flex-col-reverse": k.value }])
73
86
  }, [
74
- s(o(U), {
87
+ c(o(H), {
75
88
  data: e.data,
76
89
  height: e.height,
77
- "svg-defs": V.value
90
+ "svg-defs": o(N)
78
91
  }, {
79
- default: N(() => [
80
- e.hideTooltip ? v("", !0) : (r(), h(o(j), {
92
+ default: $(() => [
93
+ e.hideTooltip ? v("", !0) : (s(), C(o(R), {
81
94
  key: 0,
82
95
  "horizontal-placement": o(x).Right,
83
96
  "vertical-placement": o(x).Top
84
97
  }, null, 8, ["horizontal-placement", "vertical-placement"])),
85
- (r(!0), p(b, null, G(Object.keys(l.categories), (c, u) => (r(), p(b, { key: u }, [
86
- s(o(I), P({
87
- x: (y, f) => f,
98
+ (s(!0), m(b, null, U(Object.keys(a.categories), (n, u) => (s(), m(b, { key: u }, [
99
+ c(o(X), j({
100
+ x: (f, y) => y,
88
101
  ref_for: !0
89
- }, O(c), {
102
+ }, F(n), {
90
103
  color: `url(#gradient${u}-${o(d)[u]})`,
91
- opacity: Y,
92
- "curve-type": e.curveType ?? o(C).MonotoneX
104
+ opacity: W,
105
+ "curve-type": e.curveType ?? o(V).MonotoneX
93
106
  }), null, 16, ["x", "color", "curve-type"]),
94
- s(o(M), {
95
- x: (y, f) => f,
96
- y: (y) => y[c],
107
+ c(o(Y), {
108
+ x: (f, y) => y,
109
+ y: (f) => f[n],
97
110
  color: o(d)[u],
98
- "curve-type": e.curveType ?? o(C).MonotoneX
111
+ "curve-type": e.curveType ?? o(V).MonotoneX
99
112
  }, null, 8, ["x", "y", "color", "curve-type"])
100
113
  ], 64))), 128)),
101
- s(o(B), {
114
+ c(o(B), {
102
115
  type: "x",
103
116
  "tick-format": e.xFormatter,
104
117
  label: e.xLabel,
@@ -110,7 +123,7 @@ const m = 24, A = 4, Y = 0.5, H = "#3b82f6", Z = /* @__PURE__ */ E({
110
123
  "tick-values": e.xExplicitTicks,
111
124
  "min-max-ticks-only": e.minMaxTicksOnly
112
125
  }, null, 8, ["tick-format", "label", "domain-line", "grid-line", "num-ticks", "tick-line", "tick-values", "min-max-ticks-only"]),
113
- s(o(B), {
126
+ c(o(B), {
114
127
  type: "y",
115
128
  "num-ticks": e.yNumTicks,
116
129
  "tick-format": e.yFormatter,
@@ -119,25 +132,23 @@ const m = 24, A = 4, Y = 0.5, H = "#3b82f6", Z = /* @__PURE__ */ E({
119
132
  "domain-line": e.yDomainLine,
120
133
  "tick-line": !!e.yGridLine
121
134
  }, null, 8, ["num-ticks", "tick-format", "label", "grid-line", "domain-line", "tick-line"]),
122
- e.hideTooltip ? v("", !0) : (r(), h(o(w), {
135
+ e.hideTooltip ? v("", !0) : (s(), C(o(S), {
123
136
  key: 1,
124
137
  color: "#666",
125
- template: D.value
138
+ template: E.value
126
139
  }, null, 8, ["template"]))
127
140
  ]),
128
141
  _: 1
129
142
  }, 8, ["data", "height", "svg-defs"]),
130
- e.hideLegend ? v("", !0) : (r(), p("div", {
143
+ e.hideLegend ? v("", !0) : (s(), m("div", {
131
144
  key: 0,
132
- class: L(["flex items-center justify-end", { "pb-4": k.value }])
145
+ class: h(["flex items-center justify-end", { "pb-4": k.value }])
133
146
  }, [
134
- s(o(z), {
135
- items: Object.values(e.categories)
136
- }, null, 8, ["items"])
147
+ c(o(q), { items: o(D) }, null, 8, ["items"])
137
148
  ], 2))
138
149
  ], 2));
139
150
  }
140
151
  });
141
152
  export {
142
- Z as default
153
+ ne as default
143
154
  };
@@ -54,7 +54,7 @@ export interface AreaChartProps<T> {
54
54
  /**
55
55
  * Force only first and last ticks on the x-axis.
56
56
  */
57
- minMaxTicksOnly?: number;
57
+ minMaxTicksOnly?: boolean;
58
58
  /**
59
59
  * The desired number of ticks on the y-axis.
60
60
  */
@@ -1,9 +1,9 @@
1
- import { defineComponent as b, computed as u, createApp as h, createElementBlock as y, openBlock as d, normalizeClass as k, createVNode as t, createCommentVNode as B, unref as i, withCtx as T, createBlock as f } from "vue";
2
- import { Orientation as s, StackedBar as v, GroupedBar as V } from "@unovis/ts";
3
- import { VisXYContainer as P, VisTooltip as x, VisGroupedBar as C, VisStackedBar as G, VisAxis as L, VisBulletLegend as N } from "@unovis/vue";
4
- import A from "../Tooltip.js";
5
- import { LegendPosition as O } from "../../types.js";
6
- const M = /* @__PURE__ */ b({
1
+ import { defineComponent as h, computed as u, createApp as b, createElementBlock as y, openBlock as d, normalizeClass as k, createVNode as r, createCommentVNode as B, unref as i, withCtx as T, createBlock as f } from "vue";
2
+ import { Orientation as s, StackedBar as v, GroupedBar as x } from "@unovis/ts";
3
+ import { VisXYContainer as V, VisTooltip as P, VisGroupedBar as A, VisStackedBar as C, VisAxis as L, VisBulletLegend as G } from "@unovis/vue";
4
+ import N from "../Tooltip.js";
5
+ import { LegendPosition as w } from "../../types.js";
6
+ const M = /* @__PURE__ */ h({
7
7
  __name: "BarChart",
8
8
  props: {
9
9
  data: {},
@@ -15,7 +15,7 @@ const M = /* @__PURE__ */ b({
15
15
  xFormatter: {},
16
16
  yFormatter: {},
17
17
  yNumTicks: { default: (a) => a.data.length > 24 ? 24 / 4 : a.data.length - 1 },
18
- minMaxTicksOnly: {},
18
+ minMaxTicksOnly: { type: Boolean },
19
19
  xNumTicks: { default: (a) => a.data.length > 24 ? 24 / 4 : a.data.length - 1 },
20
20
  xExplicitTicks: {},
21
21
  yAxis: {},
@@ -33,19 +33,22 @@ const M = /* @__PURE__ */ b({
33
33
  yGridLine: { type: Boolean, default: !0 }
34
34
  },
35
35
  setup(a) {
36
- const r = a, m = u(() => r.yAxis.map((e) => (n) => n[e])), c = (e, n) => Object.values(r.categories)[n].color, p = u(
37
- () => r.legendPosition === O.Top
36
+ const o = a;
37
+ if (!o.yAxis || o.yAxis.length === 0)
38
+ throw new Error("yAxis is required");
39
+ const c = u(() => o.yAxis.map((e) => (n) => n[e])), m = (e, n) => Object.values(o.categories)[n].color, p = u(
40
+ () => o.legendPosition === w.Top
38
41
  ), g = u(() => (e) => {
39
42
  if (typeof window > "u" || typeof document > "u")
40
43
  return "";
41
44
  try {
42
- const n = h(A, {
45
+ const n = b(N, {
43
46
  data: e,
44
- categories: r.categories
47
+ categories: o.categories
45
48
  }), l = document.createElement("div");
46
49
  n.mount(l);
47
- const o = l.innerHTML;
48
- return n.unmount(), o;
50
+ const t = l.innerHTML;
51
+ return n.unmount(), t;
49
52
  } catch {
50
53
  return "";
51
54
  }
@@ -53,36 +56,36 @@ const M = /* @__PURE__ */ b({
53
56
  return (e, n) => (d(), y("div", {
54
57
  class: k(["flex flex-col space-y-4", { "flex-col-reverse": p.value }])
55
58
  }, [
56
- t(i(P), { height: e.height }, {
59
+ r(i(V), { height: e.height }, {
57
60
  default: T(() => [
58
- t(i(x), {
61
+ r(i(P), {
59
62
  triggers: {
60
- [i(V).selectors.bar]: g.value,
63
+ [i(x).selectors.bar]: g.value,
61
64
  [i(v).selectors.bar]: g.value
62
65
  }
63
66
  }, null, 8, ["triggers"]),
64
- e.stacked ? (d(), f(i(G), {
67
+ e.stacked ? (d(), f(i(C), {
65
68
  key: 1,
66
69
  data: e.data,
67
- x: (l, o) => o,
68
- y: m.value,
69
- color: c,
70
+ x: (l, t) => t,
71
+ y: c.value,
72
+ color: m,
70
73
  "rounded-corners": e.radius ?? 0,
71
74
  "group-padding": e.groupPadding ?? 0,
72
75
  "bar-padding": e.barPadding ?? 0.2,
73
76
  orientation: e.orientation ?? i(s).Vertical
74
- }, null, 8, ["data", "x", "y", "rounded-corners", "group-padding", "bar-padding", "orientation"])) : (d(), f(i(C), {
77
+ }, null, 8, ["data", "x", "y", "rounded-corners", "group-padding", "bar-padding", "orientation"])) : (d(), f(i(A), {
75
78
  key: 0,
76
79
  data: e.data,
77
- x: (l, o) => o,
78
- y: m.value,
79
- color: c,
80
+ x: (l, t) => t,
81
+ y: c.value,
82
+ color: m,
80
83
  "rounded-corners": e.radius ?? 0,
81
84
  "group-padding": e.groupPadding ?? 0,
82
85
  "bar-padding": e.barPadding ?? 0.2,
83
86
  orientation: e.orientation ?? i(s).Vertical
84
87
  }, null, 8, ["data", "x", "y", "rounded-corners", "group-padding", "bar-padding", "orientation"])),
85
- t(i(L), {
88
+ r(i(L), {
86
89
  type: "x",
87
90
  "tick-format": e.xFormatter,
88
91
  label: e.xLabel,
@@ -93,15 +96,15 @@ const M = /* @__PURE__ */ b({
93
96
  "tick-values": e.xExplicitTicks,
94
97
  "min-max-ticks-only": e.minMaxTicksOnly
95
98
  }, null, 8, ["tick-format", "label", "grid-line", "domain-line", "tick-line", "num-ticks", "tick-values", "min-max-ticks-only"]),
96
- t(i(L), {
99
+ r(i(L), {
97
100
  type: "y",
98
101
  label: e.yLabel,
99
102
  "grid-line": e.orientation !== i(s).Horizontal && e.yGridLine,
100
103
  "domain-line": !!e.yDomainLine,
101
- "tick-format": e.yFormatter,
104
+ "tick-format": () => "",
102
105
  "num-ticks": e.yNumTicks,
103
106
  "tick-line": e.yTickLine
104
- }, null, 8, ["label", "grid-line", "domain-line", "tick-format", "num-ticks", "tick-line"])
107
+ }, null, 8, ["label", "grid-line", "domain-line", "num-ticks", "tick-line"])
105
108
  ]),
106
109
  _: 1
107
110
  }, 8, ["height"]),
@@ -109,7 +112,7 @@ const M = /* @__PURE__ */ b({
109
112
  key: 0,
110
113
  class: k(["flex items center justify-end", { "pb-4": p.value }])
111
114
  }, [
112
- t(i(N), {
115
+ r(i(G), {
113
116
  items: Object.values(e.categories)
114
117
  }, null, 8, ["items"])
115
118
  ], 2))
@@ -48,7 +48,7 @@ export interface BarChartProps<T> {
48
48
  /**
49
49
  * Force only first and last ticks on the x-axis.
50
50
  */
51
- minMaxTicksOnly?: number;
51
+ minMaxTicksOnly?: boolean;
52
52
  /**
53
53
  * The desired number of ticks on the x-axis.
54
54
  */
@@ -16,7 +16,7 @@ const X = /* @__PURE__ */ v({
16
16
  curveType: {},
17
17
  xNumTicks: { default: (t) => t.data.length > 24 ? 24 / 4 : t.data.length - 1 },
18
18
  xExplicitTicks: {},
19
- minMaxTicksOnly: {},
19
+ minMaxTicksOnly: { type: Boolean },
20
20
  yNumTicks: { default: (t) => t.data.length > 24 ? 24 / 4 : t.data.length - 1 },
21
21
  hideTooltip: { type: Boolean },
22
22
  hideLegend: { type: Boolean },
@@ -53,7 +53,7 @@ export interface LineChartProps<T> {
53
53
  /**
54
54
  * Force only first and last ticks on the x-axis.
55
55
  */
56
- minMaxTicksOnly?: number;
56
+ minMaxTicksOnly?: boolean;
57
57
  /**
58
58
  * The desired number of ticks on the y-axis.
59
59
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-chrts",
3
- "version": "0.1.0-beta.5",
3
+ "version": "0.1.1-test.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -24,6 +24,7 @@
24
24
  "devDependencies": {
25
25
  "@tailwindcss/vite": "^4.0.15",
26
26
  "@tanstack/vue-table": "^8.21.2",
27
+ "@types/culori": "^2.1.1",
27
28
  "@types/node": "^22.13.11",
28
29
  "@unovis/ts": "^1.5.1",
29
30
  "@unovis/vue": "^1.5.1",