@energysage/es-ds-components 0.0.1 → 3.0.0-alpha.10
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/.eslintignore +9 -0
- package/.eslintrc.json +3 -0
- package/.prettierrc.json +10 -0
- package/README.md +0 -3
- package/components/es-accordion-list.vue +117 -0
- package/components/es-accordion.vue +7 -0
- package/components/es-badge.vue +20 -0
- package/components/es-breadcrumbs.vue +73 -0
- package/components/es-button.vue +122 -0
- package/components/es-card.vue +64 -0
- package/components/es-carousel.vue +316 -0
- package/components/es-col.vue +27 -0
- package/components/es-collapse.vue +83 -0
- package/components/es-container.vue +14 -0
- package/components/es-cta-banner.vue +95 -0
- package/components/es-cta-card.vue +60 -0
- package/components/es-data-table-simple.vue +73 -0
- package/components/es-data-table.vue +128 -0
- package/components/es-error-page.vue +120 -0
- package/components/es-file-input.vue +334 -0
- package/components/es-file-preview-modal.vue +61 -0
- package/components/es-footer.vue +163 -0
- package/components/es-form-checkbox.vue +40 -0
- package/components/es-form-input.vue +130 -0
- package/components/es-form-msg.vue +81 -0
- package/components/es-form-radio-card.vue +57 -0
- package/components/es-form-radio-cards.vue +78 -0
- package/components/es-form-textarea.vue +124 -0
- package/components/es-form.vue +16 -0
- package/components/es-modal.vue +103 -0
- package/components/es-nav-bar-account-menu.vue +70 -0
- package/components/es-nav-bar-featured-article.vue +60 -0
- package/components/es-nav-bar-link.vue +27 -0
- package/components/es-nav-bar-product-menu.vue +219 -0
- package/components/es-nav-bar-top-level-menu.vue +194 -0
- package/components/es-nav-bar-topic-menu.vue +197 -0
- package/components/es-nav-bar.vue +411 -0
- package/components/es-pagination.vue +67 -0
- package/components/es-popover.vue +113 -0
- package/components/es-progress-circle.vue +81 -0
- package/components/es-progress.vue +36 -0
- package/components/es-radio-button-group.vue +53 -0
- package/components/es-radio-button.vue +57 -0
- package/components/es-rating.vue +120 -0
- package/components/es-reviews-io-card-carousel.vue +279 -0
- package/components/es-row.vue +5 -0
- package/components/es-skeleton-img.vue +38 -0
- package/components/es-skeleton-wrapper.vue +17 -0
- package/components/es-skeleton.vue +97 -0
- package/components/es-slider.vue +218 -0
- package/components/es-spinner.vue +22 -0
- package/components/es-support-card.vue +150 -0
- package/components/es-support.vue +66 -0
- package/components/es-tab.vue +7 -0
- package/components/es-tabs.vue +70 -0
- package/components/es-verification-code.vue +94 -0
- package/components/es-video.vue +60 -0
- package/components/es-view-more.vue +64 -0
- package/components/es-zip-code-form.vue +204 -0
- package/components/icon/arrow-clockwise.vue +51 -0
- package/components/icon/arrow-counter-clockwise.vue +37 -0
- package/components/icon/arrow-cycle.vue +43 -0
- package/components/icon/arrow-left.vue +39 -0
- package/components/icon/arrow-right.vue +39 -0
- package/components/icon/arrow-up.vue +39 -0
- package/components/icon/arrow.vue +68 -0
- package/components/icon/bank.vue +38 -0
- package/components/icon/battery.vue +40 -0
- package/components/icon/bell.vue +42 -0
- package/components/icon/block.vue +46 -0
- package/components/icon/bolt.vue +38 -0
- package/components/icon/business.vue +42 -0
- package/components/icon/calculator.vue +37 -0
- package/components/icon/calendar.vue +46 -0
- package/components/icon/cart.vue +46 -0
- package/components/icon/chat-add.vue +44 -0
- package/components/icon/chat-approve.vue +42 -0
- package/components/icon/chat-bubble.vue +40 -0
- package/components/icon/chat-dots.vue +42 -0
- package/components/icon/check.vue +39 -0
- package/components/icon/chevron-down.vue +39 -0
- package/components/icon/chevron-horizontal.vue +39 -0
- package/components/icon/chevron-left.vue +39 -0
- package/components/icon/chevron-right.vue +39 -0
- package/components/icon/chevron-up.vue +39 -0
- package/components/icon/circle-alert.vue +46 -0
- package/components/icon/circle-check.vue +46 -0
- package/components/icon/circle-chevron-down.vue +47 -0
- package/components/icon/circle-chevron-left.vue +46 -0
- package/components/icon/circle-chevron-right.vue +46 -0
- package/components/icon/circle-chevron-up.vue +46 -0
- package/components/icon/circle-minus.vue +46 -0
- package/components/icon/circle-plus.vue +46 -0
- package/components/icon/circle-x.vue +46 -0
- package/components/icon/circle.vue +42 -0
- package/components/icon/clock.vue +46 -0
- package/components/icon/community-solar.vue +37 -0
- package/components/icon/companies.vue +43 -0
- package/components/icon/contact-us.vue +37 -0
- package/components/icon/copy.vue +45 -0
- package/components/icon/credit-card.vue +37 -0
- package/components/icon/document.vue +45 -0
- package/components/icon/electric-vehicle.vue +37 -0
- package/components/icon/electricity-circle.vue +39 -0
- package/components/icon/envelope.vue +45 -0
- package/components/icon/es-leaf.vue +39 -0
- package/components/icon/eye.vue +41 -0
- package/components/icon/facebook.vue +41 -0
- package/components/icon/file-doc.vue +72 -0
- package/components/icon/file-docx.vue +72 -0
- package/components/icon/file-pdf.vue +72 -0
- package/components/icon/flag.vue +37 -0
- package/components/icon/folder.vue +41 -0
- package/components/icon/gear.vue +37 -0
- package/components/icon/gift.vue +37 -0
- package/components/icon/hamburger.vue +38 -0
- package/components/icon/heart.vue +39 -0
- package/components/icon/heat-pump.vue +41 -0
- package/components/icon/image.vue +45 -0
- package/components/icon/info-blog-post.vue +47 -0
- package/components/icon/info.vue +45 -0
- package/components/icon/instagram.vue +49 -0
- package/components/icon/light-bulb.vue +36 -0
- package/components/icon/link-out.vue +38 -0
- package/components/icon/linkedin.vue +41 -0
- package/components/icon/location.vue +45 -0
- package/components/icon/lock-off.vue +45 -0
- package/components/icon/lock-on.vue +48 -0
- package/components/icon/marketplace.vue +43 -0
- package/components/icon/minus.vue +38 -0
- package/components/icon/money-bag.vue +37 -0
- package/components/icon/money.vue +35 -0
- package/components/icon/open-envelope.vue +45 -0
- package/components/icon/paper.vue +45 -0
- package/components/icon/payback.vue +37 -0
- package/components/icon/pencil.vue +45 -0
- package/components/icon/person-add.vue +41 -0
- package/components/icon/person-check.vue +41 -0
- package/components/icon/person-cross.vue +41 -0
- package/components/icon/person.vue +41 -0
- package/components/icon/phone.vue +41 -0
- package/components/icon/play.vue +41 -0
- package/components/icon/plus.vue +38 -0
- package/components/icon/roof.vue +37 -0
- package/components/icon/rooftop-solar.vue +37 -0
- package/components/icon/saving.vue +37 -0
- package/components/icon/search.vue +43 -0
- package/components/icon/settings-horizontal.vue +57 -0
- package/components/icon/settings-vertical.vue +57 -0
- package/components/icon/shield-with-check.vue +38 -0
- package/components/icon/shield.vue +41 -0
- package/components/icon/shopping-bag.vue +39 -0
- package/components/icon/solar.vue +37 -0
- package/components/icon/sound-down.vue +45 -0
- package/components/icon/sound-off.vue +41 -0
- package/components/icon/sound-on.vue +41 -0
- package/components/icon/sound-up.vue +41 -0
- package/components/icon/star-empty.vue +38 -0
- package/components/icon/star-full.vue +36 -0
- package/components/icon/star-half.vue +55 -0
- package/components/icon/state-ak.vue +53 -0
- package/components/icon/state-al.vue +38 -0
- package/components/icon/state-ar.vue +38 -0
- package/components/icon/state-az.vue +38 -0
- package/components/icon/state-ca.vue +38 -0
- package/components/icon/state-co.vue +38 -0
- package/components/icon/state-ct.vue +38 -0
- package/components/icon/state-dc.vue +52 -0
- package/components/icon/state-de.vue +38 -0
- package/components/icon/state-fl.vue +38 -0
- package/components/icon/state-ga.vue +38 -0
- package/components/icon/state-hi.vue +59 -0
- package/components/icon/state-ia.vue +38 -0
- package/components/icon/state-id.vue +38 -0
- package/components/icon/state-il.vue +38 -0
- package/components/icon/state-in.vue +38 -0
- package/components/icon/state-ks.vue +38 -0
- package/components/icon/state-ky.vue +38 -0
- package/components/icon/state-la.vue +38 -0
- package/components/icon/state-ma.vue +38 -0
- package/components/icon/state-md.vue +39 -0
- package/components/icon/state-me.vue +38 -0
- package/components/icon/state-mi.vue +38 -0
- package/components/icon/state-mn.vue +38 -0
- package/components/icon/state-mo.vue +38 -0
- package/components/icon/state-ms.vue +38 -0
- package/components/icon/state-mt.vue +38 -0
- package/components/icon/state-nc.vue +38 -0
- package/components/icon/state-nd.vue +38 -0
- package/components/icon/state-ne.vue +38 -0
- package/components/icon/state-nh.vue +38 -0
- package/components/icon/state-nj.vue +37 -0
- package/components/icon/state-nm.vue +38 -0
- package/components/icon/state-nv.vue +38 -0
- package/components/icon/state-ny.vue +41 -0
- package/components/icon/state-oh.vue +38 -0
- package/components/icon/state-ok.vue +38 -0
- package/components/icon/state-or.vue +38 -0
- package/components/icon/state-pa.vue +38 -0
- package/components/icon/state-ri.vue +38 -0
- package/components/icon/state-sc.vue +38 -0
- package/components/icon/state-sd.vue +38 -0
- package/components/icon/state-tn.vue +38 -0
- package/components/icon/state-tx.vue +38 -0
- package/components/icon/state-ut.vue +38 -0
- package/components/icon/state-va.vue +38 -0
- package/components/icon/state-vt.vue +38 -0
- package/components/icon/state-wa.vue +38 -0
- package/components/icon/state-wi.vue +38 -0
- package/components/icon/state-wv.vue +38 -0
- package/components/icon/state-wy.vue +38 -0
- package/components/icon/thumbs-up.vue +39 -0
- package/components/icon/trash-can.vue +41 -0
- package/components/icon/tree.vue +37 -0
- package/components/icon/twitter.vue +43 -0
- package/components/icon/upload.vue +41 -0
- package/components/icon/verified.vue +40 -0
- package/components/icon/video-play.vue +41 -0
- package/components/icon/wifi.vue +38 -0
- package/components/icon/x.vue +38 -0
- package/components/icon/youtube.vue +45 -0
- package/composables/forms.ts +124 -0
- package/nuxt.config.ts +83 -1
- package/package.json +47 -13
- package/tsconfig.json +4 -0
- package/types/es-carousel.ts +12 -0
- package/types/index.ts +1 -0
- package/utils/forms.ts +120 -0
- package/utils/get-es-footer-content.ts +90 -0
- package/utils/get-es-nav-bar-account-content.ts +55 -0
- package/utils/get-es-nav-bar-global-content.ts +482 -0
- package/utils/mime-type-finder.ts +48 -0
- package/utils/vuelidate-keys.ts +39 -0
- package/components/TestComponent.vue +0 -5
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IconFacebook from './icon/facebook.vue';
|
|
3
|
+
import IconInstagram from './icon/instagram.vue';
|
|
4
|
+
import IconLinkedin from './icon/linkedin.vue';
|
|
5
|
+
import IconTwitter from './icon/twitter.vue';
|
|
6
|
+
import IconYoutube from './icon/youtube.vue';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
name: 'EsFooter',
|
|
10
|
+
components: {
|
|
11
|
+
IconFacebook,
|
|
12
|
+
IconInstagram,
|
|
13
|
+
IconLinkedin,
|
|
14
|
+
IconTwitter,
|
|
15
|
+
IconYoutube,
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
content: {
|
|
19
|
+
type: Object,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
computed: {
|
|
24
|
+
copyrightText() {
|
|
25
|
+
return this.content.copyrightText.replace('{currentYear}', new Date().getFullYear());
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<div class="es-footer clearfix">
|
|
33
|
+
<!-- Make an impact -->
|
|
34
|
+
<div class="bg-blue-900 text-white py-200 py-lg-300 px-200">
|
|
35
|
+
<div class="container px-0">
|
|
36
|
+
<div class="row">
|
|
37
|
+
<div
|
|
38
|
+
class="col col-12 col-md-5 col-lg-4 font-size-200 font-size-md-400 font-weight-bold mb-150 mb-md-0">
|
|
39
|
+
{{ content.banner.headline }}
|
|
40
|
+
<br />
|
|
41
|
+
{{ content.banner.subHeadline }}
|
|
42
|
+
</div>
|
|
43
|
+
<div class="col col-12 col-md-7 col-lg-8">
|
|
44
|
+
{{ content.banner.body }}
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<!-- Make an impact -->
|
|
50
|
+
<div class="bg-blue-800 py-200 pt-lg-200 pb-lg-150 px-200">
|
|
51
|
+
<div class="container px-0">
|
|
52
|
+
<div class="row">
|
|
53
|
+
<!-- Link columns -->
|
|
54
|
+
<div class="col col-12 col-lg-8 order-lg-1 text-white">
|
|
55
|
+
<div class="row">
|
|
56
|
+
<div
|
|
57
|
+
v-for="column in content.columns"
|
|
58
|
+
:key="column.title"
|
|
59
|
+
class="col col-6 col-md-3 mb-100 mb-lg-0">
|
|
60
|
+
<ul class="list-unstyled mb-lg-0">
|
|
61
|
+
<li class="font-weight-bold font-size-75 font-size-md-100 mb-100 mb-lg-50">
|
|
62
|
+
{{ column.title }}
|
|
63
|
+
</li>
|
|
64
|
+
<li
|
|
65
|
+
v-for="link in column.links"
|
|
66
|
+
:key="link.text"
|
|
67
|
+
class="mt-0 mt-lg-25 mb-100 mb-lg-50 font-size-75">
|
|
68
|
+
<es-nav-bar-link
|
|
69
|
+
:href="link.url"
|
|
70
|
+
:target="link.newTab ? '_blank' : null"
|
|
71
|
+
class="text-reset">
|
|
72
|
+
{{ link.text }}
|
|
73
|
+
</es-nav-bar-link>
|
|
74
|
+
</li>
|
|
75
|
+
</ul>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<!-- Link columns -->
|
|
80
|
+
<!-- Logo and Social-->
|
|
81
|
+
<div class="col col-12 col-lg-4 order-lg-0">
|
|
82
|
+
<es-nav-bar-link
|
|
83
|
+
class="d-block mb-150 d-flex justify-content-center justify-content-lg-start"
|
|
84
|
+
:href="content.home.link">
|
|
85
|
+
<span class="sr-only">
|
|
86
|
+
{{ content.home.name }}
|
|
87
|
+
</span>
|
|
88
|
+
<div class="es-footer-logo">
|
|
89
|
+
<slot name="logo" />
|
|
90
|
+
</div>
|
|
91
|
+
</es-nav-bar-link>
|
|
92
|
+
<!-- Social icons -->
|
|
93
|
+
<div class="d-flex text-white justify-content-center justify-content-lg-start">
|
|
94
|
+
<es-nav-bar-link
|
|
95
|
+
v-for="(iconLink, index) in content.socialLinks"
|
|
96
|
+
:key="iconLink.text"
|
|
97
|
+
class="text-reset"
|
|
98
|
+
:class="{ 'mr-150': index < content.socialLinks.length - 1 }"
|
|
99
|
+
:href="iconLink.url"
|
|
100
|
+
target="_blank">
|
|
101
|
+
<span class="sr-only">{{ iconLink.text }}</span>
|
|
102
|
+
<component :is="iconLink.icon" />
|
|
103
|
+
</es-nav-bar-link>
|
|
104
|
+
</div>
|
|
105
|
+
<!-- Social icons -->
|
|
106
|
+
</div>
|
|
107
|
+
<!-- Logo and Social -->
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="bg-blue-700 text-blue-50 px-200 py-100">
|
|
112
|
+
<div class="container px-0">
|
|
113
|
+
<!-- Trademark Info -->
|
|
114
|
+
<p class="font-size-75">
|
|
115
|
+
{{ content.trademarkText }}
|
|
116
|
+
</p>
|
|
117
|
+
<p class="mb-200 font-size-75">
|
|
118
|
+
{{ copyrightText }}
|
|
119
|
+
</p>
|
|
120
|
+
<!-- Trademark Info -->
|
|
121
|
+
<!-- Legal -->
|
|
122
|
+
<hr class="border-top border-blue-500 m-0" />
|
|
123
|
+
<div class="row justify-content-center pt-100">
|
|
124
|
+
<div
|
|
125
|
+
v-for="link in content.legalLinks"
|
|
126
|
+
:key="link.text"
|
|
127
|
+
class="col col-6 col-lg-auto font-size-75 font-weight-semibold font-size-md-50 font-weight-md-normal mt-25 mb-50 px-lg-300">
|
|
128
|
+
<es-nav-bar-link
|
|
129
|
+
:href="link.url"
|
|
130
|
+
class="text-reset font-weight-normal">
|
|
131
|
+
{{ link.text }}
|
|
132
|
+
</es-nav-bar-link>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
<!-- Legal -->
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="bg-blue-50 px-200 py-100">
|
|
139
|
+
<div class="container px-0">
|
|
140
|
+
<!-- DOE -->
|
|
141
|
+
<div class="d-lg-flex align-items-end">
|
|
142
|
+
<!-- eslint-disable-next-line -->
|
|
143
|
+
<img
|
|
144
|
+
:src="content.departmentOfEnergy.logoUrl"
|
|
145
|
+
alt="department of energy logo"
|
|
146
|
+
aria-hidden="true"
|
|
147
|
+
class="mr-100 mb-100 mb-lg-0"
|
|
148
|
+
width="99"
|
|
149
|
+
height="24" />
|
|
150
|
+
<p class="mb-0 font-size-75 font-weight-normal font-weight-lg-semibold">
|
|
151
|
+
<es-nav-bar-link
|
|
152
|
+
:href="content.departmentOfEnergy.learnMore.link"
|
|
153
|
+
target="_blank"
|
|
154
|
+
class="text-blue-900">
|
|
155
|
+
{{ content.departmentOfEnergy.learnMore.text }}
|
|
156
|
+
</es-nav-bar-link>
|
|
157
|
+
</p>
|
|
158
|
+
</div>
|
|
159
|
+
<!-- DOE -->
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</template>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const model = defineModel<boolean>({
|
|
3
|
+
default: false,
|
|
4
|
+
});
|
|
5
|
+
defineOptions({
|
|
6
|
+
inheritAttrs: false,
|
|
7
|
+
});
|
|
8
|
+
defineProps({
|
|
9
|
+
id: {
|
|
10
|
+
type: String,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
disabled: {
|
|
14
|
+
type: Boolean,
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
indeterminate: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<div class="custom-control custom-checkbox">
|
|
26
|
+
<input
|
|
27
|
+
v-bind="$attrs"
|
|
28
|
+
:id="id"
|
|
29
|
+
v-model="model"
|
|
30
|
+
type="checkbox"
|
|
31
|
+
class="custom-control-input"
|
|
32
|
+
:indeterminate="indeterminate"
|
|
33
|
+
:disabled="disabled" />
|
|
34
|
+
<label
|
|
35
|
+
:for="id"
|
|
36
|
+
class="custom-control-label">
|
|
37
|
+
<slot />
|
|
38
|
+
</label>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import InputText from 'primevue/inputtext';
|
|
3
|
+
import InputMask from 'primevue/inputmask';
|
|
4
|
+
// Prevents attributes from being applied to first <div>
|
|
5
|
+
// v-bind="$attr" is on the input instead
|
|
6
|
+
defineOptions({
|
|
7
|
+
inheritAttrs: false,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
defineProps({
|
|
11
|
+
/**
|
|
12
|
+
* Required
|
|
13
|
+
*/
|
|
14
|
+
required: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
default: false,
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* Disabled
|
|
20
|
+
*/
|
|
21
|
+
disabled: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* Type
|
|
27
|
+
*/
|
|
28
|
+
type: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: 'text',
|
|
31
|
+
validator: (val: string) => ['text', 'email', 'number', 'password', 'tel', 'maskedTel'].includes(val),
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* ID
|
|
35
|
+
* required
|
|
36
|
+
*/
|
|
37
|
+
id: {
|
|
38
|
+
type: String,
|
|
39
|
+
required: true,
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* state
|
|
43
|
+
*/
|
|
44
|
+
state: {
|
|
45
|
+
type: [Boolean, null],
|
|
46
|
+
default: null,
|
|
47
|
+
},
|
|
48
|
+
labelSrOnly: {
|
|
49
|
+
type: Boolean,
|
|
50
|
+
default: false,
|
|
51
|
+
},
|
|
52
|
+
phoneMaskValue: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: '(999) 999-9999',
|
|
55
|
+
required: false,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const slots = useSlots();
|
|
60
|
+
|
|
61
|
+
const hasSuccess = () => !!slots.successMessage;
|
|
62
|
+
const hasMessage = () => !!slots.message;
|
|
63
|
+
const hasError = () => !!slots.errorMessage;
|
|
64
|
+
const hasExtraContext = () => !!slots.extraContext;
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<div
|
|
69
|
+
class="input-wrapper justify-content-end"
|
|
70
|
+
:class="$attrs.class"
|
|
71
|
+
:required="required">
|
|
72
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
73
|
+
<label
|
|
74
|
+
:for="id"
|
|
75
|
+
class="label justify-content-start"
|
|
76
|
+
:class="{ 'sr-only': labelSrOnly }">
|
|
77
|
+
<slot name="label" />
|
|
78
|
+
<span
|
|
79
|
+
v-if="required"
|
|
80
|
+
class="text-danger">
|
|
81
|
+
*
|
|
82
|
+
</span>
|
|
83
|
+
</label>
|
|
84
|
+
<p
|
|
85
|
+
v-if="hasExtraContext()"
|
|
86
|
+
class="mb-25 font-size-75">
|
|
87
|
+
<slot name="extraContext" />
|
|
88
|
+
</p>
|
|
89
|
+
<div class="input-holder position-relative">
|
|
90
|
+
<!-- prefix icons are decorative only so are aria-hidden -->
|
|
91
|
+
<span
|
|
92
|
+
v-if="$slots.prefixIcon"
|
|
93
|
+
aria-hidden="true"
|
|
94
|
+
class="prefix-icon position-absolute">
|
|
95
|
+
<slot name="prefixIcon" />
|
|
96
|
+
</span>
|
|
97
|
+
<component
|
|
98
|
+
:is="type === 'maskedTel' ? InputMask : InputText"
|
|
99
|
+
:id="id"
|
|
100
|
+
v-bind="{ ...$attrs, class: undefined }"
|
|
101
|
+
:type="type"
|
|
102
|
+
class="es-form-input form-control w-100"
|
|
103
|
+
:class="{
|
|
104
|
+
'has-prefix-icon': $slots.prefixIcon,
|
|
105
|
+
'is-invalid': state === false,
|
|
106
|
+
}"
|
|
107
|
+
:mask="phoneMaskValue"
|
|
108
|
+
:disabled="disabled"
|
|
109
|
+
:invalid="state === false" />
|
|
110
|
+
<small
|
|
111
|
+
v-if="hasMessage() && ((!hasSuccess() && state) || state == null)"
|
|
112
|
+
class="text-muted">
|
|
113
|
+
<slot name="message" />
|
|
114
|
+
</small>
|
|
115
|
+
<small
|
|
116
|
+
v-if="state === false && (hasError() || required)"
|
|
117
|
+
class="text-danger">
|
|
118
|
+
<slot
|
|
119
|
+
v-if="hasError()"
|
|
120
|
+
name="errorMessage" />
|
|
121
|
+
<template v-else-if="required"> This field is required. </template>
|
|
122
|
+
</small>
|
|
123
|
+
<small
|
|
124
|
+
v-if="state && hasSuccess()"
|
|
125
|
+
class="text-success">
|
|
126
|
+
<slot name="successMessage" />
|
|
127
|
+
</small>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</template>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
show: {
|
|
4
|
+
type: Boolean,
|
|
5
|
+
default: false,
|
|
6
|
+
},
|
|
7
|
+
timeout: {
|
|
8
|
+
type: Number,
|
|
9
|
+
default: 20,
|
|
10
|
+
required: false,
|
|
11
|
+
},
|
|
12
|
+
variant: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: 'danger',
|
|
15
|
+
required: false,
|
|
16
|
+
validator: (val: string) => ['danger', 'success', 'primary'].includes(val),
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const emit = defineEmits(['hidden']);
|
|
21
|
+
|
|
22
|
+
const hide = () => {
|
|
23
|
+
emit('hidden');
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
watch(
|
|
27
|
+
() => props.show,
|
|
28
|
+
(newValue, oldValue) => {
|
|
29
|
+
if (newValue && !oldValue) {
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
hide();
|
|
32
|
+
}, props.timeout * 1000);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<transition>
|
|
40
|
+
<div
|
|
41
|
+
v-if="show"
|
|
42
|
+
role="alert"
|
|
43
|
+
aria-live="polite"
|
|
44
|
+
aria-atomic="true"
|
|
45
|
+
class="alert es-form-msg my-100 alert-dismissible"
|
|
46
|
+
:class="`alert-${variant}`">
|
|
47
|
+
<div class="d-flex pr-100">
|
|
48
|
+
<div class="icon-wrapper flex-shrink-0 mr-100">
|
|
49
|
+
<icon-circle-alert v-if="variant === 'danger'" />
|
|
50
|
+
<icon-circle-check v-if="variant === 'success'" />
|
|
51
|
+
<icon-info v-if="variant === 'primary'" />
|
|
52
|
+
</div>
|
|
53
|
+
<slot />
|
|
54
|
+
</div>
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
aria-label="Close"
|
|
58
|
+
class="close"
|
|
59
|
+
@click="hide">
|
|
60
|
+
<icon-x />
|
|
61
|
+
</button>
|
|
62
|
+
</div>
|
|
63
|
+
</transition>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<style lang="scss" scoped>
|
|
67
|
+
.form-msg {
|
|
68
|
+
flex: 0 0 100%;
|
|
69
|
+
padding-right: 2.5rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.v-enter-active,
|
|
73
|
+
.v-leave-active {
|
|
74
|
+
transition: opacity 0.15s;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.v-enter-from,
|
|
78
|
+
.v-leave-to {
|
|
79
|
+
opacity: 0;
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useFocus } from '@vueuse/core';
|
|
3
|
+
|
|
4
|
+
const inputElem = useTemplateRef('input-elem');
|
|
5
|
+
const { focused: inputFocused } = useFocus(inputElem);
|
|
6
|
+
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
|
+
interface IProps {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
value: any;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
inline?: boolean;
|
|
14
|
+
displayName?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const props = withDefaults(defineProps<IProps>(), {
|
|
18
|
+
disabled: false,
|
|
19
|
+
inline: false,
|
|
20
|
+
displayName: '',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Need to define the implicit emit from v-model, so that it can also get fired
|
|
24
|
+
// from the label clicks
|
|
25
|
+
const emit = defineEmits(['update:modelValue']);
|
|
26
|
+
|
|
27
|
+
function handleRadioButtonClick() {
|
|
28
|
+
if (!props.disabled) {
|
|
29
|
+
emit('update:modelValue', props.value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
const model = defineModel<any>();
|
|
35
|
+
const isChecked = computed(() => props.value === model.value);
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<label
|
|
40
|
+
class="es-form-radio-card es-card interactive w-100 btn btn-outline-primary"
|
|
41
|
+
:class="{ active: isChecked, disabled: props.disabled, focus: isChecked || inputFocused }"
|
|
42
|
+
@click="handleRadioButtonClick">
|
|
43
|
+
<input
|
|
44
|
+
:id="id"
|
|
45
|
+
ref="input-elem"
|
|
46
|
+
v-model="model"
|
|
47
|
+
:disabled="props.disabled"
|
|
48
|
+
type="radio"
|
|
49
|
+
name="props.name"
|
|
50
|
+
:value="props.value"
|
|
51
|
+
:checked="isChecked"
|
|
52
|
+
@click="handleRadioButtonClick" />
|
|
53
|
+
<slot>
|
|
54
|
+
{{ displayName }}
|
|
55
|
+
</slot>
|
|
56
|
+
</label>
|
|
57
|
+
</template>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface Option {
|
|
3
|
+
id: string;
|
|
4
|
+
text: string;
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
value: any;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
inline?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
options?: Option[];
|
|
16
|
+
inline?: boolean;
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
modelValue?: any;
|
|
19
|
+
hasIcon?: boolean;
|
|
20
|
+
labelClass?: string;
|
|
21
|
+
labelSrOnly?: boolean;
|
|
22
|
+
}
|
|
23
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
24
|
+
name: '',
|
|
25
|
+
options: undefined,
|
|
26
|
+
inline: false,
|
|
27
|
+
modelValue: undefined,
|
|
28
|
+
hasIcon: false,
|
|
29
|
+
labelClass: 'font-size-h3',
|
|
30
|
+
labelSrOnly: false,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const emit = defineEmits(['update:model-value']);
|
|
34
|
+
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
function handleUpdate(value: any) {
|
|
37
|
+
emit('update:model-value', value);
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<fieldset
|
|
43
|
+
:id="`${props.id}-fieldset`"
|
|
44
|
+
class="form-group">
|
|
45
|
+
<legend
|
|
46
|
+
:id="`${props.id}-legend`"
|
|
47
|
+
class="font-size-h1 font-weight-bolder mb-200 pb-0 text-dark"
|
|
48
|
+
:class="{ 'sr-only': props.labelSrOnly }"
|
|
49
|
+
tabindex="-1">
|
|
50
|
+
{{ props.label }}
|
|
51
|
+
</legend>
|
|
52
|
+
<div>
|
|
53
|
+
<div
|
|
54
|
+
:id="`${props.id}-radiogroup`"
|
|
55
|
+
role="radiogroup"
|
|
56
|
+
tabindex="-1"
|
|
57
|
+
class="es-form-radio-cards d-flex justify-content-center btn-group-vertical"
|
|
58
|
+
:class="{ 'has-icon': props.hasIcon }">
|
|
59
|
+
<slot :options="options">
|
|
60
|
+
<es-form-radio-card
|
|
61
|
+
v-for="option in options"
|
|
62
|
+
:id="option.id"
|
|
63
|
+
:key="option.value"
|
|
64
|
+
:disabled="option?.disabled || false"
|
|
65
|
+
:name="props.name"
|
|
66
|
+
:value="option.value"
|
|
67
|
+
:model-value="props.modelValue"
|
|
68
|
+
:inline="props.inline || false"
|
|
69
|
+
@update:model-value="handleUpdate">
|
|
70
|
+
<span :class="props.labelClass">
|
|
71
|
+
{{ option.text }}
|
|
72
|
+
</span>
|
|
73
|
+
</es-form-radio-card>
|
|
74
|
+
</slot>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</fieldset>
|
|
78
|
+
</template>
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// Prevents attributes from being applied to first <div>
|
|
3
|
+
// v-bind="$attr" is on the input instead
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
defineProps({
|
|
9
|
+
/**
|
|
10
|
+
* Required
|
|
11
|
+
*/
|
|
12
|
+
required: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: false,
|
|
15
|
+
},
|
|
16
|
+
/**
|
|
17
|
+
* Disabled
|
|
18
|
+
*/
|
|
19
|
+
disabled: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* ID
|
|
25
|
+
* required
|
|
26
|
+
*/
|
|
27
|
+
id: {
|
|
28
|
+
type: String,
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
* state
|
|
33
|
+
*/
|
|
34
|
+
state: {
|
|
35
|
+
type: [Boolean, null],
|
|
36
|
+
default: null,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
const model = defineModel<string>();
|
|
40
|
+
|
|
41
|
+
const slots = useSlots();
|
|
42
|
+
|
|
43
|
+
const hasSuccess = () => !!slots.successMessage;
|
|
44
|
+
const hasMessage = () => !!slots.message;
|
|
45
|
+
const hasError = () => !!slots.errorMessage;
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div
|
|
50
|
+
class="input-wrapper justify-content-end"
|
|
51
|
+
:required="required">
|
|
52
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
53
|
+
<label
|
|
54
|
+
:for="id"
|
|
55
|
+
class="label justify-content-start">
|
|
56
|
+
<slot name="label" />
|
|
57
|
+
|
|
58
|
+
<span
|
|
59
|
+
v-if="required"
|
|
60
|
+
class="text-danger">
|
|
61
|
+
*
|
|
62
|
+
</span>
|
|
63
|
+
</label>
|
|
64
|
+
|
|
65
|
+
<div class="input-holder">
|
|
66
|
+
<textarea
|
|
67
|
+
:id="id"
|
|
68
|
+
v-model="model"
|
|
69
|
+
v-bind="$attrs"
|
|
70
|
+
class="es-form-textarea w-100 form-control"
|
|
71
|
+
:class="{ 'is-invalid': state === false }"
|
|
72
|
+
:disabled="disabled"
|
|
73
|
+
:invalid="state === false" />
|
|
74
|
+
<small
|
|
75
|
+
v-if="hasMessage() && ((!hasSuccess() && state) || state == null)"
|
|
76
|
+
class="text-muted">
|
|
77
|
+
<slot name="message" />
|
|
78
|
+
</small>
|
|
79
|
+
<small
|
|
80
|
+
v-if="state === false && (hasError() || required)"
|
|
81
|
+
class="text-danger">
|
|
82
|
+
<slot
|
|
83
|
+
v-if="hasError()"
|
|
84
|
+
name="errorMessage" />
|
|
85
|
+
<template v-else-if="required"> This field is required. </template>
|
|
86
|
+
</small>
|
|
87
|
+
<small
|
|
88
|
+
v-if="state && hasSuccess()"
|
|
89
|
+
class="text-success">
|
|
90
|
+
<slot name="successMessage" />
|
|
91
|
+
</small>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<style lang="scss" scoped>
|
|
97
|
+
@use '@energysage/es-ds-styles/scss/variables' as variables;
|
|
98
|
+
|
|
99
|
+
.es-form-textarea {
|
|
100
|
+
min-height: 8.125rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.es-form-textarea:disabled,
|
|
104
|
+
.es-form-textarea[readonly] {
|
|
105
|
+
border: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.is-invalid {
|
|
109
|
+
color: variables.$danger;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.form-inline .input-wrapper {
|
|
113
|
+
display: flex;
|
|
114
|
+
flex: 0 0 100%;
|
|
115
|
+
|
|
116
|
+
label {
|
|
117
|
+
flex: 0 0 30%;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.input-holder {
|
|
121
|
+
flex: 0 0 70%;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
inline: {
|
|
4
|
+
type: Boolean,
|
|
5
|
+
default: false,
|
|
6
|
+
},
|
|
7
|
+
});
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<form
|
|
12
|
+
:class="{ 'form-inline': props.inline }"
|
|
13
|
+
v-bind="$attrs">
|
|
14
|
+
<slot />
|
|
15
|
+
</form>
|
|
16
|
+
</template>
|