@omnitend/dashboard-for-laravel 0.28.0 → 0.30.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/dist/charts.d.ts +19 -0
- package/dist/charts.js +225 -0
- package/dist/charts.js.map +1 -0
- package/dist/charts.umd.cjs +2 -0
- package/dist/charts.umd.cjs.map +1 -0
- package/dist/components/base/DAlert.vue.d.ts +6 -1
- package/dist/components/base/DAutocomplete.vue.d.ts +21 -1
- package/dist/components/base/DFormCheckboxGroup.vue.d.ts +12 -0
- package/dist/components/extended/DXDashboardSidebar.vue.d.ts +2 -2
- package/dist/components/extended/DXField.vue.d.ts +4 -4
- package/dist/components/extended/DXForm.vue.d.ts +15 -4
- package/dist/components/extended/DXTable.vue.d.ts +39 -1
- package/dist/components/extended/DXTablePagination.vue.d.ts +2 -0
- package/dist/dashboard-for-laravel.js +8826 -8937
- package/dist/dashboard-for-laravel.js.map +1 -1
- package/dist/dashboard-for-laravel.umd.cjs +7 -7
- package/dist/dashboard-for-laravel.umd.cjs.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/public/api-reference.json +84 -9
- package/docs/public/docs-map.md +1 -1
- package/docs/public/llms.txt +3 -2
- package/package.json +11 -5
- package/resources/css/theme.scss +21 -7
- package/resources/js/charts.ts +19 -0
- package/resources/js/components/base/DAlert.vue +19 -1
- package/resources/js/components/base/DAutocomplete.vue +96 -4
- package/resources/js/components/base/DFormCheckboxGroup.vue +22 -0
- package/resources/js/components/charts/DXBarChart.vue +0 -9
- package/resources/js/components/charts/DXDoughnutChart.vue +0 -9
- package/resources/js/components/charts/DXLineChart.vue +0 -9
- package/resources/js/components/extended/DXField.vue +12 -0
- package/resources/js/components/extended/DXForm.vue +25 -5
- package/resources/js/components/extended/DXTable.vue +139 -19
- package/resources/js/components/extended/DXTableEditorModal.vue +4 -0
- package/resources/js/components/extended/DXTablePagination.vue +5 -2
- package/resources/js/composables/useForm.ts +30 -3
- package/resources/js/index.ts +4 -3
- package/resources/js/types/index.ts +1 -0
package/dist/charts.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chart entry point — `@omnitend/dashboard-for-laravel/charts` (#142).
|
|
3
|
+
*
|
|
4
|
+
* The chart components are the ONLY ones that need `chart.js` / `vue-chartjs`,
|
|
5
|
+
* so they live behind this separate subpath entry. The main entry
|
|
6
|
+
* (`@omnitend/dashboard-for-laravel`) never references the chart libraries, so
|
|
7
|
+
* they are genuinely OPTIONAL peers: a consumer that renders no charts installs
|
|
8
|
+
* neither and their build no longer fails resolving them.
|
|
9
|
+
*
|
|
10
|
+
* import { DXBarChart } from '@omnitend/dashboard-for-laravel/charts';
|
|
11
|
+
*
|
|
12
|
+
* Chart containers are styled by `.dx-chart` in the main stylesheet
|
|
13
|
+
* (`@omnitend/dashboard-for-laravel/style.css`), which chart consumers already
|
|
14
|
+
* import for the theme and the `--dx-chart-*` palette variables — so this entry
|
|
15
|
+
* ships no CSS of its own.
|
|
16
|
+
*/
|
|
17
|
+
export { default as DXBarChart } from "./components/charts/DXBarChart.vue";
|
|
18
|
+
export { default as DXLineChart } from "./components/charts/DXLineChart.vue";
|
|
19
|
+
export { default as DXDoughnutChart } from "./components/charts/DXDoughnutChart.vue";
|
package/dist/charts.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { defineComponent as m, computed as i, openBlock as f, createElementBlock as b, createVNode as h, unref as g } from "vue";
|
|
2
|
+
import { Bar as V, Line as O, Doughnut as P } from "vue-chartjs";
|
|
3
|
+
import { Chart as R, registerables as X } from "chart.js";
|
|
4
|
+
const D = (o) => !!o && typeof o == "object" && !Array.isArray(o);
|
|
5
|
+
function p(o, e) {
|
|
6
|
+
const t = { ...o };
|
|
7
|
+
for (const [a, n] of Object.entries(e))
|
|
8
|
+
D(n) && D(t[a]) ? t[a] = p(t[a], n) : t[a] = n;
|
|
9
|
+
return t;
|
|
10
|
+
}
|
|
11
|
+
let L = !1;
|
|
12
|
+
function y() {
|
|
13
|
+
L || (R.register(...X), L = !0);
|
|
14
|
+
}
|
|
15
|
+
const A = [
|
|
16
|
+
["--dx-chart-1", "#2563eb"],
|
|
17
|
+
// blue
|
|
18
|
+
["--dx-chart-2", "#65a30d"],
|
|
19
|
+
// lime
|
|
20
|
+
["--dx-chart-3", "#7c3aed"],
|
|
21
|
+
// violet
|
|
22
|
+
["--dx-chart-4", "#0d9488"],
|
|
23
|
+
// teal
|
|
24
|
+
["--dx-chart-5", "#ea580c"],
|
|
25
|
+
// orange
|
|
26
|
+
["--dx-chart-6", "#0891b2"],
|
|
27
|
+
// cyan
|
|
28
|
+
["--dx-chart-7", "#d97706"],
|
|
29
|
+
// amber
|
|
30
|
+
["--dx-chart-8", "#db2777"]
|
|
31
|
+
// pink
|
|
32
|
+
];
|
|
33
|
+
function E() {
|
|
34
|
+
if (typeof document > "u" || typeof getComputedStyle > "u")
|
|
35
|
+
return A.map(([, e]) => e);
|
|
36
|
+
const o = getComputedStyle(document.documentElement);
|
|
37
|
+
return A.map(([e, t]) => o.getPropertyValue(e).trim() || t);
|
|
38
|
+
}
|
|
39
|
+
function F(o, e) {
|
|
40
|
+
return typeof document > "u" || typeof getComputedStyle > "u" ? e : getComputedStyle(document.documentElement).getPropertyValue(o).trim() || e;
|
|
41
|
+
}
|
|
42
|
+
function B(o, e) {
|
|
43
|
+
const t = o.replace(/^#/, "");
|
|
44
|
+
if (/^[0-9a-f]{6}$/i.test(t)) {
|
|
45
|
+
const n = parseInt(t.slice(0, 2), 16), s = parseInt(t.slice(2, 4), 16), l = parseInt(t.slice(4, 6), 16);
|
|
46
|
+
return `rgba(${n}, ${s}, ${l}, ${e})`;
|
|
47
|
+
}
|
|
48
|
+
const a = o.match(/^rgba?\(([^)]+)\)$/);
|
|
49
|
+
if (a) {
|
|
50
|
+
const [n, s, l] = a[1].split(",").map((r) => r.trim());
|
|
51
|
+
return `rgba(${n}, ${s}, ${l}, ${e})`;
|
|
52
|
+
}
|
|
53
|
+
return o;
|
|
54
|
+
}
|
|
55
|
+
function k(o, e, t, a) {
|
|
56
|
+
const n = new Intl.NumberFormat(a, {
|
|
57
|
+
maximumFractionDigits: 2
|
|
58
|
+
}).format(o);
|
|
59
|
+
return e === "currency" ? `${t}${n}` : e === "percent" ? `${n}%` : n;
|
|
60
|
+
}
|
|
61
|
+
function v(o) {
|
|
62
|
+
const {
|
|
63
|
+
valueFormat: e,
|
|
64
|
+
currencySymbol: t = "£",
|
|
65
|
+
locale: a,
|
|
66
|
+
showLegend: n = !1,
|
|
67
|
+
hasValueAxis: s = !0
|
|
68
|
+
} = o, l = B(F("--bs-border-color", "#dee2e6"), 0.6), r = F("--bs-secondary-color", "#6c757d"), u = {
|
|
69
|
+
responsive: !0,
|
|
70
|
+
maintainAspectRatio: !1,
|
|
71
|
+
plugins: {
|
|
72
|
+
legend: { display: n, labels: { color: r } },
|
|
73
|
+
tooltip: {
|
|
74
|
+
callbacks: {
|
|
75
|
+
label: (c) => {
|
|
76
|
+
var S, w;
|
|
77
|
+
const d = ((S = c.parsed) == null ? void 0 : S.y) ?? c.parsed ?? c.raw, C = typeof d == "number" ? d : Number(d), x = Number.isFinite(C) ? k(C, e, t, a) : String(d), $ = ((w = c.dataset) == null ? void 0 : w.label) ?? c.label ?? "";
|
|
78
|
+
return $ ? `${$}: ${x}` : x;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
return s && (u.scales = {
|
|
85
|
+
x: {
|
|
86
|
+
grid: { display: !1 },
|
|
87
|
+
border: { color: l },
|
|
88
|
+
ticks: { color: r }
|
|
89
|
+
},
|
|
90
|
+
y: {
|
|
91
|
+
beginAtZero: !0,
|
|
92
|
+
grid: { color: l, drawBorder: !1 },
|
|
93
|
+
border: { display: !1 },
|
|
94
|
+
ticks: {
|
|
95
|
+
color: r,
|
|
96
|
+
callback: (c) => k(Number(c), e, t, a)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}), u;
|
|
100
|
+
}
|
|
101
|
+
function _(o, e, t) {
|
|
102
|
+
const a = E(), n = o.length === 1;
|
|
103
|
+
return o.map((s, l) => {
|
|
104
|
+
const r = { ...s }, u = a[l % a.length];
|
|
105
|
+
return e === "doughnut" ? (r.backgroundColor === void 0 && (r.backgroundColor = Array.from(
|
|
106
|
+
{ length: t },
|
|
107
|
+
(c, d) => a[d % a.length]
|
|
108
|
+
)), r) : e === "line" ? (r.borderColor === void 0 && (r.borderColor = u), r.backgroundColor === void 0 && (r.backgroundColor = B(u, 0.15)), r.tension === void 0 && (r.tension = 0.3), r.fill === void 0 && (r.fill = !0), r.pointRadius === void 0 && (r.pointRadius = 2), r) : (r.backgroundColor === void 0 && (r.backgroundColor = n && t > 1 ? Array.from({ length: t }, () => u) : u), r.borderRadius === void 0 && (r.borderRadius = 4), r);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const N = { class: "dx-chart" }, q = /* @__PURE__ */ m({
|
|
112
|
+
__name: "DXBarChart",
|
|
113
|
+
props: {
|
|
114
|
+
labels: {},
|
|
115
|
+
datasets: {},
|
|
116
|
+
options: {},
|
|
117
|
+
valueFormat: {},
|
|
118
|
+
currencySymbol: { default: "£" },
|
|
119
|
+
locale: {},
|
|
120
|
+
showLegend: { type: Boolean, default: void 0 }
|
|
121
|
+
},
|
|
122
|
+
setup(o) {
|
|
123
|
+
y();
|
|
124
|
+
const e = o, t = i(() => ({
|
|
125
|
+
labels: e.labels,
|
|
126
|
+
datasets: _(e.datasets, "bar", e.labels.length)
|
|
127
|
+
})), a = i(
|
|
128
|
+
() => p(
|
|
129
|
+
v({
|
|
130
|
+
valueFormat: e.valueFormat,
|
|
131
|
+
currencySymbol: e.currencySymbol,
|
|
132
|
+
locale: e.locale,
|
|
133
|
+
showLegend: e.showLegend ?? e.datasets.length > 1,
|
|
134
|
+
hasValueAxis: !0
|
|
135
|
+
}),
|
|
136
|
+
e.options ?? {}
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
return (n, s) => (f(), b("div", N, [
|
|
140
|
+
h(g(V), {
|
|
141
|
+
data: t.value,
|
|
142
|
+
options: a.value
|
|
143
|
+
}, null, 8, ["data", "options"])
|
|
144
|
+
]));
|
|
145
|
+
}
|
|
146
|
+
}), I = { class: "dx-chart" }, z = /* @__PURE__ */ m({
|
|
147
|
+
__name: "DXLineChart",
|
|
148
|
+
props: {
|
|
149
|
+
labels: {},
|
|
150
|
+
datasets: {},
|
|
151
|
+
options: {},
|
|
152
|
+
valueFormat: {},
|
|
153
|
+
currencySymbol: { default: "£" },
|
|
154
|
+
locale: {},
|
|
155
|
+
showLegend: { type: Boolean, default: void 0 }
|
|
156
|
+
},
|
|
157
|
+
setup(o) {
|
|
158
|
+
y();
|
|
159
|
+
const e = o, t = i(() => ({
|
|
160
|
+
labels: e.labels,
|
|
161
|
+
datasets: _(e.datasets, "line", e.labels.length)
|
|
162
|
+
})), a = i(
|
|
163
|
+
() => p(
|
|
164
|
+
v({
|
|
165
|
+
valueFormat: e.valueFormat,
|
|
166
|
+
currencySymbol: e.currencySymbol,
|
|
167
|
+
locale: e.locale,
|
|
168
|
+
showLegend: e.showLegend ?? e.datasets.length > 1,
|
|
169
|
+
hasValueAxis: !0
|
|
170
|
+
}),
|
|
171
|
+
e.options ?? {}
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
return (n, s) => (f(), b("div", I, [
|
|
175
|
+
h(g(O), {
|
|
176
|
+
data: t.value,
|
|
177
|
+
options: a.value
|
|
178
|
+
}, null, 8, ["data", "options"])
|
|
179
|
+
]));
|
|
180
|
+
}
|
|
181
|
+
}), j = { class: "dx-chart" }, G = /* @__PURE__ */ m({
|
|
182
|
+
__name: "DXDoughnutChart",
|
|
183
|
+
props: {
|
|
184
|
+
labels: {},
|
|
185
|
+
data: {},
|
|
186
|
+
datasets: {},
|
|
187
|
+
options: {},
|
|
188
|
+
valueFormat: {},
|
|
189
|
+
currencySymbol: { default: "£" },
|
|
190
|
+
locale: {},
|
|
191
|
+
showLegend: { type: Boolean, default: void 0 }
|
|
192
|
+
},
|
|
193
|
+
setup(o) {
|
|
194
|
+
y();
|
|
195
|
+
const e = o, t = i(
|
|
196
|
+
() => e.datasets ?? [{ data: e.data ?? [] }]
|
|
197
|
+
), a = i(() => ({
|
|
198
|
+
labels: e.labels,
|
|
199
|
+
datasets: _(t.value, "doughnut", e.labels.length)
|
|
200
|
+
})), n = i(
|
|
201
|
+
() => p(
|
|
202
|
+
v({
|
|
203
|
+
valueFormat: e.valueFormat,
|
|
204
|
+
currencySymbol: e.currencySymbol,
|
|
205
|
+
locale: e.locale,
|
|
206
|
+
showLegend: e.showLegend ?? !0,
|
|
207
|
+
hasValueAxis: !1
|
|
208
|
+
}),
|
|
209
|
+
e.options ?? {}
|
|
210
|
+
)
|
|
211
|
+
);
|
|
212
|
+
return (s, l) => (f(), b("div", j, [
|
|
213
|
+
h(g(P), {
|
|
214
|
+
data: a.value,
|
|
215
|
+
options: n.value
|
|
216
|
+
}, null, 8, ["data", "options"])
|
|
217
|
+
]));
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
export {
|
|
221
|
+
q as DXBarChart,
|
|
222
|
+
G as DXDoughnutChart,
|
|
223
|
+
z as DXLineChart
|
|
224
|
+
};
|
|
225
|
+
//# sourceMappingURL=charts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts.js","sources":["../resources/js/components/charts/chartTheme.ts","../resources/js/components/charts/DXBarChart.vue","../resources/js/components/charts/DXLineChart.vue","../resources/js/components/charts/DXDoughnutChart.vue"],"sourcesContent":["/**\n * Shared theming for the DX*Chart wrappers: the dedicated categorical chart\n * palette (--dx-chart-* from the live theme), dashboard-friendly default options (no gridlines /\n * legend clutter, responsive, formatted ticks), and a one-time Chart.js\n * registration. chart.js / vue-chartjs are OPTIONAL peer deps.\n */\nimport { Chart, registerables } from \"chart.js\";\n\nexport type ChartValueFormat = \"number\" | \"currency\" | \"percent\";\n\nconst isPlainObject = (value: unknown): value is Record<string, any> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\n/** Deep-merge consumer `options` over the themed defaults (arrays replace). */\nexport function mergeOptions(\n base: Record<string, any>,\n override: Record<string, any>,\n): Record<string, any> {\n const result: Record<string, any> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (isPlainObject(value) && isPlainObject(result[key])) {\n result[key] = mergeOptions(result[key], value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nlet registered = false;\n\n/**\n * Register Chart.js (idempotent). Uses the full `registerables` set so every\n * controller / scale / element / plugin (incl. Legend, Tooltip, Filler) is\n * available — chart.js is an external peer dep, so this adds no bundle weight.\n */\nexport function registerCharts(): void {\n if (registered) return;\n Chart.register(...registerables);\n registered = true;\n}\n\n// The dedicated data-viz palette (`$dx-chart-palette` in theme.scss) — eight\n// vivid hues in a fixed, CVD-validated order, published as --dx-chart-1..8.\n// Deliberately NOT the semantic --bs-* colours (#141): the base theme colours\n// are dark AA \"emphasis\" shades (too muted for series), and status colours\n// shouldn't impersonate \"series 2\". Fallbacks mirror the shipped theme so\n// charts still render without the CSS (SSR / tests / a consumer who didn't\n// import it). Sync with theme.scss's $dx-chart-palette is enforced by a test\n// that parses the Sass source (charts.test.ts), which is why this is exported.\nexport const PALETTE_VARS: Array<[string, string]> = [\n [\"--dx-chart-1\", \"#2563eb\"], // blue\n [\"--dx-chart-2\", \"#65a30d\"], // lime\n [\"--dx-chart-3\", \"#7c3aed\"], // violet\n [\"--dx-chart-4\", \"#0d9488\"], // teal\n [\"--dx-chart-5\", \"#ea580c\"], // orange\n [\"--dx-chart-6\", \"#0891b2\"], // cyan\n [\"--dx-chart-7\", \"#d97706\"], // amber\n [\"--dx-chart-8\", \"#db2777\"], // pink\n];\n\n/** Resolve the themed categorical palette from the document root. */\nexport function getPalette(): string[] {\n if (typeof document === \"undefined\" || typeof getComputedStyle === \"undefined\") {\n return PALETTE_VARS.map(([, fallback]) => fallback);\n }\n const styles = getComputedStyle(document.documentElement);\n return PALETTE_VARS.map(([name, fallback]) => {\n const value = styles.getPropertyValue(name).trim();\n return value || fallback;\n });\n}\n\n/** Read a single theme colour (e.g. the body text colour) with a fallback. */\nfunction themeColor(name: string, fallback: string): string {\n if (typeof document === \"undefined\" || typeof getComputedStyle === \"undefined\") {\n return fallback;\n }\n const value = getComputedStyle(document.documentElement)\n .getPropertyValue(name)\n .trim();\n return value || fallback;\n}\n\n/** Add an alpha channel to a hex or rgb() colour (best-effort). */\nexport function withAlpha(color: string, alpha: number): string {\n const hex = color.replace(/^#/, \"\");\n if (/^[0-9a-f]{6}$/i.test(hex)) {\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n const rgbMatch = color.match(/^rgba?\\(([^)]+)\\)$/);\n if (rgbMatch) {\n const [r, g, b] = rgbMatch[1].split(\",\").map((n) => n.trim());\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n return color;\n}\n\n/** Format a numeric value per the chart's value format (for tick/tooltips). */\nexport function formatValue(\n value: number,\n format: ChartValueFormat | undefined,\n currencySymbol: string,\n locale?: string,\n): string {\n const num = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 2,\n }).format(value);\n if (format === \"currency\") return `${currencySymbol}${num}`;\n if (format === \"percent\") return `${num}%`;\n return num;\n}\n\nexport interface BaseOptionArgs {\n valueFormat?: ChartValueFormat;\n currencySymbol?: string;\n locale?: string;\n /** Show the legend (default: false for a single dataset, true for many). */\n showLegend?: boolean;\n /** Whether the chart has value axes (bar/line) vs none (doughnut). */\n hasValueAxis?: boolean;\n}\n\n/** Dashboard default Chart.js options merged under any consumer `options`. */\nexport function baseOptions(args: BaseOptionArgs): Record<string, any> {\n const {\n valueFormat,\n currencySymbol = \"£\",\n locale,\n showLegend = false,\n hasValueAxis = true,\n } = args;\n\n const gridColor = withAlpha(themeColor(\"--bs-border-color\", \"#dee2e6\"), 0.6);\n const tickColor = themeColor(\"--bs-secondary-color\", \"#6c757d\");\n\n const options: Record<string, any> = {\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: { display: showLegend, labels: { color: tickColor } },\n tooltip: {\n callbacks: {\n label: (ctx: any) => {\n const raw = ctx.parsed?.y ?? ctx.parsed ?? ctx.raw;\n const value = typeof raw === \"number\" ? raw : Number(raw);\n const formatted = Number.isFinite(value)\n ? formatValue(value, valueFormat, currencySymbol, locale)\n : String(raw);\n const label = ctx.dataset?.label ?? ctx.label ?? \"\";\n return label ? `${label}: ${formatted}` : formatted;\n },\n },\n },\n },\n };\n\n if (hasValueAxis) {\n options.scales = {\n x: {\n grid: { display: false },\n border: { color: gridColor },\n ticks: { color: tickColor },\n },\n y: {\n beginAtZero: true,\n grid: { color: gridColor, drawBorder: false },\n border: { display: false },\n ticks: {\n color: tickColor,\n callback: (value: number | string) =>\n formatValue(Number(value), valueFormat, currencySymbol, locale),\n },\n },\n };\n }\n\n return options;\n}\n\n/**\n * Apply the themed palette to any dataset that doesn't set its own colours.\n * Bar: one colour per dataset (or per bar for a single dataset). Line: a themed\n * stroke + translucent fill. Doughnut/pie: one colour per slice.\n */\nexport function applyPalette(\n datasets: any[],\n kind: \"bar\" | \"line\" | \"doughnut\",\n labelsCount: number,\n): any[] {\n const palette = getPalette();\n const single = datasets.length === 1;\n\n return datasets.map((dataset, index) => {\n const next = { ...dataset };\n const color = palette[index % palette.length];\n\n if (kind === \"doughnut\") {\n if (next.backgroundColor === undefined) {\n next.backgroundColor = Array.from(\n { length: labelsCount },\n (_, i) => palette[i % palette.length],\n );\n }\n return next;\n }\n\n if (kind === \"line\") {\n if (next.borderColor === undefined) next.borderColor = color;\n if (next.backgroundColor === undefined) {\n next.backgroundColor = withAlpha(color, 0.15);\n }\n if (next.tension === undefined) next.tension = 0.3;\n if (next.fill === undefined) next.fill = true;\n if (next.pointRadius === undefined) next.pointRadius = 2;\n return next;\n }\n\n // bar\n if (next.backgroundColor === undefined) {\n next.backgroundColor =\n single && labelsCount > 1\n ? Array.from({ length: labelsCount }, () => color)\n : color;\n }\n if (next.borderRadius === undefined) next.borderRadius = 4;\n return next;\n });\n}\n","<!--\n @component\n A themed bar chart. Thin wrapper around vue-chartjs (chart.js) with the\n theme's dedicated chart palette (--dx-chart-1..8) applied and dashboard-friendly defaults (no x gridlines,\n formatted value ticks, responsive, legend hidden for a single series). Pass\n `labels` + `datasets`; `options` deep-merges over the defaults.\n\n Requires the optional peer deps `chart.js` and `vue-chartjs`.\n-->\n<template>\n <div class=\"dx-chart\">\n <Bar :data=\"chartData\" :options=\"mergedOptions\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Bar } from \"vue-chartjs\";\nimport {\n registerCharts,\n baseOptions,\n applyPalette,\n mergeOptions,\n type ChartValueFormat,\n} from \"./chartTheme\";\n\nregisterCharts();\n\ninterface Props {\n /** X-axis category labels. */\n labels: string[];\n /** Chart.js datasets. Colours are themed when a dataset omits them. */\n datasets: any[];\n /** Chart.js options; deep-merged over the themed defaults. */\n options?: Record<string, any>;\n /** Format value-axis ticks and tooltips. */\n valueFormat?: ChartValueFormat;\n /** Currency symbol for valueFormat: \"currency\" (default \"£\"). */\n currencySymbol?: string;\n /** Locale for number formatting. */\n locale?: string;\n /** Show the legend (default: only when there is more than one dataset). */\n showLegend?: boolean;\n}\n\n// `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the\n// `?? datasets.length > 1` default can actually fire when it isn't passed.\nconst props = withDefaults(defineProps<Props>(), {\n currencySymbol: \"£\",\n showLegend: undefined,\n});\n\nconst chartData = computed(() => ({\n labels: props.labels,\n datasets: applyPalette(props.datasets, \"bar\", props.labels.length),\n}));\n\nconst mergedOptions = computed(() =>\n mergeOptions(\n baseOptions({\n valueFormat: props.valueFormat,\n currencySymbol: props.currencySymbol,\n locale: props.locale,\n showLegend: props.showLegend ?? props.datasets.length > 1,\n hasValueAxis: true,\n }),\n props.options ?? {},\n ),\n);\n</script>\n","<!--\n @component\n A themed line chart. Thin wrapper around vue-chartjs (chart.js) with the\n theme's dedicated chart palette applied (--dx-chart-1..8 stroke + translucent fill, smoothed line)\n and dashboard-friendly defaults. Pass `labels` + `datasets`; `options`\n deep-merges over the defaults.\n\n Requires the optional peer deps `chart.js` and `vue-chartjs`.\n-->\n<template>\n <div class=\"dx-chart\">\n <Line :data=\"chartData\" :options=\"mergedOptions\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Line } from \"vue-chartjs\";\nimport {\n registerCharts,\n baseOptions,\n applyPalette,\n mergeOptions,\n type ChartValueFormat,\n} from \"./chartTheme\";\n\nregisterCharts();\n\ninterface Props {\n /** X-axis category labels. */\n labels: string[];\n /** Chart.js datasets. Colours are themed when a dataset omits them. */\n datasets: any[];\n /** Chart.js options; deep-merged over the themed defaults. */\n options?: Record<string, any>;\n /** Format value-axis ticks and tooltips. */\n valueFormat?: ChartValueFormat;\n /** Currency symbol for valueFormat: \"currency\" (default \"£\"). */\n currencySymbol?: string;\n /** Locale for number formatting. */\n locale?: string;\n /** Show the legend (default: only when there is more than one dataset). */\n showLegend?: boolean;\n}\n\n// `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the\n// `?? datasets.length > 1` default can actually fire when it isn't passed.\nconst props = withDefaults(defineProps<Props>(), {\n currencySymbol: \"£\",\n showLegend: undefined,\n});\n\nconst chartData = computed(() => ({\n labels: props.labels,\n datasets: applyPalette(props.datasets, \"line\", props.labels.length),\n}));\n\nconst mergedOptions = computed(() =>\n mergeOptions(\n baseOptions({\n valueFormat: props.valueFormat,\n currencySymbol: props.currencySymbol,\n locale: props.locale,\n showLegend: props.showLegend ?? props.datasets.length > 1,\n hasValueAxis: true,\n }),\n props.options ?? {},\n ),\n);\n</script>\n","<!--\n @component\n A themed doughnut chart. Thin wrapper around vue-chartjs (chart.js) with one\n chart-palette colour (--dx-chart-1..8) per slice and dashboard-friendly defaults. Pass\n `labels` + either `data` (a number array) or full `datasets`; `options`\n deep-merges over the defaults.\n\n Requires the optional peer deps `chart.js` and `vue-chartjs`.\n-->\n<template>\n <div class=\"dx-chart\">\n <Doughnut :data=\"chartData\" :options=\"mergedOptions\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Doughnut } from \"vue-chartjs\";\nimport {\n registerCharts,\n baseOptions,\n applyPalette,\n mergeOptions,\n type ChartValueFormat,\n} from \"./chartTheme\";\n\nregisterCharts();\n\ninterface Props {\n /** Slice labels. */\n labels: string[];\n /** Convenience: a single number array (one value per label). */\n data?: number[];\n /** Full Chart.js datasets (alternative to `data`). */\n datasets?: any[];\n /** Chart.js options; deep-merged over the themed defaults. */\n options?: Record<string, any>;\n /** Format tooltip values. */\n valueFormat?: ChartValueFormat;\n /** Currency symbol for valueFormat: \"currency\" (default \"£\"). */\n currencySymbol?: string;\n /** Locale for number formatting. */\n locale?: string;\n /** Show the legend (default: true — slices need identifying). */\n showLegend?: boolean;\n}\n\n// `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the\n// `?? true` default can actually fire when it isn't passed.\nconst props = withDefaults(defineProps<Props>(), {\n currencySymbol: \"£\",\n showLegend: undefined,\n});\n\nconst resolvedDatasets = computed(() =>\n props.datasets ?? [{ data: props.data ?? [] }],\n);\n\nconst chartData = computed(() => ({\n labels: props.labels,\n datasets: applyPalette(resolvedDatasets.value, \"doughnut\", props.labels.length),\n}));\n\nconst mergedOptions = computed(() =>\n mergeOptions(\n baseOptions({\n valueFormat: props.valueFormat,\n currencySymbol: props.currencySymbol,\n locale: props.locale,\n showLegend: props.showLegend ?? true,\n hasValueAxis: false,\n }),\n props.options ?? {},\n ),\n);\n</script>\n"],"names":["isPlainObject","value","mergeOptions","base","override","result","key","registered","registerCharts","Chart","registerables","PALETTE_VARS","getPalette","fallback","styles","name","themeColor","withAlpha","color","alpha","hex","r","g","b","rgbMatch","n","formatValue","format","currencySymbol","locale","num","baseOptions","args","valueFormat","showLegend","hasValueAxis","gridColor","tickColor","options","ctx","raw","_a","formatted","label","_b","applyPalette","datasets","kind","labelsCount","palette","single","dataset","index","next","_","i","props","__props","chartData","computed","mergedOptions","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","Bar","Line","resolvedDatasets","Doughnut"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(l,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("vue"),require("vue-chartjs"),require("chart.js")):typeof define=="function"&&define.amd?define(["exports","vue","vue-chartjs","chart.js"],o):(l=typeof globalThis<"u"?globalThis:l||self,o(l.DashboardForLaravelCharts={},l.Vue,l.VueChartjs,l.Chart))})(this,(function(l,o,f,y){"use strict";const C=r=>!!r&&typeof r=="object"&&!Array.isArray(r);function m(r,e){const t={...r};for(const[n,s]of Object.entries(e))C(s)&&C(t[n])?t[n]=m(t[n],s):t[n]=s;return t}let _=!1;function h(){_||(y.Chart.register(...y.registerables),_=!0)}const v=[["--dx-chart-1","#2563eb"],["--dx-chart-2","#65a30d"],["--dx-chart-3","#7c3aed"],["--dx-chart-4","#0d9488"],["--dx-chart-5","#ea580c"],["--dx-chart-6","#0891b2"],["--dx-chart-7","#d97706"],["--dx-chart-8","#db2777"]];function A(){if(typeof document>"u"||typeof getComputedStyle>"u")return v.map(([,e])=>e);const r=getComputedStyle(document.documentElement);return v.map(([e,t])=>r.getPropertyValue(e).trim()||t)}function $(r,e){return typeof document>"u"||typeof getComputedStyle>"u"?e:getComputedStyle(document.documentElement).getPropertyValue(r).trim()||e}function x(r,e){const t=r.replace(/^#/,"");if(/^[0-9a-f]{6}$/i.test(t)){const s=parseInt(t.slice(0,2),16),c=parseInt(t.slice(2,4),16),d=parseInt(t.slice(4,6),16);return`rgba(${s}, ${c}, ${d}, ${e})`}const n=r.match(/^rgba?\(([^)]+)\)$/);if(n){const[s,c,d]=n[1].split(",").map(a=>a.trim());return`rgba(${s}, ${c}, ${d}, ${e})`}return r}function S(r,e,t,n){const s=new Intl.NumberFormat(n,{maximumFractionDigits:2}).format(r);return e==="currency"?`${t}${s}`:e==="percent"?`${s}%`:s}function b(r){const{valueFormat:e,currencySymbol:t="£",locale:n,showLegend:s=!1,hasValueAxis:c=!0}=r,d=x($("--bs-border-color","#dee2e6"),.6),a=$("--bs-secondary-color","#6c757d"),u={responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:s,labels:{color:a}},tooltip:{callbacks:{label:i=>{var L,F;const p=((L=i.parsed)==null?void 0:L.y)??i.parsed??i.raw,k=typeof p=="number"?p:Number(p),w=Number.isFinite(k)?S(k,e,t,n):String(p),D=((F=i.dataset)==null?void 0:F.label)??i.label??"";return D?`${D}: ${w}`:w}}}}};return c&&(u.scales={x:{grid:{display:!1},border:{color:d},ticks:{color:a}},y:{beginAtZero:!0,grid:{color:d,drawBorder:!1},border:{display:!1},ticks:{color:a,callback:i=>S(Number(i),e,t,n)}}}),u}function g(r,e,t){const n=A(),s=r.length===1;return r.map((c,d)=>{const a={...c},u=n[d%n.length];return e==="doughnut"?(a.backgroundColor===void 0&&(a.backgroundColor=Array.from({length:t},(i,p)=>n[p%n.length])),a):e==="line"?(a.borderColor===void 0&&(a.borderColor=u),a.backgroundColor===void 0&&(a.backgroundColor=x(u,.15)),a.tension===void 0&&(a.tension=.3),a.fill===void 0&&(a.fill=!0),a.pointRadius===void 0&&(a.pointRadius=2),a):(a.backgroundColor===void 0&&(a.backgroundColor=s&&t>1?Array.from({length:t},()=>u):u),a.borderRadius===void 0&&(a.borderRadius=4),a)})}const B={class:"dx-chart"},V=o.defineComponent({__name:"DXBarChart",props:{labels:{},datasets:{},options:{},valueFormat:{},currencySymbol:{default:"£"},locale:{},showLegend:{type:Boolean,default:void 0}},setup(r){h();const e=r,t=o.computed(()=>({labels:e.labels,datasets:g(e.datasets,"bar",e.labels.length)})),n=o.computed(()=>m(b({valueFormat:e.valueFormat,currencySymbol:e.currencySymbol,locale:e.locale,showLegend:e.showLegend??e.datasets.length>1,hasValueAxis:!0}),e.options??{}));return(s,c)=>(o.openBlock(),o.createElementBlock("div",B,[o.createVNode(o.unref(f.Bar),{data:t.value,options:n.value},null,8,["data","options"])]))}}),O={class:"dx-chart"},j=o.defineComponent({__name:"DXLineChart",props:{labels:{},datasets:{},options:{},valueFormat:{},currencySymbol:{default:"£"},locale:{},showLegend:{type:Boolean,default:void 0}},setup(r){h();const e=r,t=o.computed(()=>({labels:e.labels,datasets:g(e.datasets,"line",e.labels.length)})),n=o.computed(()=>m(b({valueFormat:e.valueFormat,currencySymbol:e.currencySymbol,locale:e.locale,showLegend:e.showLegend??e.datasets.length>1,hasValueAxis:!0}),e.options??{}));return(s,c)=>(o.openBlock(),o.createElementBlock("div",O,[o.createVNode(o.unref(f.Line),{data:t.value,options:n.value},null,8,["data","options"])]))}}),E={class:"dx-chart"},N=o.defineComponent({__name:"DXDoughnutChart",props:{labels:{},data:{},datasets:{},options:{},valueFormat:{},currencySymbol:{default:"£"},locale:{},showLegend:{type:Boolean,default:void 0}},setup(r){h();const e=r,t=o.computed(()=>e.datasets??[{data:e.data??[]}]),n=o.computed(()=>({labels:e.labels,datasets:g(t.value,"doughnut",e.labels.length)})),s=o.computed(()=>m(b({valueFormat:e.valueFormat,currencySymbol:e.currencySymbol,locale:e.locale,showLegend:e.showLegend??!0,hasValueAxis:!1}),e.options??{}));return(c,d)=>(o.openBlock(),o.createElementBlock("div",E,[o.createVNode(o.unref(f.Doughnut),{data:n.value,options:s.value},null,8,["data","options"])]))}});l.DXBarChart=V,l.DXDoughnutChart=N,l.DXLineChart=j,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
|
|
2
|
+
//# sourceMappingURL=charts.umd.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts.umd.cjs","sources":["../resources/js/components/charts/chartTheme.ts","../resources/js/components/charts/DXBarChart.vue","../resources/js/components/charts/DXLineChart.vue","../resources/js/components/charts/DXDoughnutChart.vue"],"sourcesContent":["/**\n * Shared theming for the DX*Chart wrappers: the dedicated categorical chart\n * palette (--dx-chart-* from the live theme), dashboard-friendly default options (no gridlines /\n * legend clutter, responsive, formatted ticks), and a one-time Chart.js\n * registration. chart.js / vue-chartjs are OPTIONAL peer deps.\n */\nimport { Chart, registerables } from \"chart.js\";\n\nexport type ChartValueFormat = \"number\" | \"currency\" | \"percent\";\n\nconst isPlainObject = (value: unknown): value is Record<string, any> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\n/** Deep-merge consumer `options` over the themed defaults (arrays replace). */\nexport function mergeOptions(\n base: Record<string, any>,\n override: Record<string, any>,\n): Record<string, any> {\n const result: Record<string, any> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (isPlainObject(value) && isPlainObject(result[key])) {\n result[key] = mergeOptions(result[key], value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nlet registered = false;\n\n/**\n * Register Chart.js (idempotent). Uses the full `registerables` set so every\n * controller / scale / element / plugin (incl. Legend, Tooltip, Filler) is\n * available — chart.js is an external peer dep, so this adds no bundle weight.\n */\nexport function registerCharts(): void {\n if (registered) return;\n Chart.register(...registerables);\n registered = true;\n}\n\n// The dedicated data-viz palette (`$dx-chart-palette` in theme.scss) — eight\n// vivid hues in a fixed, CVD-validated order, published as --dx-chart-1..8.\n// Deliberately NOT the semantic --bs-* colours (#141): the base theme colours\n// are dark AA \"emphasis\" shades (too muted for series), and status colours\n// shouldn't impersonate \"series 2\". Fallbacks mirror the shipped theme so\n// charts still render without the CSS (SSR / tests / a consumer who didn't\n// import it). Sync with theme.scss's $dx-chart-palette is enforced by a test\n// that parses the Sass source (charts.test.ts), which is why this is exported.\nexport const PALETTE_VARS: Array<[string, string]> = [\n [\"--dx-chart-1\", \"#2563eb\"], // blue\n [\"--dx-chart-2\", \"#65a30d\"], // lime\n [\"--dx-chart-3\", \"#7c3aed\"], // violet\n [\"--dx-chart-4\", \"#0d9488\"], // teal\n [\"--dx-chart-5\", \"#ea580c\"], // orange\n [\"--dx-chart-6\", \"#0891b2\"], // cyan\n [\"--dx-chart-7\", \"#d97706\"], // amber\n [\"--dx-chart-8\", \"#db2777\"], // pink\n];\n\n/** Resolve the themed categorical palette from the document root. */\nexport function getPalette(): string[] {\n if (typeof document === \"undefined\" || typeof getComputedStyle === \"undefined\") {\n return PALETTE_VARS.map(([, fallback]) => fallback);\n }\n const styles = getComputedStyle(document.documentElement);\n return PALETTE_VARS.map(([name, fallback]) => {\n const value = styles.getPropertyValue(name).trim();\n return value || fallback;\n });\n}\n\n/** Read a single theme colour (e.g. the body text colour) with a fallback. */\nfunction themeColor(name: string, fallback: string): string {\n if (typeof document === \"undefined\" || typeof getComputedStyle === \"undefined\") {\n return fallback;\n }\n const value = getComputedStyle(document.documentElement)\n .getPropertyValue(name)\n .trim();\n return value || fallback;\n}\n\n/** Add an alpha channel to a hex or rgb() colour (best-effort). */\nexport function withAlpha(color: string, alpha: number): string {\n const hex = color.replace(/^#/, \"\");\n if (/^[0-9a-f]{6}$/i.test(hex)) {\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n const rgbMatch = color.match(/^rgba?\\(([^)]+)\\)$/);\n if (rgbMatch) {\n const [r, g, b] = rgbMatch[1].split(\",\").map((n) => n.trim());\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n return color;\n}\n\n/** Format a numeric value per the chart's value format (for tick/tooltips). */\nexport function formatValue(\n value: number,\n format: ChartValueFormat | undefined,\n currencySymbol: string,\n locale?: string,\n): string {\n const num = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 2,\n }).format(value);\n if (format === \"currency\") return `${currencySymbol}${num}`;\n if (format === \"percent\") return `${num}%`;\n return num;\n}\n\nexport interface BaseOptionArgs {\n valueFormat?: ChartValueFormat;\n currencySymbol?: string;\n locale?: string;\n /** Show the legend (default: false for a single dataset, true for many). */\n showLegend?: boolean;\n /** Whether the chart has value axes (bar/line) vs none (doughnut). */\n hasValueAxis?: boolean;\n}\n\n/** Dashboard default Chart.js options merged under any consumer `options`. */\nexport function baseOptions(args: BaseOptionArgs): Record<string, any> {\n const {\n valueFormat,\n currencySymbol = \"£\",\n locale,\n showLegend = false,\n hasValueAxis = true,\n } = args;\n\n const gridColor = withAlpha(themeColor(\"--bs-border-color\", \"#dee2e6\"), 0.6);\n const tickColor = themeColor(\"--bs-secondary-color\", \"#6c757d\");\n\n const options: Record<string, any> = {\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: { display: showLegend, labels: { color: tickColor } },\n tooltip: {\n callbacks: {\n label: (ctx: any) => {\n const raw = ctx.parsed?.y ?? ctx.parsed ?? ctx.raw;\n const value = typeof raw === \"number\" ? raw : Number(raw);\n const formatted = Number.isFinite(value)\n ? formatValue(value, valueFormat, currencySymbol, locale)\n : String(raw);\n const label = ctx.dataset?.label ?? ctx.label ?? \"\";\n return label ? `${label}: ${formatted}` : formatted;\n },\n },\n },\n },\n };\n\n if (hasValueAxis) {\n options.scales = {\n x: {\n grid: { display: false },\n border: { color: gridColor },\n ticks: { color: tickColor },\n },\n y: {\n beginAtZero: true,\n grid: { color: gridColor, drawBorder: false },\n border: { display: false },\n ticks: {\n color: tickColor,\n callback: (value: number | string) =>\n formatValue(Number(value), valueFormat, currencySymbol, locale),\n },\n },\n };\n }\n\n return options;\n}\n\n/**\n * Apply the themed palette to any dataset that doesn't set its own colours.\n * Bar: one colour per dataset (or per bar for a single dataset). Line: a themed\n * stroke + translucent fill. Doughnut/pie: one colour per slice.\n */\nexport function applyPalette(\n datasets: any[],\n kind: \"bar\" | \"line\" | \"doughnut\",\n labelsCount: number,\n): any[] {\n const palette = getPalette();\n const single = datasets.length === 1;\n\n return datasets.map((dataset, index) => {\n const next = { ...dataset };\n const color = palette[index % palette.length];\n\n if (kind === \"doughnut\") {\n if (next.backgroundColor === undefined) {\n next.backgroundColor = Array.from(\n { length: labelsCount },\n (_, i) => palette[i % palette.length],\n );\n }\n return next;\n }\n\n if (kind === \"line\") {\n if (next.borderColor === undefined) next.borderColor = color;\n if (next.backgroundColor === undefined) {\n next.backgroundColor = withAlpha(color, 0.15);\n }\n if (next.tension === undefined) next.tension = 0.3;\n if (next.fill === undefined) next.fill = true;\n if (next.pointRadius === undefined) next.pointRadius = 2;\n return next;\n }\n\n // bar\n if (next.backgroundColor === undefined) {\n next.backgroundColor =\n single && labelsCount > 1\n ? Array.from({ length: labelsCount }, () => color)\n : color;\n }\n if (next.borderRadius === undefined) next.borderRadius = 4;\n return next;\n });\n}\n","<!--\n @component\n A themed bar chart. Thin wrapper around vue-chartjs (chart.js) with the\n theme's dedicated chart palette (--dx-chart-1..8) applied and dashboard-friendly defaults (no x gridlines,\n formatted value ticks, responsive, legend hidden for a single series). Pass\n `labels` + `datasets`; `options` deep-merges over the defaults.\n\n Requires the optional peer deps `chart.js` and `vue-chartjs`.\n-->\n<template>\n <div class=\"dx-chart\">\n <Bar :data=\"chartData\" :options=\"mergedOptions\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Bar } from \"vue-chartjs\";\nimport {\n registerCharts,\n baseOptions,\n applyPalette,\n mergeOptions,\n type ChartValueFormat,\n} from \"./chartTheme\";\n\nregisterCharts();\n\ninterface Props {\n /** X-axis category labels. */\n labels: string[];\n /** Chart.js datasets. Colours are themed when a dataset omits them. */\n datasets: any[];\n /** Chart.js options; deep-merged over the themed defaults. */\n options?: Record<string, any>;\n /** Format value-axis ticks and tooltips. */\n valueFormat?: ChartValueFormat;\n /** Currency symbol for valueFormat: \"currency\" (default \"£\"). */\n currencySymbol?: string;\n /** Locale for number formatting. */\n locale?: string;\n /** Show the legend (default: only when there is more than one dataset). */\n showLegend?: boolean;\n}\n\n// `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the\n// `?? datasets.length > 1` default can actually fire when it isn't passed.\nconst props = withDefaults(defineProps<Props>(), {\n currencySymbol: \"£\",\n showLegend: undefined,\n});\n\nconst chartData = computed(() => ({\n labels: props.labels,\n datasets: applyPalette(props.datasets, \"bar\", props.labels.length),\n}));\n\nconst mergedOptions = computed(() =>\n mergeOptions(\n baseOptions({\n valueFormat: props.valueFormat,\n currencySymbol: props.currencySymbol,\n locale: props.locale,\n showLegend: props.showLegend ?? props.datasets.length > 1,\n hasValueAxis: true,\n }),\n props.options ?? {},\n ),\n);\n</script>\n","<!--\n @component\n A themed line chart. Thin wrapper around vue-chartjs (chart.js) with the\n theme's dedicated chart palette applied (--dx-chart-1..8 stroke + translucent fill, smoothed line)\n and dashboard-friendly defaults. Pass `labels` + `datasets`; `options`\n deep-merges over the defaults.\n\n Requires the optional peer deps `chart.js` and `vue-chartjs`.\n-->\n<template>\n <div class=\"dx-chart\">\n <Line :data=\"chartData\" :options=\"mergedOptions\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Line } from \"vue-chartjs\";\nimport {\n registerCharts,\n baseOptions,\n applyPalette,\n mergeOptions,\n type ChartValueFormat,\n} from \"./chartTheme\";\n\nregisterCharts();\n\ninterface Props {\n /** X-axis category labels. */\n labels: string[];\n /** Chart.js datasets. Colours are themed when a dataset omits them. */\n datasets: any[];\n /** Chart.js options; deep-merged over the themed defaults. */\n options?: Record<string, any>;\n /** Format value-axis ticks and tooltips. */\n valueFormat?: ChartValueFormat;\n /** Currency symbol for valueFormat: \"currency\" (default \"£\"). */\n currencySymbol?: string;\n /** Locale for number formatting. */\n locale?: string;\n /** Show the legend (default: only when there is more than one dataset). */\n showLegend?: boolean;\n}\n\n// `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the\n// `?? datasets.length > 1` default can actually fire when it isn't passed.\nconst props = withDefaults(defineProps<Props>(), {\n currencySymbol: \"£\",\n showLegend: undefined,\n});\n\nconst chartData = computed(() => ({\n labels: props.labels,\n datasets: applyPalette(props.datasets, \"line\", props.labels.length),\n}));\n\nconst mergedOptions = computed(() =>\n mergeOptions(\n baseOptions({\n valueFormat: props.valueFormat,\n currencySymbol: props.currencySymbol,\n locale: props.locale,\n showLegend: props.showLegend ?? props.datasets.length > 1,\n hasValueAxis: true,\n }),\n props.options ?? {},\n ),\n);\n</script>\n","<!--\n @component\n A themed doughnut chart. Thin wrapper around vue-chartjs (chart.js) with one\n chart-palette colour (--dx-chart-1..8) per slice and dashboard-friendly defaults. Pass\n `labels` + either `data` (a number array) or full `datasets`; `options`\n deep-merges over the defaults.\n\n Requires the optional peer deps `chart.js` and `vue-chartjs`.\n-->\n<template>\n <div class=\"dx-chart\">\n <Doughnut :data=\"chartData\" :options=\"mergedOptions\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Doughnut } from \"vue-chartjs\";\nimport {\n registerCharts,\n baseOptions,\n applyPalette,\n mergeOptions,\n type ChartValueFormat,\n} from \"./chartTheme\";\n\nregisterCharts();\n\ninterface Props {\n /** Slice labels. */\n labels: string[];\n /** Convenience: a single number array (one value per label). */\n data?: number[];\n /** Full Chart.js datasets (alternative to `data`). */\n datasets?: any[];\n /** Chart.js options; deep-merged over the themed defaults. */\n options?: Record<string, any>;\n /** Format tooltip values. */\n valueFormat?: ChartValueFormat;\n /** Currency symbol for valueFormat: \"currency\" (default \"£\"). */\n currencySymbol?: string;\n /** Locale for number formatting. */\n locale?: string;\n /** Show the legend (default: true — slices need identifying). */\n showLegend?: boolean;\n}\n\n// `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the\n// `?? true` default can actually fire when it isn't passed.\nconst props = withDefaults(defineProps<Props>(), {\n currencySymbol: \"£\",\n showLegend: undefined,\n});\n\nconst resolvedDatasets = computed(() =>\n props.datasets ?? [{ data: props.data ?? [] }],\n);\n\nconst chartData = computed(() => ({\n labels: props.labels,\n datasets: applyPalette(resolvedDatasets.value, \"doughnut\", props.labels.length),\n}));\n\nconst mergedOptions = computed(() =>\n mergeOptions(\n baseOptions({\n valueFormat: props.valueFormat,\n currencySymbol: props.currencySymbol,\n locale: props.locale,\n showLegend: props.showLegend ?? true,\n hasValueAxis: false,\n }),\n props.options ?? {},\n ),\n);\n</script>\n"],"names":["isPlainObject","value","mergeOptions","base","override","result","key","registered","registerCharts","Chart","registerables","PALETTE_VARS","getPalette","fallback","styles","name","themeColor","withAlpha","color","alpha","hex","r","g","b","rgbMatch","n","formatValue","format","currencySymbol","locale","num","baseOptions","args","valueFormat","showLegend","hasValueAxis","gridColor","tickColor","options","ctx","raw","_a","formatted","label","_b","applyPalette","datasets","kind","labelsCount","palette","single","dataset","index","next","_","i","props","__props","chartData","computed","mergedOptions","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","Bar","Line","resolvedDatasets","Doughnut"],"mappings":"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"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
modelValue?: boolean | number;
|
|
3
|
+
};
|
|
1
4
|
declare var __VLS_7: string | number, __VLS_8: {};
|
|
2
5
|
type __VLS_Slots = {} & {
|
|
3
6
|
[K in NonNullable<typeof __VLS_7>]?: (props: typeof __VLS_8) => any;
|
|
4
7
|
};
|
|
5
|
-
declare const __VLS_component: import("vue").DefineComponent<
|
|
8
|
+
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
9
|
+
modelValue: boolean | number;
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
11
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
7
12
|
export default _default;
|
|
8
13
|
type __VLS_WithSlots<T, S> = T & {
|
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
import type { SelectOption } from "bootstrap-vue-next";
|
|
2
|
+
type AutocompleteOptions = readonly (object | string | number | boolean)[];
|
|
3
|
+
type FilterFunction = (options: SelectOption[], search: string) => SelectOption[];
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Options passed straight through to BAutocomplete (see its `options` prop). */
|
|
6
|
+
options?: AutocompleteOptions;
|
|
7
|
+
/**
|
|
8
|
+
* A custom filter. Composed with `null-option` rather than replaced: when a
|
|
9
|
+
* null option is present it stays pinned and this runs on the rest.
|
|
10
|
+
*/
|
|
11
|
+
filterFunction?: FilterFunction;
|
|
12
|
+
/**
|
|
13
|
+
* Prepend a pinned, never-filtered, selectable "no selection" row whose value
|
|
14
|
+
* is `null` (#138). `true` → default label "None"; a string → that label.
|
|
15
|
+
* Selecting it sets the model to `null` (bvn reads that as no selection, so
|
|
16
|
+
* the ✕ hides and the placeholder shows). Off by default — unchanged
|
|
17
|
+
* behaviour. DXTable does NOT use this; it builds its own "All" option.
|
|
18
|
+
*/
|
|
19
|
+
nullOption?: boolean | string;
|
|
20
|
+
}
|
|
1
21
|
declare var __VLS_6: string | number, __VLS_7: any;
|
|
2
22
|
type __VLS_Slots = {} & {
|
|
3
23
|
[K in NonNullable<typeof __VLS_6>]?: (props: typeof __VLS_7) => any;
|
|
4
24
|
};
|
|
5
|
-
declare const __VLS_component: import("vue").DefineComponent<
|
|
25
|
+
declare const __VLS_component: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
26
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
7
27
|
export default _default;
|
|
8
28
|
type __VLS_WithSlots<T, S> = T & {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare var __VLS_7: string | number, __VLS_8: any;
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
[K in NonNullable<typeof __VLS_7>]?: (props: typeof __VLS_8) => any;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
7
|
+
export default _default;
|
|
8
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
9
|
+
new (): {
|
|
10
|
+
$slots: S;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -46,9 +46,9 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}
|
|
|
46
46
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
47
47
|
onToggle?: (() => any) | undefined;
|
|
48
48
|
}>, {
|
|
49
|
-
collapsed: boolean;
|
|
50
|
-
hidden: boolean;
|
|
51
49
|
title: string;
|
|
50
|
+
hidden: boolean;
|
|
51
|
+
collapsed: boolean;
|
|
52
52
|
collapsibleGroups: boolean;
|
|
53
53
|
autoCollapseInactiveGroups: boolean;
|
|
54
54
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -112,10 +112,10 @@ declare var __VLS_1: {
|
|
|
112
112
|
model: any;
|
|
113
113
|
value: any;
|
|
114
114
|
update: typeof setValue;
|
|
115
|
-
},
|
|
115
|
+
}, __VLS_201: {
|
|
116
116
|
field: FieldDefinition;
|
|
117
117
|
model: any;
|
|
118
|
-
},
|
|
118
|
+
}, __VLS_206: {
|
|
119
119
|
field: FieldDefinition;
|
|
120
120
|
model: any;
|
|
121
121
|
};
|
|
@@ -160,9 +160,9 @@ type __VLS_Slots = {} & {
|
|
|
160
160
|
} & {
|
|
161
161
|
value?: (props: typeof __VLS_133) => any;
|
|
162
162
|
} & {
|
|
163
|
-
info?: (props: typeof
|
|
163
|
+
info?: (props: typeof __VLS_201) => any;
|
|
164
164
|
} & {
|
|
165
|
-
hint?: (props: typeof
|
|
165
|
+
hint?: (props: typeof __VLS_206) => any;
|
|
166
166
|
};
|
|
167
167
|
declare const __VLS_component: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
168
168
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
@@ -28,11 +28,21 @@ interface Props {
|
|
|
28
28
|
autoErrorTab?: boolean;
|
|
29
29
|
/**
|
|
30
30
|
* Wrap the form in a card for a visual boundary (mirrors DXTable's
|
|
31
|
-
* `card` prop).
|
|
32
|
-
* card
|
|
33
|
-
*
|
|
31
|
+
* `card` prop). Off by default since DXForm is commonly embedded in a
|
|
32
|
+
* page card or modal already. Tabbed forms are wrapped by default
|
|
33
|
+
* regardless — see `cardTabs`; setting `card` also forces the tabbed
|
|
34
|
+
* card on even when `cardTabs` is disabled.
|
|
34
35
|
*/
|
|
35
36
|
card?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Wrap a TABBED form's content in a card panel so the active tab reads
|
|
39
|
+
* as a finished panel connected to the tab strip (the standard
|
|
40
|
+
* Bootstrap card-with-tabs pattern) rather than floating on the bare
|
|
41
|
+
* page background (#159). On by default. Set `false` for bare tabs
|
|
42
|
+
* (e.g. inside a modal that already provides a boundary). Ignored for
|
|
43
|
+
* flat (non-tabbed) forms — use `card` for those.
|
|
44
|
+
*/
|
|
45
|
+
cardTabs?: boolean;
|
|
36
46
|
/**
|
|
37
47
|
* Form-wide field layout: "vertical" (default, label above input) or
|
|
38
48
|
* "horizontal" (label left, input right). Overridable per-field via
|
|
@@ -63,12 +73,13 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_PublicProps,
|
|
|
63
73
|
onSubmit?: (() => any) | undefined;
|
|
64
74
|
"onUpdate:activeTab"?: ((value: number) => any) | undefined;
|
|
65
75
|
}>, {
|
|
66
|
-
card: boolean;
|
|
67
76
|
layout: "vertical" | "horizontal";
|
|
77
|
+
card: boolean;
|
|
68
78
|
submitText: string;
|
|
69
79
|
submitLoadingText: string;
|
|
70
80
|
showSubmit: boolean;
|
|
71
81
|
autoErrorTab: boolean;
|
|
82
|
+
cardTabs: boolean;
|
|
72
83
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
73
84
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
74
85
|
export default _default;
|
|
@@ -36,6 +36,19 @@ export interface TableField {
|
|
|
36
36
|
filter?: FilterType;
|
|
37
37
|
filterOptions?: FilterOption[];
|
|
38
38
|
filterPlaceholder?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Fixed width for this column, applied via a `<colgroup>` `<col>`. A number
|
|
41
|
+
* is treated as pixels (`200` → `200px`); a string is used verbatim
|
|
42
|
+
* (`"20%"`, `"12rem"`). Pair with the table-level `fixedLayout` prop so the
|
|
43
|
+
* width is authoritative and the column stops resizing to fit its content —
|
|
44
|
+
* without `fixedLayout` a wider cell can still stretch the column (#156).
|
|
45
|
+
*/
|
|
46
|
+
width?: string | number;
|
|
47
|
+
/**
|
|
48
|
+
* Minimum width for this column, applied via the same `<col>` as `width`.
|
|
49
|
+
* A number is pixels; a string is used verbatim.
|
|
50
|
+
*/
|
|
51
|
+
minWidth?: string | number;
|
|
39
52
|
[key: string]: any;
|
|
40
53
|
}
|
|
41
54
|
export interface PaginationData {
|
|
@@ -109,11 +122,27 @@ export interface Props<TItem = any> {
|
|
|
109
122
|
showPagination?: boolean;
|
|
110
123
|
/** Show per-page selector */
|
|
111
124
|
showPerPageSelector?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Show the footer's item-count caption ("N items." / "X to Y out of Z
|
|
127
|
+
* items."). Defaults to `true`. Set `false` to suppress just the caption,
|
|
128
|
+
* independent of the pager — a page ported from a plain `<b-table>` that
|
|
129
|
+
* hides the pager with `:show-pagination="false"` would otherwise gain a
|
|
130
|
+
* caption it never had (#127).
|
|
131
|
+
*/
|
|
132
|
+
showCount?: boolean;
|
|
112
133
|
/** Per-page options for selector */
|
|
113
134
|
perPageOptions?: number[];
|
|
114
135
|
/** Current page (for provider mode) */
|
|
115
136
|
currentPage?: number;
|
|
116
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* Items per page. With a `v-model:per-page` it is controlled state; a bare
|
|
139
|
+
* `:per-page="20"` is the INITIAL page size (see the initial-value vs
|
|
140
|
+
* controlled note above). When passed explicitly it takes PRECEDENCE over any
|
|
141
|
+
* per-page preference persisted in localStorage — `:per-page="20"` always
|
|
142
|
+
* starts at 20, never a size the user once picked on another table (#124).
|
|
143
|
+
* Omit it to let a stored preference (URL-keyed tables only) or the default
|
|
144
|
+
* apply.
|
|
145
|
+
*/
|
|
117
146
|
perPage?: number;
|
|
118
147
|
/** Striped (banded) rows. Off by default — banding adds little on short
|
|
119
148
|
* tables and can read as noise; opt in with `:striped="true"`. */
|
|
@@ -217,6 +246,15 @@ export interface Props<TItem = any> {
|
|
|
217
246
|
rowClickable?: (item: TItem, index: number) => boolean;
|
|
218
247
|
/** Enable client-side filtering, sorting, and pagination on items array */
|
|
219
248
|
clientSide?: boolean;
|
|
249
|
+
/**
|
|
250
|
+
* Apply `table-layout: fixed` to the underlying table. Off by default, so
|
|
251
|
+
* existing tables keep their content-sized columns. When on, column widths
|
|
252
|
+
* stop depending on cell content, so they no longer reshuffle when a filter
|
|
253
|
+
* narrows the rows — the table stays put as you filter (#156). Combine with
|
|
254
|
+
* per-field `width`/`minWidth` to control the proportions; columns with no
|
|
255
|
+
* declared width share the remaining space equally.
|
|
256
|
+
*/
|
|
257
|
+
fixedLayout?: boolean;
|
|
220
258
|
}
|
|
221
259
|
declare const _default: <T = any>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
222
260
|
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{
|
|
@@ -10,6 +10,8 @@ interface Props {
|
|
|
10
10
|
showPagination: boolean;
|
|
11
11
|
/** Whether to render the per-page selector. */
|
|
12
12
|
showPerPageSelector: boolean;
|
|
13
|
+
/** Whether to render the item-count caption (the "X out of Z items" line). */
|
|
14
|
+
showCount: boolean;
|
|
13
15
|
/** Singular item noun for the info line (e.g. "product"). */
|
|
14
16
|
singularItemName: string;
|
|
15
17
|
/** Plural item noun for the info line (e.g. "products"). */
|