236 lines
7.2 KiB
Vue
236 lines
7.2 KiB
Vue
<template>
|
|
<div
|
|
class="alert fade show text-center mb-0 py-2 px-4 border-0"
|
|
role="alert"
|
|
v-on="{ 'close.bs.alert': onAlertClose }"
|
|
:class="[
|
|
isDismissible ? 'alert-dismissible' : '',
|
|
this.alertClass,
|
|
this.cssClassNameForCmsWidget,
|
|
]">
|
|
<p class="mx-6 my-0 fw-bold alert-heading">
|
|
<img v-if="showInfoIcon" :src="infoIcon" alt="Info Icon" class="info-icon" />
|
|
{{ alertHeadline }}
|
|
</p>
|
|
<hr v-if="showHorizontalRow" />
|
|
<template v-for="paragraph in splitAlertCopyForParagraphTag" :key="paragraph">
|
|
<p
|
|
class="mx-4 mt-1 mb-0 text-body small"
|
|
v-if="!doesCopyContainRouterLink(paragraph) && !doesCopyContainTextLink(paragraph)"
|
|
v-html="paragraph"></p>
|
|
<p class="mx-4 mt-1 mb-0 text-body small" v-else>
|
|
<template v-if="doesCopyContainRouterLink(paragraph)">
|
|
<textBlock :customText="paragraph" class="mb-1" marginTopSizeOverride="0" />
|
|
</template>
|
|
<template v-else v-for="copy in splitCopyOnCMSPlaceHolder(paragraph)" :key="copy">
|
|
<span v-if="doesCopyContainTextLink(copy)">
|
|
<textLink
|
|
linkType="text"
|
|
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
|
href="javascript:void(0)"
|
|
@click-event="
|
|
$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))
|
|
"
|
|
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)" />
|
|
</span>
|
|
<span v-else v-html="copy"></span>
|
|
</template>
|
|
</p>
|
|
</template>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23.7 23.7" xml:space="preserve">
|
|
<path
|
|
d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581 1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21 .46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
doesCopyContainRouterLink,
|
|
doesCopyContainTextLink,
|
|
splitCopyOnCMSPlaceHolder,
|
|
getRouterLinkRouteFromCopy,
|
|
getRouterLinkDisplayTextFromCopy,
|
|
splitCMSCopyOnParagraphTag,
|
|
} from "@/helpers/cms-content-helper";
|
|
import textLink from "@/ux-components/text-link/text-link";
|
|
import { applicationConfig } from "@/constants/application-config";
|
|
import textBlock from "@/digital-components/text-block/text-block";
|
|
|
|
export default {
|
|
name: "alert",
|
|
props: {
|
|
showInfoIcon: Boolean,
|
|
showHorizontalRow: Boolean,
|
|
isDismissible: Boolean,
|
|
alertClass: String,
|
|
/*
|
|
alertClass class names:
|
|
alert-success (green)
|
|
alert-danger (red)
|
|
alert-warning (yellow)
|
|
alert-info (blue)
|
|
*/
|
|
cmsWidgetName: {
|
|
type: String,
|
|
default(rawProps) {
|
|
if (!rawProps.cmsWidgetName) {
|
|
console.log("Error: Missing a CMS Widget Name (required field)");
|
|
}
|
|
return "widgetUndefined";
|
|
},
|
|
},
|
|
manualHeadline: String,
|
|
manualCopy: String,
|
|
shouldScrollToOnMount: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
onAlertCloseCallback: {
|
|
type: Function,
|
|
},
|
|
},
|
|
computed: {
|
|
infoIcon() {
|
|
return require(`@/assets/img/icons/info-circle-blue.svg`);
|
|
},
|
|
pageQueryString() {
|
|
return applicationConfig.PAGE_QUERYSTRING;
|
|
},
|
|
alertHeadline() {
|
|
return this.manualHeadline
|
|
? this.manualHeadline
|
|
: this.getCmsContent(this.cmsWidgetName, "HeadlineText");
|
|
},
|
|
alertCopy() {
|
|
return this.manualCopy
|
|
? this.manualCopy
|
|
: this.getCmsContent(this.cmsWidgetName, "BodyText");
|
|
},
|
|
splitAlertCopyForParagraphTag() {
|
|
return splitCMSCopyOnParagraphTag(this.alertCopy);
|
|
},
|
|
},
|
|
methods: {
|
|
doesCopyContainRouterLink,
|
|
splitCopyOnCMSPlaceHolder,
|
|
doesCopyContainTextLink,
|
|
getRouterLinkRouteFromCopy,
|
|
getRouterLinkDisplayTextFromCopy,
|
|
ensureAlertIsInViewPort() {
|
|
if (this.shouldScrollToOnMount && this.$el.style.display != "none") {
|
|
var footerHeight = this.getFooterInfoBoxHeight();
|
|
if (!this.isAlertInViewport(footerHeight)) {
|
|
this.$el.scrollIntoView(true); // 'true' attempts to scroll element to top of viewport
|
|
}
|
|
}
|
|
},
|
|
isAlertInViewport(footerHeight) {
|
|
const rect = this.$el.getBoundingClientRect();
|
|
return (
|
|
rect.top >= 0 &&
|
|
// remove footerHeight from window height to avoid items being hidden behind footer
|
|
rect.bottom <=
|
|
(window.innerHeight - footerHeight ||
|
|
document.documentElement.clientHeight - footerHeight)
|
|
);
|
|
},
|
|
onAlertClose() {
|
|
this.onAlertCloseCallback?.();
|
|
},
|
|
},
|
|
mounted() {
|
|
this.ensureAlertIsInViewPort();
|
|
},
|
|
components: {
|
|
textLink,
|
|
textBlock,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.alert {
|
|
padding: 0.675rem 0;
|
|
border-radius: 0.5rem;
|
|
border-width: 0px;
|
|
|
|
hr {
|
|
border: 1px solid $blue;
|
|
margin-left: 1rem;
|
|
margin-right: 1rem;
|
|
}
|
|
|
|
button {
|
|
display: none;
|
|
}
|
|
.btn-close {
|
|
background: none;
|
|
opacity: 1;
|
|
width: 0.75rem;
|
|
height: 0.75rem;
|
|
padding: 0;
|
|
}
|
|
&.drop-off-alert {
|
|
p {
|
|
margin: 0;
|
|
}
|
|
}
|
|
&.alert-dismissible {
|
|
button {
|
|
display: flex;
|
|
top: 0.875rem;
|
|
right: 1rem;
|
|
}
|
|
}
|
|
&.alert-info {
|
|
background-color: $blue-100;
|
|
.alert-heading {
|
|
color: $blue-700;
|
|
}
|
|
svg {
|
|
fill: $blue-700;
|
|
width: 1rem;
|
|
height: 1rem;
|
|
}
|
|
}
|
|
&.alert-danger {
|
|
background-color: $red-100;
|
|
.alert-heading {
|
|
color: $red-600;
|
|
}
|
|
svg {
|
|
fill: $red-600;
|
|
width: 1rem;
|
|
height: 1rem;
|
|
}
|
|
}
|
|
&.alert-warning {
|
|
background-color: $yellow-100;
|
|
.alert-heading {
|
|
color: $yellow-600;
|
|
}
|
|
svg {
|
|
fill: $yellow-600;
|
|
width: 1rem;
|
|
height: 1rem;
|
|
}
|
|
}
|
|
&.alert-success {
|
|
background-color: $green-100;
|
|
.alert-heading {
|
|
color: $green-700;
|
|
}
|
|
svg {
|
|
fill: $green-700;
|
|
width: 1rem;
|
|
height: 1rem;
|
|
}
|
|
}
|
|
& p {
|
|
font-size: 0.875rem;
|
|
}
|
|
}
|
|
</style>
|