@omnitend/dashboard-for-laravel 0.41.2 → 0.42.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/README.md +2 -1
- package/dist/assets/MavenPro-Bold-35b16f06.woff2 +0 -0
- package/dist/assets/MavenPro-Medium-febc8674.woff2 +0 -0
- package/dist/assets/MavenPro-Regular-aee3df9e.woff2 +0 -0
- package/dist/assets/MavenPro-SemiBold-c555dbfa.woff2 +0 -0
- package/dist/assets/Poppins-Medium-5800fa57.woff2 +0 -0
- package/dist/assets/Poppins-SemiBold-94a36267.woff2 +0 -0
- package/dist/charts.js +148 -130
- package/dist/charts.js.map +1 -1
- package/dist/charts.umd.cjs +1 -1
- package/dist/charts.umd.cjs.map +1 -1
- package/dist/components/charts/chartTheme.d.ts +14 -2
- package/dist/components/extended/DXField.vue.d.ts +16 -5
- package/dist/components/extended/DXForm.vue.d.ts +25 -9
- package/dist/components/extended/DXNumberStepper.vue.d.ts +33 -0
- package/dist/components/extended/DXSaveButton.vue.d.ts +38 -0
- package/dist/components/extended/DXTable.vue.d.ts +6 -2
- package/dist/composables/useForm.d.ts +7 -0
- package/dist/dashboard-for-laravel.js +9369 -9133
- 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 +2 -0
- package/dist/style.css +2 -2
- package/dist/types/index.d.ts +20 -3
- package/docs/public/api-reference.json +165 -14
- package/docs/public/docs-map.md +4 -2
- package/docs/public/llms.txt +4 -2
- package/package.json +1 -1
- package/resources/css/theme.scss +512 -89
- package/resources/fonts/maven-pro/MavenPro-Bold.woff2 +0 -0
- package/resources/fonts/maven-pro/MavenPro-Medium.woff2 +0 -0
- package/resources/fonts/maven-pro/MavenPro-Regular.woff2 +0 -0
- package/resources/fonts/maven-pro/MavenPro-SemiBold.woff2 +0 -0
- package/resources/fonts/maven-pro/OFL.txt +93 -0
- package/resources/fonts/poppins/OFL.txt +93 -0
- package/resources/fonts/poppins/Poppins-Medium.woff2 +0 -0
- package/resources/fonts/poppins/Poppins-SemiBold.woff2 +0 -0
- package/resources/js/components/charts/DXBarChart.vue +2 -1
- package/resources/js/components/charts/DXDoughnutChart.vue +2 -1
- package/resources/js/components/charts/DXLineChart.vue +2 -1
- package/resources/js/components/charts/chartTheme.ts +68 -21
- package/resources/js/components/extended/DXDashboard.vue +4 -2
- package/resources/js/components/extended/DXDashboardSidebar.vue +52 -20
- package/resources/js/components/extended/DXField.vue +59 -28
- package/resources/js/components/extended/DXForm.vue +122 -21
- package/resources/js/components/extended/DXNumberStepper.vue +243 -0
- package/resources/js/components/extended/DXSaveButton.vue +82 -0
- package/resources/js/components/extended/DXTable.vue +44 -15
- package/resources/js/composables/useForm.ts +11 -0
- package/resources/js/composables/useToast.ts +1 -1
- package/resources/js/index.ts +2 -0
- package/resources/js/types/index.ts +21 -3
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2011 The Maven Pro Project Authors (http://www.vissol.co.uk/mavenpro/), with Reserved Font Name "Maven Pro".
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component
|
|
3
3
|
A themed bar chart. Thin wrapper around vue-chartjs (chart.js) with the
|
|
4
|
-
theme's dedicated chart palette (--dx-chart-1..8
|
|
4
|
+
theme's dedicated chart palette (--dx-chart-1..8 fills, a 1px --dx-chart-edge outline) applied
|
|
5
|
+
and dashboard-friendly defaults (no x gridlines,
|
|
5
6
|
formatted value ticks, responsive, legend hidden for a single series). Pass
|
|
6
7
|
`labels` + `datasets`; `options` deep-merges over the defaults.
|
|
7
8
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component
|
|
3
3
|
A themed doughnut chart. Thin wrapper around vue-chartjs (chart.js) with one
|
|
4
|
-
chart-palette colour (--dx-chart-1..8) per slice
|
|
4
|
+
chart-palette colour (--dx-chart-1..8) per slice, a 1px --dx-chart-edge outline, and
|
|
5
|
+
dashboard-friendly defaults. Pass
|
|
5
6
|
`labels` + either `data` (a number array) or full `datasets`; `options`
|
|
6
7
|
deep-merges over the defaults.
|
|
7
8
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component
|
|
3
3
|
A themed line chart. Thin wrapper around vue-chartjs (chart.js) with the
|
|
4
|
-
theme's dedicated chart palette applied (--dx-chart-1..8 stroke
|
|
4
|
+
theme's dedicated chart palette applied (--dx-chart-line-1..8 stroke and point outline,
|
|
5
|
+
--dx-chart-1..8 point centre and translucent area fill, smoothed line)
|
|
5
6
|
and dashboard-friendly defaults. Pass `labels` + `datasets`; `options`
|
|
6
7
|
deep-merges over the defaults.
|
|
7
8
|
|
|
@@ -42,24 +42,42 @@ export function registerCharts(): void {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// The dedicated data-viz palette (`$dx-chart-palette` in theme.scss) — eight
|
|
45
|
-
// vivid
|
|
46
|
-
// Deliberately NOT the semantic --bs-* colours
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
// that parses the Sass source (charts.test.ts), which is why this is exported.
|
|
45
|
+
// light, vivid fills in a fixed, CVD-validated order, published as
|
|
46
|
+
// --dx-chart-1..8. Deliberately NOT read from the semantic --bs-* colours
|
|
47
|
+
// (#141). Fallbacks mirror the shipped theme so charts still render without
|
|
48
|
+
// the CSS (SSR / tests / a consumer who didn't import it). Sync with
|
|
49
|
+
// theme.scss is enforced by a test that parses the Sass source
|
|
50
|
+
// (charts.test.ts), which is why these lists are exported.
|
|
52
51
|
export const PALETTE_VARS: Array<[string, string]> = [
|
|
53
|
-
["--dx-chart-1", "#
|
|
54
|
-
["--dx-chart-2", "#
|
|
55
|
-
["--dx-chart-3", "#
|
|
56
|
-
["--dx-chart-4", "#
|
|
57
|
-
["--dx-chart-5", "#
|
|
58
|
-
["--dx-chart-6", "#
|
|
59
|
-
["--dx-chart-7", "#
|
|
60
|
-
["--dx-chart-8", "#
|
|
52
|
+
["--dx-chart-1", "#7fd7fd"], // sky
|
|
53
|
+
["--dx-chart-2", "#7bf25a"], // lime
|
|
54
|
+
["--dx-chart-3", "#e46ab9"], // magenta
|
|
55
|
+
["--dx-chart-4", "#d6e86a"], // lime-yellow
|
|
56
|
+
["--dx-chart-5", "#b9a3f0"], // lavender
|
|
57
|
+
["--dx-chart-6", "#efd574"], // butter
|
|
58
|
+
["--dx-chart-7", "#9fb4ff"], // periwinkle
|
|
59
|
+
["--dx-chart-8", "#f7a072"], // peach
|
|
61
60
|
];
|
|
62
61
|
|
|
62
|
+
// The line/point shade for each slot (`$dx-chart-line-palette`): the fill
|
|
63
|
+
// darkened to 3.5:1 on white, so a line stroke or point outline clears WCAG
|
|
64
|
+
// 1.4.11 non-text contrast where the light fill alone would not. Same order.
|
|
65
|
+
export const LINE_PALETTE_VARS: Array<[string, string]> = [
|
|
66
|
+
["--dx-chart-line-1", "#5590aa"],
|
|
67
|
+
["--dx-chart-line-2", "#4d9839"],
|
|
68
|
+
["--dx-chart-line-3", "#d161a9"],
|
|
69
|
+
["--dx-chart-line-4", "#848f41"],
|
|
70
|
+
["--dx-chart-line-5", "#907fbb"],
|
|
71
|
+
["--dx-chart-line-6", "#99884a"],
|
|
72
|
+
["--dx-chart-line-7", "#7686be"],
|
|
73
|
+
["--dx-chart-line-8", "#ba7956"],
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
// The 1px outline on bars and doughnut segments (`$dx-chart-edge`): it carries
|
|
77
|
+
// the non-text contrast for the light fills. Dark mode remaps it to the dark
|
|
78
|
+
// body colour.
|
|
79
|
+
export const EDGE_VAR: [string, string] = ["--dx-chart-edge", "#121419"];
|
|
80
|
+
|
|
63
81
|
/**
|
|
64
82
|
* The element whose computed style the theme variables are read from.
|
|
65
83
|
*
|
|
@@ -86,12 +104,29 @@ function themeScope(scope?: Element | null): Element | null {
|
|
|
86
104
|
* backward compatible.
|
|
87
105
|
*/
|
|
88
106
|
export function getPalette(scope?: Element | null): string[] {
|
|
107
|
+
return resolveVars(PALETTE_VARS, scope);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolve the themed line/point shades (`--dx-chart-line-1..8`), slot for slot
|
|
112
|
+
* with getPalette(). Same scope rules as getPalette().
|
|
113
|
+
*/
|
|
114
|
+
export function getLinePalette(scope?: Element | null): string[] {
|
|
115
|
+
return resolveVars(LINE_PALETTE_VARS, scope);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Resolve the bar/segment edge colour (`--dx-chart-edge`). */
|
|
119
|
+
export function getEdgeColor(scope?: Element | null): string {
|
|
120
|
+
return resolveVars([EDGE_VAR], scope)[0];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function resolveVars(vars: Array<[string, string]>, scope?: Element | null): string[] {
|
|
89
124
|
const host = themeScope(scope);
|
|
90
125
|
if (host === null) {
|
|
91
|
-
return
|
|
126
|
+
return vars.map(([, fallback]) => fallback);
|
|
92
127
|
}
|
|
93
128
|
const styles = getComputedStyle(host);
|
|
94
|
-
return
|
|
129
|
+
return vars.map(([name, fallback]) => {
|
|
95
130
|
const value = styles.getPropertyValue(name).trim();
|
|
96
131
|
return value || fallback;
|
|
97
132
|
});
|
|
@@ -273,8 +308,11 @@ export function baseOptions(args: BaseOptionArgs): Record<string, any> {
|
|
|
273
308
|
|
|
274
309
|
/**
|
|
275
310
|
* Apply the themed palette to any dataset that doesn't set its own colours.
|
|
276
|
-
*
|
|
277
|
-
*
|
|
311
|
+
* Each property is filled in only when the caller left it undefined.
|
|
312
|
+
* Bar: one fill per dataset (or per bar for a single dataset), with a 1px
|
|
313
|
+
* edge outline. Line: the slot's darker line shade for the stroke and point
|
|
314
|
+
* outlines, the fill for point centres, and a 35% fill wash under the line.
|
|
315
|
+
* Doughnut/pie: one fill per slice, with a 1px edge outline.
|
|
278
316
|
*
|
|
279
317
|
* `scope` is the chart's container element; the palette is resolved from its
|
|
280
318
|
* computed style so a nested `data-bs-theme` container themes correctly (#161).
|
|
@@ -287,11 +325,14 @@ export function applyPalette(
|
|
|
287
325
|
scope?: Element | null,
|
|
288
326
|
): any[] {
|
|
289
327
|
const palette = getPalette(scope);
|
|
328
|
+
const linePalette = getLinePalette(scope);
|
|
329
|
+
const edge = getEdgeColor(scope);
|
|
290
330
|
const single = datasets.length === 1;
|
|
291
331
|
|
|
292
332
|
return datasets.map((dataset, index) => {
|
|
293
333
|
const next = { ...dataset };
|
|
294
334
|
const color = palette[index % palette.length];
|
|
335
|
+
const lineColor = linePalette[index % linePalette.length];
|
|
295
336
|
|
|
296
337
|
if (kind === "doughnut") {
|
|
297
338
|
if (next.backgroundColor === undefined) {
|
|
@@ -300,14 +341,18 @@ export function applyPalette(
|
|
|
300
341
|
(_, i) => palette[i % palette.length],
|
|
301
342
|
);
|
|
302
343
|
}
|
|
344
|
+
if (next.borderColor === undefined) next.borderColor = edge;
|
|
345
|
+
if (next.borderWidth === undefined) next.borderWidth = 1;
|
|
303
346
|
return next;
|
|
304
347
|
}
|
|
305
348
|
|
|
306
349
|
if (kind === "line") {
|
|
307
|
-
if (next.borderColor === undefined) next.borderColor =
|
|
350
|
+
if (next.borderColor === undefined) next.borderColor = lineColor;
|
|
308
351
|
if (next.backgroundColor === undefined) {
|
|
309
|
-
next.backgroundColor = withAlpha(color, 0.
|
|
352
|
+
next.backgroundColor = withAlpha(color, 0.35);
|
|
310
353
|
}
|
|
354
|
+
if (next.pointBackgroundColor === undefined) next.pointBackgroundColor = color;
|
|
355
|
+
if (next.pointBorderColor === undefined) next.pointBorderColor = lineColor;
|
|
311
356
|
if (next.tension === undefined) next.tension = 0.3;
|
|
312
357
|
if (next.fill === undefined) next.fill = true;
|
|
313
358
|
if (next.pointRadius === undefined) next.pointRadius = 2;
|
|
@@ -321,6 +366,8 @@ export function applyPalette(
|
|
|
321
366
|
? Array.from({ length: labelsCount }, () => color)
|
|
322
367
|
: color;
|
|
323
368
|
}
|
|
369
|
+
if (next.borderColor === undefined) next.borderColor = edge;
|
|
370
|
+
if (next.borderWidth === undefined) next.borderWidth = 1;
|
|
324
371
|
if (next.borderRadius === undefined) next.borderRadius = 4;
|
|
325
372
|
return next;
|
|
326
373
|
});
|
|
@@ -70,8 +70,10 @@
|
|
|
70
70
|
</template>
|
|
71
71
|
</DXDashboardNavbar>
|
|
72
72
|
|
|
73
|
-
<!-- Page Content
|
|
74
|
-
|
|
73
|
+
<!-- Page Content. Vertical padding only: the horizontal edge is the
|
|
74
|
+
shared dashboard gutter, applied to the container inside (see
|
|
75
|
+
`$dashboard-gutter-x` in theme.scss) so it matches the navbar's. -->
|
|
76
|
+
<main class="dashboard-main py-4">
|
|
75
77
|
<!-- Fluid: full-width, left-aligned content (for wide tables / admin
|
|
76
78
|
pages). Default: a centred reading-width column. -->
|
|
77
79
|
<DContainer v-if="fluid" fluid :class="contentClass">
|
|
@@ -213,34 +213,66 @@ const brandInitial = computed(() => {
|
|
|
213
213
|
const normalizeUrl = (url: string): string =>
|
|
214
214
|
url.toLowerCase().replace(/[?#].*$/, '').replace(/\/$/, '');
|
|
215
215
|
|
|
216
|
+
// An item's query parameters, lowercased, as [name, value] pairs.
|
|
217
|
+
const queryParams = (url: string): [string, string][] => {
|
|
218
|
+
const query = url.toLowerCase().split('#')[0].split('?')[1] ?? '';
|
|
219
|
+
return Array.from(new URLSearchParams(query).entries());
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// Identity of a nav item for matching: its path plus its query, so items that
|
|
223
|
+
// differ only by query string (`/tasks?business_unit_id=1`, `...=2`) are told
|
|
224
|
+
// apart.
|
|
225
|
+
const itemKey = (url: string): string =>
|
|
226
|
+
normalizeUrl(url) + '?' + queryParams(url).map(([name, value]) => `${name}=${value}`).sort().join('&');
|
|
227
|
+
|
|
216
228
|
/**
|
|
217
|
-
* The single best-matching nav item
|
|
218
|
-
* match
|
|
219
|
-
* `/rotas/507` activates the `/rotas` item. Root `/` only matches
|
|
220
|
-
* is a prefix of every path, so it is never treated as an
|
|
221
|
-
*
|
|
229
|
+
* The single best-matching nav item for the current route, as an `itemKey`.
|
|
230
|
+
* Paths first: an exact match, otherwise the longest ancestor path, so a detail
|
|
231
|
+
* page like `/rotas/507` activates the `/rotas` item. Root `/` only matches
|
|
232
|
+
* exactly — it is a prefix of every path, so it is never treated as an
|
|
233
|
+
* ancestor. Then, among items on that winning path, queries: an item whose
|
|
234
|
+
* query names parameters only matches when the current URL carries every one of
|
|
235
|
+
* them with the same value (extra current parameters such as `page` are fine),
|
|
236
|
+
* and the item naming the most such parameters wins. An item with no query
|
|
237
|
+
* matches whatever the current query is. If every item on the path names a
|
|
238
|
+
* query the current URL doesn't carry, nothing is active.
|
|
239
|
+
* Returns null if nothing matches.
|
|
222
240
|
*/
|
|
223
|
-
const
|
|
241
|
+
const activeKey = computed<string | null>(() => {
|
|
224
242
|
const current = normalizeUrl(props.currentUrl);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
243
|
+
const currentParams = new URLSearchParams(
|
|
244
|
+
props.currentUrl.toLowerCase().split('#')[0].split('?')[1] ?? '',
|
|
245
|
+
);
|
|
246
|
+
const items = props.navigation
|
|
247
|
+
.filter((group) => group.visible !== false)
|
|
248
|
+
.flatMap((group) => group.items.filter((item) => item.visible !== false));
|
|
249
|
+
|
|
250
|
+
let bestPath: string | null = null;
|
|
251
|
+
for (const item of items) {
|
|
252
|
+
const candidate = normalizeUrl(item.url);
|
|
253
|
+
const matches =
|
|
254
|
+
candidate === current ||
|
|
255
|
+
(candidate !== '' && current.startsWith(candidate + '/'));
|
|
256
|
+
if (matches && (bestPath === null || candidate.length > bestPath.length)) {
|
|
257
|
+
bestPath = candidate;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (bestPath === null) return null;
|
|
261
|
+
|
|
262
|
+
let best: { key: string; score: number } | null = null;
|
|
263
|
+
for (const item of items) {
|
|
264
|
+
if (normalizeUrl(item.url) !== bestPath) continue;
|
|
265
|
+
const params = queryParams(item.url);
|
|
266
|
+
const carried = params.every(([name, value]) => currentParams.getAll(name).includes(value));
|
|
267
|
+
if (carried && (best === null || params.length > best.score)) {
|
|
268
|
+
best = { key: itemKey(item.url), score: params.length };
|
|
237
269
|
}
|
|
238
270
|
}
|
|
239
|
-
return best;
|
|
271
|
+
return best?.key ?? null;
|
|
240
272
|
});
|
|
241
273
|
|
|
242
274
|
const isActive = (url: string): boolean =>
|
|
243
|
-
|
|
275
|
+
activeKey.value !== null && itemKey(url) === activeKey.value;
|
|
244
276
|
|
|
245
277
|
// Index of the group containing the active route (-1 if none).
|
|
246
278
|
const activeGroupIndex = computed(() =>
|
|
@@ -69,15 +69,30 @@
|
|
|
69
69
|
|
|
70
70
|
<!-- Custom value slot overrides the built-in control (checkbox / switch
|
|
71
71
|
/ standard types; not switch-list or repeater). -->
|
|
72
|
+
<!-- A `plaintext` field is display-only, so its value slot is wrapped
|
|
73
|
+
in `.dx-form-plaintext`: a badge or a line of text then shares
|
|
74
|
+
the label's centre line instead of sitting at the top of the row. -->
|
|
75
|
+
<div
|
|
76
|
+
v-if="showValueSlot && $slots.value && isPlaintext"
|
|
77
|
+
class="dx-form-plaintext"
|
|
78
|
+
>
|
|
79
|
+
<slot
|
|
80
|
+
name="value"
|
|
81
|
+
:field="field"
|
|
82
|
+
:model="model"
|
|
83
|
+
:value="fieldValue"
|
|
84
|
+
:update="setValue"
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
72
87
|
<!--
|
|
73
|
-
@slot Replaces the built-in control with a custom value editor.
|
|
88
|
+
@slot Replaces the built-in control with a custom value editor. On a `plaintext` field the content is wrapped in `.dx-form-plaintext` so display-only content lines up with the label.
|
|
74
89
|
@binding {FieldDefinition} field The field definition being rendered.
|
|
75
90
|
@binding {any} model The model passed to field predicates (defaults to the live form data).
|
|
76
91
|
@binding {any} value The current field value.
|
|
77
92
|
@binding {(value: any) => void} update Setter that writes the value back and clears the field's validation error.
|
|
78
93
|
-->
|
|
79
94
|
<slot
|
|
80
|
-
v-if="showValueSlot && $slots.value"
|
|
95
|
+
v-else-if="showValueSlot && $slots.value"
|
|
81
96
|
name="value"
|
|
82
97
|
:field="field"
|
|
83
98
|
:model="model"
|
|
@@ -154,7 +169,7 @@
|
|
|
154
169
|
>
|
|
155
170
|
<DFormGroup
|
|
156
171
|
v-bind="switchListRowAttrs"
|
|
157
|
-
class="mb-0
|
|
172
|
+
class="mb-0"
|
|
158
173
|
>
|
|
159
174
|
<template #label>
|
|
160
175
|
<DXFieldLabel
|
|
@@ -420,7 +435,11 @@ interface Props {
|
|
|
420
435
|
*/
|
|
421
436
|
layout?: "vertical" | "horizontal";
|
|
422
437
|
|
|
423
|
-
/**
|
|
438
|
+
/**
|
|
439
|
+
* Label column width for horizontal layout (mirrors BFormGroup's
|
|
440
|
+
* `labelCols`/`labelCols*`). Omitted: the label takes
|
|
441
|
+
* `--dx-form-label-width` (45%) from `sm` up and stacks below.
|
|
442
|
+
*/
|
|
424
443
|
labelCols?: LabelCols;
|
|
425
444
|
|
|
426
445
|
/**
|
|
@@ -487,23 +506,39 @@ function labelColsAttrs(cols: LabelCols | undefined): Record<string, any> {
|
|
|
487
506
|
return attrs;
|
|
488
507
|
}
|
|
489
508
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
509
|
+
/**
|
|
510
|
+
* BFormGroup attrs for a horizontal label column. With no `labelCols` from the
|
|
511
|
+
* caller (field or form), the label is `--dx-form-label-width` (45%) wide from
|
|
512
|
+
* `sm` up and stacks below: `labelColsSm: true` makes it a `col-sm` (so
|
|
513
|
+
* BFormGroup goes horizontal and stacks below `sm` like any breakpoint
|
|
514
|
+
* `labelCols`), and the `--default-width` modifier is what theme.scss sizes.
|
|
515
|
+
* The 45% falls between two 12-column steps, which is why it is CSS rather
|
|
516
|
+
* than a column count. An explicit `labelCols` goes through the grid unchanged.
|
|
517
|
+
*/
|
|
518
|
+
function labelColumnAttrs(cols: LabelCols | undefined): Record<string, any> {
|
|
519
|
+
// Right-align the label column so the label (and the hint that sits
|
|
520
|
+
// beneath it in horizontal layout) line up against the control column,
|
|
521
|
+
// like a classic label-left settings form.
|
|
522
|
+
const labelClass = "text-sm-end dx-field-label-col";
|
|
523
|
+
if (cols === undefined) {
|
|
524
|
+
return {
|
|
525
|
+
labelColsSm: true,
|
|
526
|
+
labelClass: `${labelClass} dx-field-label-col--default-width`,
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return { ...labelColsAttrs(cols), labelClass };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// `layout: "horizontal"` alone is enough to see the effect (the default label
|
|
533
|
+
// width above). When the field's label is hidden, reserve no label column at
|
|
534
|
+
// all — BFormGroup would otherwise still emit an empty label column (it goes
|
|
535
|
+
// horizontal whenever any labelCols are set, regardless of whether a label
|
|
536
|
+
// exists), leaving the control indented in the input column beside dead
|
|
537
|
+
// space. Dropping the column lets the control span full width, so a
|
|
538
|
+
// switch/checkbox self-label lines up with sibling row labels (#78).
|
|
498
539
|
const horizontalAttrs = computed<Record<string, any>>(() =>
|
|
499
540
|
isHorizontal.value && !props.hideLabel
|
|
500
|
-
?
|
|
501
|
-
...labelColsAttrs(props.labelCols ?? 3),
|
|
502
|
-
// Right-align the label column so the label (and the hint that
|
|
503
|
-
// sits beneath it in horizontal layout) line up against the
|
|
504
|
-
// control column, like a classic label-left settings form.
|
|
505
|
-
labelClass: "text-sm-end dx-field-label-col",
|
|
506
|
-
}
|
|
541
|
+
? labelColumnAttrs(props.labelCols)
|
|
507
542
|
: {},
|
|
508
543
|
);
|
|
509
544
|
|
|
@@ -667,12 +702,7 @@ const resolvedInfo = computed(() => resolveMaybe(props.field.info));
|
|
|
667
702
|
// FIELD label but would collapse every option row's label column too —
|
|
668
703
|
// `hideLabel` on a switch-list should drop only the section heading.
|
|
669
704
|
const switchListRowAttrs = computed<Record<string, any>>(() =>
|
|
670
|
-
isHorizontal.value
|
|
671
|
-
? {
|
|
672
|
-
...labelColsAttrs(props.labelCols ?? 3),
|
|
673
|
-
labelClass: "text-sm-end dx-field-label-col",
|
|
674
|
-
}
|
|
675
|
-
: {},
|
|
705
|
+
isHorizontal.value ? labelColumnAttrs(props.labelCols) : {},
|
|
676
706
|
);
|
|
677
707
|
|
|
678
708
|
// The model is an array of selected option values, exactly like
|
|
@@ -864,9 +894,10 @@ onBeforeUnmount(() => {
|
|
|
864
894
|
|
|
865
895
|
<style scoped>
|
|
866
896
|
/* Switch-list rows (#160): compact rhythm with a divider between rows. The
|
|
867
|
-
vertical centring of label
|
|
868
|
-
|
|
869
|
-
|
|
897
|
+
vertical centring of label, switch and trailing control is a global
|
|
898
|
+
`.dx-switch-list-row .row` rule in theme.scss: the `.row` is inside
|
|
899
|
+
bootstrap-vue-next's BFormGroup wrapper, so a class on the DFormGroup
|
|
900
|
+
lands on the wrapper, not the row. */
|
|
870
901
|
.dx-switch-list-row {
|
|
871
902
|
padding: 0.25rem 0;
|
|
872
903
|
border-bottom: 1px solid var(--bs-border-color);
|