@ulu/frontend-vue 0.1.0-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/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/breakpoints-ClT9bfZm.js +211 -0
- package/dist/frontend-vue.css +1 -0
- package/dist/frontend-vue.js +82 -0
- package/dist/frontend-vue.umd.cjs +561 -0
- package/dist/index-P5Rwl_Dl.js +7263 -0
- package/dist/index.es-HlG3u0J5.js +3134 -0
- package/lib/_index.scss +14 -0
- package/lib/components/_index.scss +6 -0
- package/lib/components/collapsible/UluAccordion.vue +82 -0
- package/lib/components/collapsible/UluCollapsibleRegion.vue +278 -0
- package/lib/components/collapsible/UluDropdown.vue +42 -0
- package/lib/components/collapsible/UluModal.vue +384 -0
- package/lib/components/collapsible/UluOverflowPopover.vue +52 -0
- package/lib/components/collapsible/UluTab.vue +9 -0
- package/lib/components/collapsible/UluTabGroup.vue +31 -0
- package/lib/components/collapsible/UluTabList.vue +9 -0
- package/lib/components/collapsible/UluTabPanel.vue +9 -0
- package/lib/components/collapsible/UluTabPanels.vue +9 -0
- package/lib/components/elements/UluAlert.vue +81 -0
- package/lib/components/elements/UluBadge.vue +58 -0
- package/lib/components/elements/UluBadgeStack.vue +27 -0
- package/lib/components/elements/UluButton.vue +161 -0
- package/lib/components/elements/UluCallout.vue +30 -0
- package/lib/components/elements/UluCard.vue +241 -0
- package/lib/components/elements/UluDefinitionList.vue +40 -0
- package/lib/components/elements/UluExternalLink.vue +47 -0
- package/lib/components/elements/UluIcon.vue +108 -0
- package/lib/components/elements/UluList.vue +87 -0
- package/lib/components/elements/UluMain.vue +5 -0
- package/lib/components/elements/UluSpokeSpinner.vue +25 -0
- package/lib/components/elements/UluTag.vue +53 -0
- package/lib/components/forms/UluCheckboxMenu.vue +36 -0
- package/lib/components/forms/UluFileDisplay.vue +39 -0
- package/lib/components/forms/UluFormDropzone.vue +62 -0
- package/lib/components/forms/UluFormFile.vue +47 -0
- package/lib/components/forms/UluFormMessage.vue +20 -0
- package/lib/components/forms/UluFormSelect.vue +37 -0
- package/lib/components/forms/UluFormText.vue +32 -0
- package/lib/components/forms/UluSearchForm.vue +31 -0
- package/lib/components/index.js +54 -0
- package/lib/components/layout/UluAdaptiveLayout.vue +11 -0
- package/lib/components/layout/UluDataGrid.vue +41 -0
- package/lib/components/layout/UluTitleRail.vue +56 -0
- package/lib/components/layout/UluWhenBreakpoint.vue +86 -0
- package/lib/components/navigation/UluBreadcrumb.vue +72 -0
- package/lib/components/navigation/UluMenu.vue +105 -0
- package/lib/components/navigation/UluMenuStack.vue +49 -0
- package/lib/components/navigation/UluNavStrip.vue +48 -0
- package/lib/components/navigation/UluSkipLink.vue +5 -0
- package/lib/components/systems/facets/UluFacets.vue +380 -0
- package/lib/components/systems/facets/UluFacetsList.vue +39 -0
- package/lib/components/systems/facets/UluFacetsSearch.vue +67 -0
- package/lib/components/systems/facets/_facets.scss +64 -0
- package/lib/components/systems/index.js +17 -0
- package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +152 -0
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsNav.vue +37 -0
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue +124 -0
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsSection.vue +63 -0
- package/lib/components/systems/scroll-anchors/symbols.js +6 -0
- package/lib/components/systems/skeleton/UluShowSkeleton.vue +13 -0
- package/lib/components/systems/skeleton/UluSkeletonContent.vue +60 -0
- package/lib/components/systems/skeleton/UluSkeletonMedia.vue +11 -0
- package/lib/components/systems/skeleton/UluSkeletonTextInline.vue +9 -0
- package/lib/components/systems/slider/UluImageSlideShow.vue +75 -0
- package/lib/components/systems/slider/UluSlideShow.vue +331 -0
- package/lib/components/systems/slider/UluSlideShowSlide.vue +25 -0
- package/lib/components/systems/table-sticky/UluTableSticky.vue +793 -0
- package/lib/components/systems/table-sticky/UluTableStickyRows.vue +73 -0
- package/lib/components/systems/table-sticky/UluTableStickyTable.vue +237 -0
- package/lib/components/systems/table-sticky/_table-sticky.scss +185 -0
- package/lib/components/utils/UluCondText.vue +28 -0
- package/lib/components/utils/UluEmpty.vue +3 -0
- package/lib/components/utils/UluEmptyView.vue +3 -0
- package/lib/components/utils/UluPlaceholderImage.vue +53 -0
- package/lib/components/utils/UluPlaceholderText.vue +25 -0
- package/lib/components/utils/UluRouteAnnouncer.vue +83 -0
- package/lib/components/visualizations/UluAnimateNumber.vue +32 -0
- package/lib/components/visualizations/UluProgressBar.vue +94 -0
- package/lib/components/visualizations/UluProgressDonut.vue +97 -0
- package/lib/composables/index.js +10 -0
- package/lib/composables/useBreakpointManager.js +68 -0
- package/lib/composables/useIcon.js +62 -0
- package/lib/composables/useModifiers.js +93 -0
- package/lib/composables/useWindowResize.js +64 -0
- package/lib/index.js +10 -0
- package/lib/plugins/_index.scss +7 -0
- package/lib/plugins/breakpoints/index.js +47 -0
- package/lib/plugins/index.js +11 -0
- package/lib/plugins/modals/UluModalsDisplay.vue +59 -0
- package/lib/plugins/modals/api.js +76 -0
- package/lib/plugins/modals/index.js +60 -0
- package/lib/plugins/modals/useModals.js +9 -0
- package/lib/plugins/popovers/UluPopover.vue +189 -0
- package/lib/plugins/popovers/UluTooltipDisplay.vue +15 -0
- package/lib/plugins/popovers/UluTooltipPopover.vue +83 -0
- package/lib/plugins/popovers/defaults.js +108 -0
- package/lib/plugins/popovers/directive.js +95 -0
- package/lib/plugins/popovers/index.js +18 -0
- package/lib/plugins/popovers/manager.js +54 -0
- package/lib/plugins/popovers/useFollow.js +80 -0
- package/lib/plugins/popovers/utils.js +5 -0
- package/lib/plugins/toast/UluToast.vue +87 -0
- package/lib/plugins/toast/UluToastDisplay.vue +35 -0
- package/lib/plugins/toast/_toast.scss +198 -0
- package/lib/plugins/toast/defaults.js +30 -0
- package/lib/plugins/toast/index.js +17 -0
- package/lib/plugins/toast/store.js +71 -0
- package/lib/plugins/toast/useToast.js +18 -0
- package/lib/settings.js +119 -0
- package/lib/utils/dom.js +14 -0
- package/lib/utils/placeholder.js +6 -0
- package/lib/utils/vue-router.js +219 -0
- package/package.json +75 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="element"
|
|
4
|
+
class="button"
|
|
5
|
+
:class="[
|
|
6
|
+
{
|
|
7
|
+
'button--transparent' : transparent,
|
|
8
|
+
'button--primary' : primary,
|
|
9
|
+
'button--secondary' : secondary,
|
|
10
|
+
'button--outline' : outline,
|
|
11
|
+
'button--small' : small,
|
|
12
|
+
'button--large' : large,
|
|
13
|
+
'button--icon' : iconOnly,
|
|
14
|
+
'no-margin' : noMargin,
|
|
15
|
+
},
|
|
16
|
+
classes,
|
|
17
|
+
resolvedModifiers
|
|
18
|
+
]"
|
|
19
|
+
v-bind="attrs"
|
|
20
|
+
:aria-label="resolvedAriaLabel"
|
|
21
|
+
>
|
|
22
|
+
<slot name="before"/>
|
|
23
|
+
<UluIcon
|
|
24
|
+
v-if="icon && (iconBefore || iconOnly)"
|
|
25
|
+
:definition="icon"
|
|
26
|
+
class="button__icon"
|
|
27
|
+
/>
|
|
28
|
+
<span v-if="($slots.default || text) && !iconOnly">
|
|
29
|
+
<slot>
|
|
30
|
+
{{ text }}
|
|
31
|
+
</slot>
|
|
32
|
+
</span>
|
|
33
|
+
<UluIcon
|
|
34
|
+
v-if="icon && (!iconBefore && !iconOnly)"
|
|
35
|
+
:definition="icon"
|
|
36
|
+
class="button__icon"
|
|
37
|
+
/>
|
|
38
|
+
<slot name="after"/>
|
|
39
|
+
</component>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script>
|
|
43
|
+
import { RouterLink } from "vue-router";
|
|
44
|
+
import UluIcon from "./UluIcon.vue";
|
|
45
|
+
import { useModifiers } from "../../composables/useModifiers.js";
|
|
46
|
+
export default {
|
|
47
|
+
name: "UluButton",
|
|
48
|
+
components: {
|
|
49
|
+
UluIcon
|
|
50
|
+
},
|
|
51
|
+
props: {
|
|
52
|
+
/**
|
|
53
|
+
* Icon prop, if used will set the icon for the button, will use UluIcon (which uses font-awesome icons conditionally)
|
|
54
|
+
* - If using custom icons don't use this prop, use before or after slots with correct classes (ie .button__icon)
|
|
55
|
+
*/
|
|
56
|
+
icon: [String, Array],
|
|
57
|
+
/**
|
|
58
|
+
* If passing an icon (and not using iconOnly) this determines if the icon is before or after (default) the text
|
|
59
|
+
*/
|
|
60
|
+
iconBefore: Boolean,
|
|
61
|
+
/**
|
|
62
|
+
* Button style for only icon
|
|
63
|
+
*/
|
|
64
|
+
iconOnly: Boolean,
|
|
65
|
+
/**
|
|
66
|
+
* If set will use router-link for button component and pass to prop
|
|
67
|
+
*/
|
|
68
|
+
to: [String, Object],
|
|
69
|
+
/**
|
|
70
|
+
* Sets the button to a link with this href
|
|
71
|
+
*/
|
|
72
|
+
href: String,
|
|
73
|
+
/**
|
|
74
|
+
* Set a value for target attribute when button is a link
|
|
75
|
+
*/
|
|
76
|
+
target: String,
|
|
77
|
+
/**
|
|
78
|
+
* Sets the download attribute on the link (passing string [filename] will populate the download attribute, true will just include it as boolean attribute)
|
|
79
|
+
*/
|
|
80
|
+
download: [Boolean, String],
|
|
81
|
+
/**
|
|
82
|
+
* For icon only buttons or buttons that need an explicit label
|
|
83
|
+
*/
|
|
84
|
+
alt: String,
|
|
85
|
+
/**
|
|
86
|
+
* If not using slot this sets the buttons text via prop
|
|
87
|
+
*/
|
|
88
|
+
text: String,
|
|
89
|
+
/**
|
|
90
|
+
* Pass any sizes setup for button (ie. small, large, etc)
|
|
91
|
+
*/
|
|
92
|
+
size: String,
|
|
93
|
+
/**
|
|
94
|
+
* Preset to set primary style (needs to be a button style in ulu scss)
|
|
95
|
+
*/
|
|
96
|
+
primary: Boolean,
|
|
97
|
+
/**
|
|
98
|
+
* Preset to set secondary style (needs to be a button style in ulu scss)
|
|
99
|
+
*/
|
|
100
|
+
secondary: Boolean,
|
|
101
|
+
/**
|
|
102
|
+
* Preset to set small size (use "size" for any sizes)
|
|
103
|
+
*/
|
|
104
|
+
small: Boolean,
|
|
105
|
+
/**
|
|
106
|
+
* Preset to set large size (use "size" for any sizes)
|
|
107
|
+
*/
|
|
108
|
+
large: Boolean,
|
|
109
|
+
/**
|
|
110
|
+
* Preset to set outline style button (needs to be a button style in ulu scss)
|
|
111
|
+
*/
|
|
112
|
+
outline: Boolean,
|
|
113
|
+
/**
|
|
114
|
+
* Preset to set transparent style button (needs to be a button style in ulu scss)
|
|
115
|
+
*/
|
|
116
|
+
transparent: Boolean,
|
|
117
|
+
/**
|
|
118
|
+
* Add no-margin utility
|
|
119
|
+
*/
|
|
120
|
+
noMargin: Boolean,
|
|
121
|
+
/**
|
|
122
|
+
* Modifiers (to add any modifier classes based on base class [ie. 'tertiary'])
|
|
123
|
+
*/
|
|
124
|
+
modifiers: [String, Array]
|
|
125
|
+
},
|
|
126
|
+
setup(props) {
|
|
127
|
+
const { resolvedModifiers } = useModifiers({ props, baseClass: "button" });
|
|
128
|
+
return { resolvedModifiers };
|
|
129
|
+
},
|
|
130
|
+
computed: {
|
|
131
|
+
resolvedAriaLabel() {
|
|
132
|
+
const label = this.alt || this.iconOnly && this.text;
|
|
133
|
+
return label ? label : null;
|
|
134
|
+
},
|
|
135
|
+
classes() {
|
|
136
|
+
const classes = [];
|
|
137
|
+
const { size } = this;
|
|
138
|
+
if (size) {
|
|
139
|
+
classes.push(`button--${ size }`);
|
|
140
|
+
}
|
|
141
|
+
return classes;
|
|
142
|
+
},
|
|
143
|
+
element() {
|
|
144
|
+
return this.to ? RouterLink : this.href ? "a" : "button";
|
|
145
|
+
},
|
|
146
|
+
attrs() {
|
|
147
|
+
const { to, href, download, target } = this;
|
|
148
|
+
const attrs = to ? { to } : href ? { href } : {};
|
|
149
|
+
if (href) {
|
|
150
|
+
if (target) {
|
|
151
|
+
attrs.target = target;
|
|
152
|
+
}
|
|
153
|
+
if (download) {
|
|
154
|
+
attrs.download = typeof download === "string" ? download : true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return attrs;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="callout"
|
|
4
|
+
:class="[resolvedModifiers, { 'full-height' : fullHeight }]"
|
|
5
|
+
>
|
|
6
|
+
<slot/>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script>
|
|
11
|
+
import { useModifiers } from "../../composables/useModifiers.js";
|
|
12
|
+
export default {
|
|
13
|
+
name: "UluCallout",
|
|
14
|
+
props: {
|
|
15
|
+
/**
|
|
16
|
+
* Add full height utility class
|
|
17
|
+
*/
|
|
18
|
+
fullHeight: Boolean,
|
|
19
|
+
/**
|
|
20
|
+
* Class modifiers (ie. 'transparent', 'secondary', etc)
|
|
21
|
+
* - Can be String or Array of Strings
|
|
22
|
+
*/
|
|
23
|
+
modifiers: [String, Array]
|
|
24
|
+
},
|
|
25
|
+
setup(props) {
|
|
26
|
+
const { resolvedModifiers } = useModifiers({ props, baseClass: "callout" });
|
|
27
|
+
return { resolvedModifiers };
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
</script>
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
class="card"
|
|
4
|
+
:is="resolvedElement"
|
|
5
|
+
@mousedown="onMousedown"
|
|
6
|
+
@mouseup="onMouseup"
|
|
7
|
+
:class="[
|
|
8
|
+
{
|
|
9
|
+
'card--horizontal' : horizontal || horizontalCenter,
|
|
10
|
+
'card--horizontal-center' : horizontalCenter,
|
|
11
|
+
'card--overlay' : overlay,
|
|
12
|
+
},
|
|
13
|
+
resolvedModifiers
|
|
14
|
+
]"
|
|
15
|
+
:style="{ cursor: cursorStyle }"
|
|
16
|
+
:target="target"
|
|
17
|
+
:to="to"
|
|
18
|
+
:href="href"
|
|
19
|
+
:data-ulu-proxy-click-init="proxyClickEnabled"
|
|
20
|
+
>
|
|
21
|
+
<div class="card__body">
|
|
22
|
+
<div class="card__main">
|
|
23
|
+
<component
|
|
24
|
+
:is="titleElement"
|
|
25
|
+
class="card__title"
|
|
26
|
+
:class="classes.title"
|
|
27
|
+
>
|
|
28
|
+
<router-link
|
|
29
|
+
v-if="titleTo"
|
|
30
|
+
class="card__title-link"
|
|
31
|
+
:to="titleTo"
|
|
32
|
+
ref="link"
|
|
33
|
+
>
|
|
34
|
+
<slot name="title">
|
|
35
|
+
{{ title }}
|
|
36
|
+
</slot>
|
|
37
|
+
</router-link>
|
|
38
|
+
<a
|
|
39
|
+
v-else-if="titleHref"
|
|
40
|
+
class="card__title-link"
|
|
41
|
+
:href="titleHref"
|
|
42
|
+
:target="titleTarget"
|
|
43
|
+
ref="link"
|
|
44
|
+
>
|
|
45
|
+
<slot name="title">
|
|
46
|
+
{{ title }}
|
|
47
|
+
</slot>
|
|
48
|
+
</a>
|
|
49
|
+
<template v-else>
|
|
50
|
+
<slot name="title">
|
|
51
|
+
{{ title }}
|
|
52
|
+
</slot>
|
|
53
|
+
</template>
|
|
54
|
+
</component>
|
|
55
|
+
<slot name="body"/>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="card__aside" v-if="$slots.body">
|
|
58
|
+
<slot name="aside"/>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<div
|
|
62
|
+
v-if="$slots.image || imageSrc"
|
|
63
|
+
class="card__image"
|
|
64
|
+
:class="[
|
|
65
|
+
{ 'card__image--icon' : imageIcon },
|
|
66
|
+
classes.image
|
|
67
|
+
]"
|
|
68
|
+
>
|
|
69
|
+
<slot name="image">
|
|
70
|
+
<img :src="imageSrc" :alt="imageAlt">
|
|
71
|
+
</slot>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="card__footer" v-if="$slots.footer">
|
|
74
|
+
<slot name="footer"/>
|
|
75
|
+
</div>
|
|
76
|
+
</component>
|
|
77
|
+
</template>
|
|
78
|
+
|
|
79
|
+
<script>
|
|
80
|
+
import { RouterLink } from "vue-router";
|
|
81
|
+
import { useModifiers } from "../../composables/useModifiers.js";
|
|
82
|
+
const titleLinkValidator = (_, props) => {
|
|
83
|
+
const valid = !(props.to || props.href);
|
|
84
|
+
if (!valid) {
|
|
85
|
+
console.warn("'titleHref' and 'titleTo' can't be used with to or href (nesting links)");
|
|
86
|
+
}
|
|
87
|
+
return valid;
|
|
88
|
+
};
|
|
89
|
+
export default {
|
|
90
|
+
name: "UluCard",
|
|
91
|
+
props: {
|
|
92
|
+
/**
|
|
93
|
+
* Specify card element, unless to or href are used which will use 'a' or 'router-link'
|
|
94
|
+
* - Other than changing to more appropriate element (ie 'li' if in list for example), this can
|
|
95
|
+
* be used to set the card to a button to attach your own click handlers to
|
|
96
|
+
*/
|
|
97
|
+
cardElement: {
|
|
98
|
+
type: String,
|
|
99
|
+
default: "article"
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Text for title if not using slot
|
|
103
|
+
*/
|
|
104
|
+
title: String,
|
|
105
|
+
/**
|
|
106
|
+
* Element to use for title
|
|
107
|
+
*/
|
|
108
|
+
titleElement: {
|
|
109
|
+
type: String,
|
|
110
|
+
default: "h3"
|
|
111
|
+
},
|
|
112
|
+
/**
|
|
113
|
+
* Title will be router link
|
|
114
|
+
*/
|
|
115
|
+
titleTo: {
|
|
116
|
+
type: [String, Object],
|
|
117
|
+
validator: titleLinkValidator
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* Will make title a link to href
|
|
121
|
+
*/
|
|
122
|
+
titleHref: {
|
|
123
|
+
type: String,
|
|
124
|
+
validator: titleLinkValidator
|
|
125
|
+
},
|
|
126
|
+
/**
|
|
127
|
+
* When using href this will set title link's target attribute
|
|
128
|
+
*/
|
|
129
|
+
titleTarget: String,
|
|
130
|
+
/**
|
|
131
|
+
* If set the entire card will be router link
|
|
132
|
+
* - Do not us in combination with titleTo or titleHref
|
|
133
|
+
*/
|
|
134
|
+
to: [String, Object],
|
|
135
|
+
/**
|
|
136
|
+
* If set the entire card will be a link to href
|
|
137
|
+
* - Do not us in combination with titleTo or titleHref
|
|
138
|
+
*/
|
|
139
|
+
href: {
|
|
140
|
+
type: String,
|
|
141
|
+
|
|
142
|
+
},
|
|
143
|
+
/**
|
|
144
|
+
* When using href this will set link's target attribute
|
|
145
|
+
*/
|
|
146
|
+
target: String,
|
|
147
|
+
/**
|
|
148
|
+
* Classes with class bindings for different elements including ({ title, image })
|
|
149
|
+
*/
|
|
150
|
+
classes: {
|
|
151
|
+
type: Object,
|
|
152
|
+
default: () => ({})
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Whether to proxy clicks of non-interactive elements (making whole card clickable)
|
|
156
|
+
*/
|
|
157
|
+
proxyClick: Boolean,
|
|
158
|
+
/**
|
|
159
|
+
* Options to be merged for proxy click settings ({ preventSelector, preventSelectionDuration })
|
|
160
|
+
*/
|
|
161
|
+
proxyClickOptions: {
|
|
162
|
+
type: Object,
|
|
163
|
+
default: () => ({})
|
|
164
|
+
},
|
|
165
|
+
/**
|
|
166
|
+
* Source of image
|
|
167
|
+
*/
|
|
168
|
+
imageSrc: String,
|
|
169
|
+
/**
|
|
170
|
+
* Alt text for image
|
|
171
|
+
*/
|
|
172
|
+
imageAlt: String,
|
|
173
|
+
/**
|
|
174
|
+
* If true image will use icon modifier (displays for image adjusts for icon vs full image)
|
|
175
|
+
*/
|
|
176
|
+
imageIcon: Boolean,
|
|
177
|
+
/**
|
|
178
|
+
* Horizontal card layout
|
|
179
|
+
*/
|
|
180
|
+
horizontal: Boolean,
|
|
181
|
+
/**
|
|
182
|
+
* Horizontal centered card layout
|
|
183
|
+
*/
|
|
184
|
+
horizontalCenter: Boolean,
|
|
185
|
+
/**
|
|
186
|
+
* Overlay card layout
|
|
187
|
+
*/
|
|
188
|
+
overlay: Boolean,
|
|
189
|
+
/**
|
|
190
|
+
* Class modifiers (ie. 'transparent', 'secondary', etc)
|
|
191
|
+
* - Can be String or Array of Strings
|
|
192
|
+
*/
|
|
193
|
+
modifiers: [Array, String]
|
|
194
|
+
},
|
|
195
|
+
data() {
|
|
196
|
+
const { proxyClickOptions, proxyClick, titleHref, titleTo } = this;
|
|
197
|
+
return {
|
|
198
|
+
proxyClickEnabled: (proxyClick && (titleHref || titleTo)) || null,
|
|
199
|
+
resolvedProxyOptions: {
|
|
200
|
+
selectorPrevent: "input, select, textarea, button, a, [tabindex='-1']",
|
|
201
|
+
mousedownDurationPrevent: 250,
|
|
202
|
+
...proxyClickOptions
|
|
203
|
+
},
|
|
204
|
+
cursorStyle: null,
|
|
205
|
+
proxyStart: null,
|
|
206
|
+
shouldProxy: false
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
setup(props) {
|
|
210
|
+
const { resolvedModifiers } = useModifiers({ props, baseClass: "card" });
|
|
211
|
+
return { resolvedModifiers };
|
|
212
|
+
},
|
|
213
|
+
computed: {
|
|
214
|
+
resolvedElement() {
|
|
215
|
+
const { cardElement, to, href } = this;
|
|
216
|
+
return to ? RouterLink : href ? 'a' : cardElement;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
methods: {
|
|
220
|
+
onMousedown({ target, timeStamp }) {
|
|
221
|
+
if (!this.proxyClickEnabled) return;
|
|
222
|
+
const { resolvedProxyOptions } = this;
|
|
223
|
+
const { selectorPrevent } = resolvedProxyOptions;
|
|
224
|
+
this.shouldProxy = false;
|
|
225
|
+
if (!target.matches(selectorPrevent)) {
|
|
226
|
+
this.shouldProxy = true;
|
|
227
|
+
this.proxyStart = timeStamp;
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
onMouseup({ timeStamp }) {
|
|
231
|
+
if (!this.proxyClickEnabled) return;
|
|
232
|
+
const { link } = this.$refs;
|
|
233
|
+
const { resolvedProxyOptions } = this;
|
|
234
|
+
const { mousedownDurationPrevent } = resolvedProxyOptions;
|
|
235
|
+
if (this.shouldProxy && timeStamp - this.proxyStart < mousedownDurationPrevent) {
|
|
236
|
+
link.click();
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
</script>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<dl :class="classes.list">
|
|
3
|
+
<div
|
|
4
|
+
v-for="(item, index) in items"
|
|
5
|
+
:key="index"
|
|
6
|
+
:class="classes.item"
|
|
7
|
+
>
|
|
8
|
+
<dt :class="classes.term">
|
|
9
|
+
<slot name="term" :item="item" :index="index">
|
|
10
|
+
{{ item.term }}
|
|
11
|
+
</slot>
|
|
12
|
+
</dt>
|
|
13
|
+
<dd :class="classes.description">
|
|
14
|
+
<slot name="description" :item="item" :index="index">
|
|
15
|
+
{{ item.description }}
|
|
16
|
+
</slot>
|
|
17
|
+
</dd>
|
|
18
|
+
</div>
|
|
19
|
+
</dl>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script>
|
|
23
|
+
export default {
|
|
24
|
+
name: "UluDefinitionList",
|
|
25
|
+
props: {
|
|
26
|
+
/**
|
|
27
|
+
* Array of term, and description (props in object)
|
|
28
|
+
* - Can use slots also
|
|
29
|
+
*/
|
|
30
|
+
items: Array,
|
|
31
|
+
/**
|
|
32
|
+
* Classes object for different elements { list, item, term, description }
|
|
33
|
+
*/
|
|
34
|
+
classes: {
|
|
35
|
+
type: Object,
|
|
36
|
+
default: () => ({})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
</script>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a class="external-link" :href="href" :target="target">
|
|
3
|
+
<span class="external-link__text">
|
|
4
|
+
<slot>{{ text }}</slot>
|
|
5
|
+
</span>
|
|
6
|
+
<UluIcon
|
|
7
|
+
class="external-link__icon margin-left-small-x display-inline"
|
|
8
|
+
type="externalLink"
|
|
9
|
+
:definition="icon"
|
|
10
|
+
/>
|
|
11
|
+
</a>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import UluIcon from "./UluIcon.vue";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Component for external links (adds icon after link text)
|
|
19
|
+
*/
|
|
20
|
+
export default {
|
|
21
|
+
name: "UluExternalLink",
|
|
22
|
+
components: {
|
|
23
|
+
UluIcon
|
|
24
|
+
},
|
|
25
|
+
props: {
|
|
26
|
+
/**
|
|
27
|
+
* Text for link or use slot
|
|
28
|
+
*/
|
|
29
|
+
text: String,
|
|
30
|
+
/**
|
|
31
|
+
* Link href
|
|
32
|
+
*/
|
|
33
|
+
href: String,
|
|
34
|
+
/**
|
|
35
|
+
* Link target
|
|
36
|
+
*/
|
|
37
|
+
target: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: "_blank"
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Override default icon
|
|
43
|
+
*/
|
|
44
|
+
icon: String
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
</script>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
v-if="customIconComponent"
|
|
4
|
+
:is="customIconComponent"
|
|
5
|
+
v-bind="customIconProps"
|
|
6
|
+
/>
|
|
7
|
+
<component
|
|
8
|
+
v-else-if="!useStaticFa && faIconComponent && resolvedDefinition"
|
|
9
|
+
:is="faIconComponent"
|
|
10
|
+
v-bind="iconProps"
|
|
11
|
+
/>
|
|
12
|
+
<span
|
|
13
|
+
v-else-if="useStaticFa && resolvedDefinition"
|
|
14
|
+
:class="staticIconClasses"
|
|
15
|
+
aria-hidden="true"
|
|
16
|
+
></span>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup>
|
|
20
|
+
import { ref, defineAsyncComponent, markRaw, watchEffect, computed } from "vue";
|
|
21
|
+
import { useIcon } from "../../composables/useIcon.js";
|
|
22
|
+
import { getSetting, getIconByType } from "../../settings.js";
|
|
23
|
+
|
|
24
|
+
const faIconComponent = ref(null);
|
|
25
|
+
const { getIconProps, getClassesFromDefinition } = useIcon();
|
|
26
|
+
|
|
27
|
+
let FaModule;
|
|
28
|
+
|
|
29
|
+
const props = defineProps({
|
|
30
|
+
/**
|
|
31
|
+
* Semantic type of icon to use, will be resolved from settings
|
|
32
|
+
*/
|
|
33
|
+
type: String,
|
|
34
|
+
/**
|
|
35
|
+
* Icon definition can be string (fa classes), or array or object (any prop format FaIcon accepts)
|
|
36
|
+
* - This will override the 'type' prop if both are provided
|
|
37
|
+
*/
|
|
38
|
+
definition: [String, Array, Object, Boolean],
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const useStaticFa = computed(() => {
|
|
42
|
+
return getSetting("fontAwesomeStatic");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const customIconComponent = computed(() => {
|
|
46
|
+
return getSetting("iconComponent");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const iconPropResolver = computed(() => {
|
|
50
|
+
return getSetting("iconPropResolver");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Resolve the final icon definition, giving precedence to the `definition` prop
|
|
54
|
+
const resolvedDefinition = computed(() => {
|
|
55
|
+
if (props.definition) {
|
|
56
|
+
return props.definition;
|
|
57
|
+
}
|
|
58
|
+
if (props.type) {
|
|
59
|
+
try {
|
|
60
|
+
return getIconByType(props.type);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.warn(e);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const customIconProps = computed(() => {
|
|
70
|
+
if (!customIconComponent.value || !resolvedDefinition.value) return null;
|
|
71
|
+
return iconPropResolver.value(resolvedDefinition.value);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// This is now a computed property for component props
|
|
75
|
+
const iconProps = computed(() => {
|
|
76
|
+
return getIconProps(resolvedDefinition.value);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Computed property for static icon classes, using the utility method
|
|
80
|
+
const staticIconClasses = computed(() => {
|
|
81
|
+
return getClassesFromDefinition(resolvedDefinition.value);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Watch for changes to prop
|
|
85
|
+
// - Use watchEffect because we are watching reactive object property access (props)
|
|
86
|
+
// - Load FA if needed (so it's not included if it's unneeded)
|
|
87
|
+
// - Replace the empty component after load or if value changes
|
|
88
|
+
watchEffect(async () => {
|
|
89
|
+
// Only attempt to load the component if we are NOT using the static version
|
|
90
|
+
if (!useStaticFa.value && resolvedDefinition.value) {
|
|
91
|
+
if (faIconComponent.value === null) {
|
|
92
|
+
if (FaModule) {
|
|
93
|
+
faIconComponent.value = markRaw(FaModule.FontAwesomeIcon);
|
|
94
|
+
} else {
|
|
95
|
+
const componentPromise = defineAsyncComponent(async () => {
|
|
96
|
+
const module = await import("@fortawesome/vue-fontawesome");
|
|
97
|
+
FaModule = module;
|
|
98
|
+
return module.FontAwesomeIcon;
|
|
99
|
+
});
|
|
100
|
+
faIconComponent.value = markRaw(componentPromise);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// If using static FA or no definition, ensure component is null
|
|
105
|
+
faIconComponent.value = null;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
</script>
|