@ulu/frontend-vue 0.1.0-beta.9 → 0.1.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{breakpoints-BbkGNxxt.js → breakpoints-DM-CBTtb.js} +1 -1
- package/dist/frontend-vue.css +1 -1
- package/dist/frontend-vue.js +79 -68
- package/dist/index-BNRZ3Apw.js +7541 -0
- package/lib/components/collapsible/UluAccordion.vue +71 -53
- package/lib/components/collapsible/UluAccordionGroup.vue +54 -0
- package/lib/components/collapsible/UluCollapsible.vue +144 -0
- package/lib/components/collapsible/UluDropdown.vue +29 -29
- package/lib/components/collapsible/UluOverflowPopover.vue +1 -1
- package/lib/components/elements/UluBadge.vue +51 -28
- package/lib/components/elements/UluBadgeStack.vue +8 -13
- package/lib/components/elements/UluButtonVerbose.vue +119 -0
- package/lib/components/elements/UluCard.vue +1 -1
- package/lib/components/elements/UluDefinitionList.vue +14 -17
- package/lib/components/elements/UluExternalLink.vue +21 -27
- package/lib/components/elements/UluIcon.vue +11 -1
- package/lib/components/elements/UluList.vue +53 -55
- package/lib/components/elements/UluSpokeSpinner.vue +12 -18
- package/lib/components/elements/UluTag.vue +35 -35
- package/lib/components/forms/UluFileDisplay.vue +49 -31
- package/lib/components/forms/UluFormFile.vue +37 -24
- package/lib/components/forms/UluFormMessage.vue +13 -10
- package/lib/components/forms/UluFormSelect.vue +28 -16
- package/lib/components/forms/UluFormText.vue +24 -15
- package/lib/components/forms/UluSearchForm.vue +11 -10
- package/lib/components/forms/UluSelectableMenu.vue +99 -0
- package/lib/components/index.js +4 -3
- package/lib/components/layout/UluTitleRail.vue +18 -0
- package/lib/components/layout/UluWhenBreakpoint.vue +9 -0
- package/lib/components/navigation/UluBreadcrumb.vue +9 -2
- package/lib/components/navigation/UluMenu.vue +8 -3
- package/lib/components/navigation/UluMenuStack.vue +3 -1
- package/lib/components/navigation/UluPager.vue +102 -0
- package/lib/components/systems/facets/ExampleFacetsWithPagination.vue +119 -0
- package/lib/components/systems/facets/UluFacetsFilterLists.vue +91 -0
- package/lib/components/systems/facets/UluFacetsFilterPopovers.vue +125 -0
- package/lib/components/systems/facets/UluFacetsFilterSelects.vue +71 -0
- package/lib/components/systems/facets/UluFacetsHeaderLayout.vue +24 -0
- package/lib/components/systems/facets/UluFacetsList.vue +62 -34
- package/lib/components/systems/facets/UluFacetsResults.vue +63 -0
- package/lib/components/systems/facets/UluFacetsSearch.vue +27 -50
- package/lib/components/systems/facets/UluFacetsSidebarLayout.vue +70 -0
- package/lib/components/systems/facets/UluFacetsSort.vue +45 -0
- package/lib/components/systems/facets/_facets.scss +2 -3
- package/lib/components/systems/facets/_mock-data.js +40 -0
- package/lib/components/systems/facets/useFacets.js +268 -0
- package/lib/components/systems/index.js +13 -2
- package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +2 -1
- package/lib/components/systems/skeleton/UluShowSkeleton.vue +9 -8
- package/lib/components/systems/skeleton/UluSkeletonContent.vue +39 -43
- package/lib/components/systems/skeleton/UluSkeletonMedia.vue +4 -6
- package/lib/components/systems/skeleton/UluSkeletonText.vue +27 -0
- package/lib/components/systems/slider/UluImageSlideShow.vue +1 -1
- package/lib/components/systems/slider/UluSlideShow.vue +8 -3
- package/lib/components/systems/table-sticky/UluTableSticky.vue +7 -7
- package/lib/components/systems/table-sticky/UluTableStickyTable.vue +3 -3
- package/lib/components/visualizations/UluAnimateNumber.vue +7 -1
- package/lib/components/visualizations/UluProgressBar.vue +99 -68
- package/lib/components/visualizations/UluProgressCircle.vue +146 -0
- package/lib/components/visualizations/progress-bar-examples.html +175 -0
- package/lib/composables/index.js +3 -1
- package/lib/composables/useDocumentTitle.js +61 -0
- package/lib/composables/usePagination.js +122 -0
- package/lib/index.js +1 -0
- package/lib/plugins/core/index.js +6 -1
- package/lib/plugins/popovers/UluPopover.vue +8 -3
- package/lib/plugins/toast/UluToast.vue +1 -1
- package/lib/plugins/toast/UluToastDisplay.vue +19 -2
- package/lib/utils/dom.js +12 -0
- package/lib/utils/index.js +2 -0
- package/lib/utils/{vue-router.js → router.js} +114 -30
- package/package.json +17 -11
- package/types/components/systems/facets/_mock-data.d.ts +18 -0
- package/types/components/systems/facets/_mock-data.d.ts.map +1 -0
- package/types/components/systems/facets/useFacets.d.ts +39 -0
- package/types/components/systems/facets/useFacets.d.ts.map +1 -0
- package/types/components/systems/index.d.ts +1 -1
- package/types/composables/index.d.ts +2 -0
- package/types/composables/useDocumentTitle.d.ts +22 -0
- package/types/composables/useDocumentTitle.d.ts.map +1 -0
- package/types/composables/usePageTitle.d.ts +19 -0
- package/types/composables/usePageTitle.d.ts.map +1 -0
- package/types/composables/usePagination.d.ts +25 -0
- package/types/composables/usePagination.d.ts.map +1 -0
- package/types/index.d.ts +1 -0
- package/types/plugins/core/index.d.ts.map +1 -1
- package/types/utils/dom.d.ts +1 -0
- package/types/utils/dom.d.ts.map +1 -1
- package/types/utils/index.d.ts +3 -0
- package/types/utils/index.d.ts.map +1 -0
- package/types/utils/router.d.ts +144 -0
- package/types/utils/router.d.ts.map +1 -0
- package/dist/index-D3Uc6T5M.js +0 -6469
- package/lib/components/collapsible/UluCollapsibleRegion.vue +0 -278
- package/lib/components/forms/UluCheckboxMenu.vue +0 -36
- package/lib/components/systems/facets/UluFacets.vue +0 -380
- package/lib/components/systems/skeleton/UluSkeletonTextInline.vue +0 -9
- package/lib/components/visualizations/UluProgressDonut.vue +0 -97
- package/lib/utils/placeholder.js +0 -6
|
@@ -1,46 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
class="progress-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}"
|
|
9
|
-
>
|
|
10
|
-
<div class="progress-bar__header">
|
|
11
|
-
<strong
|
|
12
|
-
class="progress-bar__label"
|
|
13
|
-
:class="{
|
|
14
|
-
'type-normal' : small,
|
|
15
|
-
'hidden-visually' : labelHidden,
|
|
16
|
-
}"
|
|
2
|
+
<div :class="componentClasses">
|
|
3
|
+
<div v-if="label || $slots.icon" class="progress-bar__header">
|
|
4
|
+
<strong
|
|
5
|
+
v-if="label"
|
|
6
|
+
class="progress-bar__label"
|
|
7
|
+
:class="{ 'hidden-visually': labelHidden }"
|
|
17
8
|
>
|
|
18
9
|
{{ label }}
|
|
19
10
|
</strong>
|
|
20
|
-
<div v-if="
|
|
21
|
-
<
|
|
22
|
-
<span class="hidden-visually">{{ status.message }}</span>
|
|
11
|
+
<div v-if="$slots.icon" class="progress-bar__icon">
|
|
12
|
+
<slot name="icon" />
|
|
23
13
|
</div>
|
|
24
14
|
</div>
|
|
25
15
|
<div class="progress-bar__track">
|
|
26
|
-
<div
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
></div>
|
|
30
|
-
<div
|
|
31
|
-
v-if="deficit"
|
|
16
|
+
<div class="progress-bar__bar" :style="{ width: barWidth }"></div>
|
|
17
|
+
<div
|
|
18
|
+
v-if="deficit > 0"
|
|
32
19
|
class="progress-bar__bar--deficit"
|
|
33
|
-
:style="
|
|
20
|
+
:style="{ width: deficitBarWidth }"
|
|
34
21
|
></div>
|
|
35
22
|
</div>
|
|
36
|
-
<div class="progress-bar__values">
|
|
23
|
+
<div v-if="!loader && !indeterminate" class="progress-bar__values">
|
|
37
24
|
<div class="progress-bar__value progress-bar__value--amount">
|
|
38
25
|
<strong class="hidden-visually">Amount:</strong>
|
|
39
26
|
{{ amount }}
|
|
40
27
|
</div>
|
|
41
|
-
<div
|
|
42
|
-
v-if="deficit > 0"
|
|
43
|
-
class="progress-bar__value progress-bar__value--deficit
|
|
28
|
+
<div
|
|
29
|
+
v-if="deficit > 0"
|
|
30
|
+
class="progress-bar__value progress-bar__value--deficit"
|
|
44
31
|
>
|
|
45
32
|
<strong class="hidden-visually">Deficit: </strong>
|
|
46
33
|
-{{ deficit }}
|
|
@@ -53,42 +40,86 @@
|
|
|
53
40
|
</div>
|
|
54
41
|
</template>
|
|
55
42
|
|
|
56
|
-
<script>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
43
|
+
<script setup>
|
|
44
|
+
import { computed } from "vue";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A linear progress bar to display progress, with support for various styles and a deficit indicator.
|
|
48
|
+
* @slot icon - A slot for placing an icon in the header, typically to indicate status.
|
|
49
|
+
*/
|
|
50
|
+
const props = defineProps({
|
|
51
|
+
/**
|
|
52
|
+
* The label to display above the progress bar.
|
|
53
|
+
*/
|
|
54
|
+
label: String,
|
|
55
|
+
/**
|
|
56
|
+
* Hides the label visually, but keeps it for screen readers.
|
|
57
|
+
*/
|
|
58
|
+
labelHidden: Boolean,
|
|
59
|
+
/**
|
|
60
|
+
* The current amount of progress.
|
|
61
|
+
*/
|
|
62
|
+
amount: {
|
|
63
|
+
type: Number,
|
|
64
|
+
default: 0,
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* The total amount that represents 100% progress.
|
|
68
|
+
*/
|
|
69
|
+
total: {
|
|
70
|
+
type: Number,
|
|
71
|
+
default: 100,
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* The amount of deficit to display on the bar.
|
|
75
|
+
*/
|
|
76
|
+
deficit: {
|
|
77
|
+
type: Number,
|
|
78
|
+
default: 0,
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Renders a smaller version of the progress bar.
|
|
82
|
+
*/
|
|
83
|
+
small: Boolean,
|
|
84
|
+
/**
|
|
85
|
+
* Applies the 'positive' style (e.g., green).
|
|
86
|
+
*/
|
|
87
|
+
positive: Boolean,
|
|
88
|
+
/**
|
|
89
|
+
* Applies the 'negative' style (e.g., red).
|
|
90
|
+
*/
|
|
91
|
+
negative: Boolean,
|
|
92
|
+
/**
|
|
93
|
+
* Applies styles for use as a thin loader.
|
|
94
|
+
*/
|
|
95
|
+
loader: Boolean,
|
|
96
|
+
/**
|
|
97
|
+
* Applies an indeterminate animation for unknown progress.
|
|
98
|
+
*/
|
|
99
|
+
indeterminate: Boolean,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const getCssPercentage = (amount, total) => {
|
|
103
|
+
const percent = total === 0 ? 0 : (amount / total) * 100;
|
|
104
|
+
return `${ percent }%`;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const barWidth = computed(() => {
|
|
108
|
+
if (props.indeterminate) return null; // No value for width
|
|
109
|
+
return getCssPercentage(props.amount, props.total);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const deficitBarWidth = computed(() => getCssPercentage(props.deficit, props.total));
|
|
113
|
+
|
|
114
|
+
const componentClasses = computed(() => {
|
|
115
|
+
return {
|
|
116
|
+
'progress-bar': true,
|
|
117
|
+
'progress-bar--small': props.small,
|
|
118
|
+
'progress-bar--positive': props.positive,
|
|
119
|
+
'progress-bar--negative': props.negative,
|
|
120
|
+
'progress-bar--loader': props.loader,
|
|
121
|
+
'progress-bar--indeterminate': props.indeterminate,
|
|
122
|
+
'type-small': props.small, // From original component, seems to control font size
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
</script>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="componentClasses">
|
|
3
|
+
<strong class="hidden-visually">{{ label }}</strong>
|
|
4
|
+
<div class="progress-circle__chart">
|
|
5
|
+
<svg class="progress-circle__chart-svg" viewBox="0 0 32 32">
|
|
6
|
+
<circle
|
|
7
|
+
class="progress-circle__chart-track"
|
|
8
|
+
r="16"
|
|
9
|
+
cx="16"
|
|
10
|
+
cy="16"
|
|
11
|
+
/>
|
|
12
|
+
<circle
|
|
13
|
+
class="progress-circle__chart-pie"
|
|
14
|
+
ref="pie"
|
|
15
|
+
r="16"
|
|
16
|
+
cx="16"
|
|
17
|
+
cy="16"
|
|
18
|
+
:style="{ strokeDasharray: endDasharray }"
|
|
19
|
+
/>
|
|
20
|
+
<circle
|
|
21
|
+
class="progress-circle__chart-mask"
|
|
22
|
+
cx="16"
|
|
23
|
+
cy="16"
|
|
24
|
+
/>
|
|
25
|
+
</svg>
|
|
26
|
+
<strong v-if="!showValueOutside" class="progress-circle__chart-value">
|
|
27
|
+
{{ percentage }}%
|
|
28
|
+
</strong>
|
|
29
|
+
</div>
|
|
30
|
+
<strong v-if="showValueOutside" class="progress-circle__value type-small-x">
|
|
31
|
+
{{ percentage }}%
|
|
32
|
+
</strong>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script>
|
|
37
|
+
/**
|
|
38
|
+
* A circular progress indicator component.
|
|
39
|
+
*/
|
|
40
|
+
export default {
|
|
41
|
+
name: 'UluProgressCircle',
|
|
42
|
+
props: {
|
|
43
|
+
/**
|
|
44
|
+
* The label for accessibility (visually hidden).
|
|
45
|
+
*/
|
|
46
|
+
label: {
|
|
47
|
+
type: String,
|
|
48
|
+
default: "Progress"
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* The progress percentage (0-100).
|
|
52
|
+
*/
|
|
53
|
+
percentage: {
|
|
54
|
+
type: Number,
|
|
55
|
+
default: 0
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* Renders a smaller version of the component.
|
|
59
|
+
*/
|
|
60
|
+
small: Boolean,
|
|
61
|
+
/**
|
|
62
|
+
* Displays the percentage value outside (to the side) of the circle.
|
|
63
|
+
*/
|
|
64
|
+
outside: Boolean,
|
|
65
|
+
/**
|
|
66
|
+
* Displays the percentage value below the circle.
|
|
67
|
+
*/
|
|
68
|
+
outsideBelow: Boolean,
|
|
69
|
+
/**
|
|
70
|
+
* Sets the status color of the progress circle (e.g., 'low', 'incomplete', 'complete').
|
|
71
|
+
*/
|
|
72
|
+
status: {
|
|
73
|
+
type: String,
|
|
74
|
+
default: ''
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Renders the component as a solid pie chart instead of a donut.
|
|
78
|
+
*/
|
|
79
|
+
pieStyle: Boolean,
|
|
80
|
+
/**
|
|
81
|
+
* Removes the center mask, filling the entire circle.
|
|
82
|
+
*/
|
|
83
|
+
noMask: Boolean,
|
|
84
|
+
/**
|
|
85
|
+
* The duration of the animation in milliseconds.
|
|
86
|
+
*/
|
|
87
|
+
duration: {
|
|
88
|
+
type: Number,
|
|
89
|
+
default: 1000 // Matches SCSS animation-duration
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* The easing function for the animation.
|
|
93
|
+
*/
|
|
94
|
+
easing: {
|
|
95
|
+
type: String,
|
|
96
|
+
default: "ease-in" // Matches SCSS animation-timing
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
watch: {
|
|
100
|
+
// Need to reanimate if value changes
|
|
101
|
+
percentage(newVal, oldVal) {
|
|
102
|
+
if (newVal !== oldVal) {
|
|
103
|
+
this.animate(this.normalize(oldVal));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
computed: {
|
|
108
|
+
endDasharray() {
|
|
109
|
+
return `${ this.normalize(this.percentage) } 100`;
|
|
110
|
+
},
|
|
111
|
+
showValueOutside() {
|
|
112
|
+
return this.outside || this.outsideBelow || this.small;
|
|
113
|
+
},
|
|
114
|
+
componentClasses() {
|
|
115
|
+
const classes = {
|
|
116
|
+
'progress-circle': true,
|
|
117
|
+
'progress-circle--small': this.small,
|
|
118
|
+
'progress-circle--pie': this.pieStyle,
|
|
119
|
+
'progress-circle--outside': this.showValueOutside,
|
|
120
|
+
'progress-circle--outside-below': this.outsideBelow,
|
|
121
|
+
'progress-circle--no-mask': this.noMask,
|
|
122
|
+
};
|
|
123
|
+
if (this.status) {
|
|
124
|
+
classes[`progress-circle--${this.status}`] = true;
|
|
125
|
+
}
|
|
126
|
+
return classes;
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
methods: {
|
|
130
|
+
normalize(percentage) {
|
|
131
|
+
// Added the 1% extra to 100% because sometimes it renders with a tiny gap
|
|
132
|
+
return percentage === 100 ? 101 : percentage;
|
|
133
|
+
},
|
|
134
|
+
animate(from = 0) {
|
|
135
|
+
const { pie } = this.$refs;
|
|
136
|
+
if (!pie || !pie.animate) return; // No Animation API or element not ready
|
|
137
|
+
const { duration, easing, endDasharray } = this;
|
|
138
|
+
const keyframes = { strokeDasharray: [`${ from } 100`, endDasharray] };
|
|
139
|
+
pie.animate(keyframes, { duration, easing, fill: "forwards" });
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
mounted() {
|
|
143
|
+
this.animate();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
</script>
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
|
|
2
|
+
<h2 class="h2">Basic Example</h2>
|
|
3
|
+
<p>The default progress bar has no modifiers.</p>
|
|
4
|
+
<div class="progress-bar">
|
|
5
|
+
<div class="progress-bar__header"><strong class="progress-bar__label">Label that is long test</strong>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="progress-bar__track">
|
|
8
|
+
<div class="progress-bar__bar" style="width: 40%;"></div>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="progress-bar__values">
|
|
11
|
+
<div class="progress-bar__value progress-bar__value--amount"><strong class="hidden-visually">Amount:</strong>
|
|
12
|
+
200</div>
|
|
13
|
+
<div class="progress-bar__value progress-bar__value--total"><strong class="hidden-visually">Total:</strong> 500
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="rule rule--light"></div>
|
|
19
|
+
|
|
20
|
+
<h2 class="h2">Indeterminate Modifier</h2>
|
|
21
|
+
<p>Uses the <code>.progress-bar--indeterminate</code> modifier for an animated loading state when the progress is unknown.</p>
|
|
22
|
+
<div class="progress-bar progress-bar--loader progress-bar--indeterminate">
|
|
23
|
+
<div class="progress-bar__track">
|
|
24
|
+
<div class="progress-bar__bar"></div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="rule rule--light"></div>
|
|
29
|
+
|
|
30
|
+
<h2 class="h2">Loader Style</h2>
|
|
31
|
+
<p>Uses the <code>.progress-bar--loader</code> modifier for a thin loading bar.</p>
|
|
32
|
+
<div class="progress-bar progress-bar--loader">
|
|
33
|
+
<div class="progress-bar__track">
|
|
34
|
+
<div class="progress-bar__bar" style="width: 65%;"></div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class="rule rule--light"></div>
|
|
40
|
+
|
|
41
|
+
<h2 class="h2">Completed Example</h2>
|
|
42
|
+
<p>An example of a completed progress bar with an icon.</p>
|
|
43
|
+
<div class="progress-bar">
|
|
44
|
+
<div class="progress-bar__header"><strong class="progress-bar__label">Progress</strong>
|
|
45
|
+
<div class="progress-bar__icon">
|
|
46
|
+
<span class="fas fa-check" aria-hidden="true"></span>
|
|
47
|
+
<span class="hidden-visually">Item Completed</span>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<div class="progress-bar__track">
|
|
51
|
+
<div class="progress-bar__bar" style="width: 100%;"></div>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="progress-bar__values">
|
|
54
|
+
<div class="progress-bar__value progress-bar__value--amount"><strong class="hidden-visually">Amount:</strong>
|
|
55
|
+
500</div>
|
|
56
|
+
<div class="progress-bar__value progress-bar__value--total"><strong class="hidden-visually">Total:</strong> 500
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="rule rule--light"></div>
|
|
62
|
+
|
|
63
|
+
<h2 class="h2">Deficit Example</h2>
|
|
64
|
+
<p>An example of a progress bar with a deficit.</p>
|
|
65
|
+
<div class="progress-bar">
|
|
66
|
+
<div class="progress-bar__header"><strong class="progress-bar__label">Progress</strong>
|
|
67
|
+
<div class="progress-bar__icon"><span class="fas fa-triangle-exclamation" aria-hidden="true"></span><span class="hidden-visually">Item Has Deficit</span></div>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="progress-bar__track">
|
|
70
|
+
<div class="progress-bar__bar" style="width: 60%;"></div>
|
|
71
|
+
<div class="progress-bar__bar progress-bar__bar--deficit" style="width: 20%;"></div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="progress-bar__values">
|
|
74
|
+
<div class="progress-bar__value progress-bar__value--amount"><strong class="hidden-visually">Amount:</strong>
|
|
75
|
+
300</div>
|
|
76
|
+
<div class="progress-bar__value progress-bar__value--deficit color-status is-danger"><strong
|
|
77
|
+
class="hidden-visually">Deficit: </strong> -100</div>
|
|
78
|
+
<div class="progress-bar__value progress-bar__value--total"><strong class="hidden-visually">Total:</strong> 500
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div class="rule rule--light"></div>
|
|
84
|
+
|
|
85
|
+
<h2 class="h2">Positive Style</h2>
|
|
86
|
+
<p>Uses the <code>.progress-bar--positive</code> modifier.</p>
|
|
87
|
+
<div class="progress-bar progress-bar--positive">
|
|
88
|
+
<div class="progress-bar__header"><strong class="progress-bar__label">Positive</strong></div>
|
|
89
|
+
<div class="progress-bar__track">
|
|
90
|
+
<div class="progress-bar__bar" style="width: 75%;"></div>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div class="rule rule--light"></div>
|
|
95
|
+
|
|
96
|
+
<h2 class="h2">Negative Style</h2>
|
|
97
|
+
<p>Uses the <code>.progress-bar--negative</code> modifier.</p>
|
|
98
|
+
<div class="progress-bar progress-bar--negative">
|
|
99
|
+
<div class="progress-bar__header"><strong class="progress-bar__label">Negative</strong></div>
|
|
100
|
+
<div class="progress-bar__track">
|
|
101
|
+
<div class="progress-bar__bar" style="width: 30%;"></div>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<div class="rule rule--light"></div>
|
|
106
|
+
|
|
107
|
+
<h2 class="h2">Small Modifier</h2>
|
|
108
|
+
<p>Uses the <code>.progress-bar--small</code> modifier. Font sizing is controlled by the parent element.</p>
|
|
109
|
+
<div class="progress-bar progress-bar--small progress-bar--positive type-small">
|
|
110
|
+
<div class="progress-bar__header"><strong class="progress-bar__label type-normal">Progress</strong>
|
|
111
|
+
<div class="progress-bar__icon">
|
|
112
|
+
<span class="fas fa-check" aria-hidden="true"></span>
|
|
113
|
+
<span class="hidden-visually">Item Completed</span>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="progress-bar__track">
|
|
117
|
+
<div class="progress-bar__bar" style="width: 100%;"></div>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="progress-bar__values">
|
|
120
|
+
<div class="progress-bar__value progress-bar__value--amount"><strong class="hidden-visually">Amount:</strong>
|
|
121
|
+
500</div>
|
|
122
|
+
<div class="progress-bar__value progress-bar__value--total"><strong class="hidden-visually">Total:</strong> 500
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div class="progress-bar progress-bar--small progress-bar--deficit type-small">
|
|
128
|
+
<div class="progress-bar__header"><strong class="progress-bar__label type-normal">Progress</strong>
|
|
129
|
+
<div class="progress-bar__icon"><span class="fas fa-triangle-exclamation" aria-hidden="true"></span><span class="hidden-visually">Item Has Deficit</span></div>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="progress-bar__track">
|
|
132
|
+
<div class="progress-bar__bar" style="width: 60%;"></div>
|
|
133
|
+
<div class="progress-bar__bar progress-bar__bar--deficit" style="width: 20%;"></div>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="progress-bar__values">
|
|
136
|
+
<div class="progress-bar__value progress-bar__value--amount"><strong class="hidden-visually">Amount:</strong>
|
|
137
|
+
300</div>
|
|
138
|
+
<div class="progress-bar__value progress-bar__value--deficit color-status is-danger"><strong
|
|
139
|
+
class="hidden-visually">Deficit: </strong> -100</div>
|
|
140
|
+
<div class="progress-bar__value progress-bar__value--total"><strong class="hidden-visually">Total:</strong> 500
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<div class="rule rule--light"></div>
|
|
146
|
+
|
|
147
|
+
<h2 class="h2">Icon left with rail</h2>
|
|
148
|
+
<p>Combining with rail component for icon on left</p>
|
|
149
|
+
|
|
150
|
+
<div class="progress-bar progress-bar--positive">
|
|
151
|
+
<div class="rail">
|
|
152
|
+
<div class="rail__item">
|
|
153
|
+
<div class="progress-bar__icon type-large">
|
|
154
|
+
<span class="fas fa-check" aria-hidden="true"></span>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
<div class="rail__item flex-grow">
|
|
158
|
+
<div class="progress-bar__header">
|
|
159
|
+
<strong class="progress-bar__label">Progress</strong>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="progress-bar__track">
|
|
162
|
+
<div class="progress-bar__bar" style="width: 100%;"></div>
|
|
163
|
+
</div>
|
|
164
|
+
<div class="progress-bar__values">
|
|
165
|
+
<div class="progress-bar__value progress-bar__value--amount"><strong class="hidden-visually">Amount:</strong>
|
|
166
|
+
300</div>
|
|
167
|
+
<div class="progress-bar__value progress-bar__value--deficit color-status is-danger"><strong
|
|
168
|
+
class="hidden-visually">Deficit: </strong> -100</div>
|
|
169
|
+
<div class="progress-bar__value progress-bar__value--total"><strong class="hidden-visually">Total:</strong> 500
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
|
package/lib/composables/index.js
CHANGED
|
@@ -8,4 +8,6 @@ export { useIcon } from './useIcon.js';
|
|
|
8
8
|
export { useModifiers } from './useModifiers.js';
|
|
9
9
|
export { useWindowResize } from './useWindowResize.js';
|
|
10
10
|
export { useRequiredInject } from './useRequiredInject.js';
|
|
11
|
-
export { useBreakpointManager } from './useBreakpointManager.js';
|
|
11
|
+
export { useBreakpointManager } from './useBreakpointManager.js';
|
|
12
|
+
export { usePagination } from './usePagination.js';
|
|
13
|
+
export { useDocumentTitle } from './useDocumentTitle.js';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { reactive, watchEffect, onUnmounted, unref, computed } from "vue";
|
|
2
|
+
import { useHead as defaultUseHead } from "@unhead/vue";
|
|
3
|
+
import { useRoute as defaultUseRoute } from "vue-router";
|
|
4
|
+
import { getRouteTitle } from "../utils/router.js";
|
|
5
|
+
|
|
6
|
+
// A reactive map to store component-defined titles.
|
|
7
|
+
const componentTitles = reactive({});
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A composable to manage the document title.
|
|
11
|
+
*
|
|
12
|
+
* When called with a `title` option, it sets a dynamic title for the current page.
|
|
13
|
+
* This is for use within specific components.
|
|
14
|
+
*
|
|
15
|
+
* When called without a `title` option (typically in App.vue), it manages the
|
|
16
|
+
* document title for the whole app, using titles from components or route meta.
|
|
17
|
+
*
|
|
18
|
+
* @param {object} options
|
|
19
|
+
* @param {import('vue').Ref<string> | string} [options.title] - The dynamic title to set for the current page.
|
|
20
|
+
* @param {string} [options.titleTemplate='%s'] - The template for the document title, e.g., '%s | My Site'.
|
|
21
|
+
* @param {Function} [options.useRoute=defaultUseRoute] - Injectable `useRoute` for testing.
|
|
22
|
+
* @param {Function} [options.useHead=defaultUseHead] - Injectable `useHead` for testing.
|
|
23
|
+
*/
|
|
24
|
+
export function useDocumentTitle(options = {}) {
|
|
25
|
+
const {
|
|
26
|
+
title,
|
|
27
|
+
titleTemplate = "%s",
|
|
28
|
+
useRoute = defaultUseRoute,
|
|
29
|
+
useHead = defaultUseHead,
|
|
30
|
+
} = options;
|
|
31
|
+
|
|
32
|
+
const route = useRoute();
|
|
33
|
+
const path = route.path;
|
|
34
|
+
|
|
35
|
+
// --- Setter Mode ---
|
|
36
|
+
// If a title is provided, we're in "setter" mode, used within a component.
|
|
37
|
+
if (title !== undefined) {
|
|
38
|
+
watchEffect(() => {
|
|
39
|
+
componentTitles[path] = unref(title);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
onUnmounted(() => {
|
|
43
|
+
delete componentTitles[path];
|
|
44
|
+
});
|
|
45
|
+
return; // End execution for setter mode.
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// --- Manager Mode ---
|
|
49
|
+
// If no title is provided, we're in "manager" mode, used in App.vue.
|
|
50
|
+
const documentTitle = computed(() => {
|
|
51
|
+
const titleFromComponent = componentTitles[route.path];
|
|
52
|
+
const titleFromMeta = getRouteTitle(route, route);
|
|
53
|
+
const resolvedTitle = titleFromComponent || titleFromMeta;
|
|
54
|
+
|
|
55
|
+
return resolvedTitle ? titleTemplate.replace("%s", resolvedTitle) : "App";
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
useHead({
|
|
59
|
+
title: documentTitle,
|
|
60
|
+
});
|
|
61
|
+
}
|