@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,197 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default {
|
|
3
|
+
name: 'EsNavBarTopicMenu',
|
|
4
|
+
props: {
|
|
5
|
+
homeName: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
homeLink: {
|
|
10
|
+
type: String,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
closeButtonText: {
|
|
14
|
+
type: String,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
items: {
|
|
18
|
+
type: Array,
|
|
19
|
+
required: true,
|
|
20
|
+
},
|
|
21
|
+
link: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: '',
|
|
24
|
+
},
|
|
25
|
+
newTab: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: false,
|
|
28
|
+
},
|
|
29
|
+
name: {
|
|
30
|
+
type: String,
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
showItemsOnMobile: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: true,
|
|
36
|
+
},
|
|
37
|
+
subHeading: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: '',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
computed: {
|
|
43
|
+
checkboxId() {
|
|
44
|
+
return `topMenu-${this.name}`;
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<li
|
|
52
|
+
class="topic-group border-0 mb-lg-200"
|
|
53
|
+
:class="{ 'nav-item': showItemsOnMobile }">
|
|
54
|
+
<!-- desktop header, if it's a link -->
|
|
55
|
+
<es-nav-bar-link
|
|
56
|
+
v-if="link"
|
|
57
|
+
class="dropdown-item nav-link topic-menu-header d-none d-lg-block font-size-sm mb-lg-50 position-relative px-lg-0 py-lg-50 text-gray"
|
|
58
|
+
:href="link"
|
|
59
|
+
:target="newTab ? '_blank' : null">
|
|
60
|
+
<span class="align-items-center eyebrow d-flex link-name">
|
|
61
|
+
{{ name }}
|
|
62
|
+
<icon-arrow-right
|
|
63
|
+
class="d-none d-lg-inline-block ml-25"
|
|
64
|
+
height="24px"
|
|
65
|
+
width="24px" />
|
|
66
|
+
</span>
|
|
67
|
+
<span
|
|
68
|
+
v-if="subHeading"
|
|
69
|
+
class="d-block link-subheading">
|
|
70
|
+
{{ subHeading }}
|
|
71
|
+
</span>
|
|
72
|
+
</es-nav-bar-link>
|
|
73
|
+
<!-- desktop header, if it's not a link -->
|
|
74
|
+
<p
|
|
75
|
+
v-else
|
|
76
|
+
class="dropdown-toggle topic-menu-header eyebrow align-items-center d-none d-lg-block mb-lg-50 position-relative px-lg-0 py-lg-50">
|
|
77
|
+
<span class="d-block">
|
|
78
|
+
{{ name }}
|
|
79
|
+
</span>
|
|
80
|
+
<span
|
|
81
|
+
v-if="subHeading"
|
|
82
|
+
class="d-block">
|
|
83
|
+
{{ subHeading }}
|
|
84
|
+
</span>
|
|
85
|
+
</p>
|
|
86
|
+
<!-- mobile nav item, tapping which drills down to submenu -->
|
|
87
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
88
|
+
<label
|
|
89
|
+
:for="checkboxId"
|
|
90
|
+
class="dropdown-label nav-item-border-mobile nav-link align-items-center d-lg-none justify-content-between w-100 h-100 font-weight-bold"
|
|
91
|
+
:class="{
|
|
92
|
+
'd-flex': showItemsOnMobile,
|
|
93
|
+
'd-none': !showItemsOnMobile,
|
|
94
|
+
}">
|
|
95
|
+
{{ name }}
|
|
96
|
+
<icon-chevron-right
|
|
97
|
+
class="expand-icon"
|
|
98
|
+
style="height: 24px" />
|
|
99
|
+
</label>
|
|
100
|
+
<input
|
|
101
|
+
:id="checkboxId"
|
|
102
|
+
:name="checkboxId"
|
|
103
|
+
type="checkbox"
|
|
104
|
+
class="menu-checkbox" />
|
|
105
|
+
<div class="menu submenu">
|
|
106
|
+
<div class="menu-header">
|
|
107
|
+
<div class="col-3" />
|
|
108
|
+
<div class="col-6 align-self-center text-center py-100">
|
|
109
|
+
<div class="nav-es-logo-mobile align-items-center d-flex">
|
|
110
|
+
<slot name="logo" />
|
|
111
|
+
</div>
|
|
112
|
+
<span class="sr-only">
|
|
113
|
+
{{ homeName }}
|
|
114
|
+
</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="d-flex col-3 justify-content-end">
|
|
117
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
118
|
+
<label
|
|
119
|
+
for="data--main-menu"
|
|
120
|
+
class="mb-0">
|
|
121
|
+
<icon-x class="menu-toggle align-self-center" />
|
|
122
|
+
<span class="sr-only">
|
|
123
|
+
{{ closeButtonText }}
|
|
124
|
+
</span>
|
|
125
|
+
</label>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
<ul
|
|
129
|
+
class="visible-lg list-unstyled"
|
|
130
|
+
style="top: 0">
|
|
131
|
+
<li class="nav-item col-lg-12 d-lg-none mb-50">
|
|
132
|
+
<div class="col-2">
|
|
133
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
134
|
+
<label
|
|
135
|
+
:for="checkboxId"
|
|
136
|
+
class="menu-toggle d-flex w-100 h-100 mb-0 align-items-center font-size-sm">
|
|
137
|
+
<icon-arrow-left
|
|
138
|
+
class="expand-icon"
|
|
139
|
+
style="height: 24px" />
|
|
140
|
+
</label>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="col-8 align-self-center text-center py-100">
|
|
143
|
+
<es-nav-bar-link
|
|
144
|
+
v-if="link"
|
|
145
|
+
class="nav-link font-weight-bold d-flex w-100 h-100 justify-content-center align-items-center"
|
|
146
|
+
:href="link"
|
|
147
|
+
:target="newTab ? '_blank' : null">
|
|
148
|
+
{{ name }}
|
|
149
|
+
</es-nav-bar-link>
|
|
150
|
+
<div
|
|
151
|
+
v-else
|
|
152
|
+
class="h-100">
|
|
153
|
+
<span
|
|
154
|
+
class="nav-item justify-content-center align-items-center d-flex font-weight-boldest h-100 text-decoration-none w-100">
|
|
155
|
+
{{ name }}
|
|
156
|
+
</span>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="col-2"> </div>
|
|
160
|
+
</li>
|
|
161
|
+
<!-- @vue-expect-error -->
|
|
162
|
+
<li
|
|
163
|
+
v-for="item in items"
|
|
164
|
+
:key="item.name">
|
|
165
|
+
<!-- @vue-expect-error -->
|
|
166
|
+
<es-nav-bar-link
|
|
167
|
+
class="dropdown-item nav-item nav-item-border-mobile nav-link d-flex align-items-center ml-lg-0 px-lg-0 py-lg-50"
|
|
168
|
+
:class="{ 'font-weight-bold': item.emphasize }"
|
|
169
|
+
:href="item.link"
|
|
170
|
+
:target="item.newTab ? '_blank' : null">
|
|
171
|
+
<!-- @vue-expect-error -->
|
|
172
|
+
{{ item.name }}
|
|
173
|
+
</es-nav-bar-link>
|
|
174
|
+
</li>
|
|
175
|
+
</ul>
|
|
176
|
+
</div>
|
|
177
|
+
<!-- mobile link, shown only if we have a link and don't want to show child items on mobile -->
|
|
178
|
+
<es-nav-bar-link
|
|
179
|
+
v-if="link"
|
|
180
|
+
class="nav-item nav-item-menu nav-item-border-mobile nav-link d-lg-none w-100 text-decoration-none"
|
|
181
|
+
:class="{
|
|
182
|
+
'd-none': showItemsOnMobile,
|
|
183
|
+
'd-block': !showItemsOnMobile,
|
|
184
|
+
}"
|
|
185
|
+
:href="link"
|
|
186
|
+
:target="newTab ? '_blank' : null">
|
|
187
|
+
<span class="d-block eyebrow link-name">
|
|
188
|
+
{{ name }}
|
|
189
|
+
</span>
|
|
190
|
+
<span
|
|
191
|
+
v-if="subHeading"
|
|
192
|
+
class="d-block font-size-sm link-subheading">
|
|
193
|
+
{{ subHeading }}
|
|
194
|
+
</span>
|
|
195
|
+
</es-nav-bar-link>
|
|
196
|
+
</li>
|
|
197
|
+
</template>
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export default {
|
|
3
|
+
name: 'EsNavBar',
|
|
4
|
+
props: {
|
|
5
|
+
accountContent: {
|
|
6
|
+
type: Object,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
globalContent: {
|
|
10
|
+
type: Object,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
mounted() {
|
|
15
|
+
// CUSTOM GLOBAL-NAV SCRIPT STARTS
|
|
16
|
+
|
|
17
|
+
// Function to collapse all open menus
|
|
18
|
+
function uncheck_menus() {
|
|
19
|
+
document.querySelectorAll('.menu-checkbox').forEach((element) => {
|
|
20
|
+
const checkbox = element;
|
|
21
|
+
// @ts-expect-error legacy code
|
|
22
|
+
checkbox.checked = false;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Create an overlay to obscure page contents
|
|
27
|
+
const overlay = document.querySelector('.content-overlay');
|
|
28
|
+
|
|
29
|
+
// Function to show/hide overlay
|
|
30
|
+
function show_overlay(overlay_visible: boolean) {
|
|
31
|
+
if (overlay_visible) {
|
|
32
|
+
// @ts-expect-error legacy code
|
|
33
|
+
overlay.classList.add('show');
|
|
34
|
+
} else {
|
|
35
|
+
// @ts-expect-error legacy code
|
|
36
|
+
overlay.classList.remove('show');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Show overlay and lock scrolling on body when menu is open
|
|
41
|
+
function show_mobile_menus() {
|
|
42
|
+
show_overlay(true);
|
|
43
|
+
document.body.style.overflow = 'hidden';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Close all submenus, hide overlay, and unlock scrolling when menu is closed
|
|
47
|
+
function collapse_mobile_menus() {
|
|
48
|
+
uncheck_menus();
|
|
49
|
+
show_overlay(false);
|
|
50
|
+
document.body.style.overflow = 'visible';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Create a checkbox used to determine if any mobile menus are open
|
|
54
|
+
const mainMenuCheckbox = document.querySelector('.main-menu-checkbox');
|
|
55
|
+
const accountMenuCheckbox = document.querySelector('.account-menu-checkbox');
|
|
56
|
+
|
|
57
|
+
// Collapse all open menus on window resize
|
|
58
|
+
window.addEventListener('resize', () => {
|
|
59
|
+
// @ts-expect-error legacy code
|
|
60
|
+
if (mainMenuCheckbox.checked || accountMenuCheckbox.checked) {
|
|
61
|
+
collapse_mobile_menus();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Collapse all open menus on overlay click
|
|
66
|
+
// @ts-expect-error legacy code
|
|
67
|
+
overlay.addEventListener('click', () => {
|
|
68
|
+
collapse_mobile_menus();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Show overlay on hovers for desktop only
|
|
72
|
+
document
|
|
73
|
+
.querySelectorAll(
|
|
74
|
+
// eslint-disable-next-line max-len
|
|
75
|
+
'.nav-es-container .nav-item .dropdown-toggle, .nav-es-container .nav-item .dropdown-menu, .nav-es-container .nav-item.has-dropdown',
|
|
76
|
+
)
|
|
77
|
+
.forEach((element) => {
|
|
78
|
+
element.addEventListener('mouseover', () => {
|
|
79
|
+
show_overlay(true);
|
|
80
|
+
});
|
|
81
|
+
element.addEventListener('mouseout', () => {
|
|
82
|
+
// @ts-expect-error legacy code
|
|
83
|
+
// Hide overlay on mouseout on desktop not mobile
|
|
84
|
+
show_overlay(mainMenuCheckbox.checked || accountMenuCheckbox.checked);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// @ts-expect-error legacy code
|
|
89
|
+
// Toggle menu display on main menu open/close
|
|
90
|
+
mainMenuCheckbox.addEventListener('change', (event) => {
|
|
91
|
+
// @ts-expect-error legacy code
|
|
92
|
+
if (event.target.checked) {
|
|
93
|
+
show_mobile_menus();
|
|
94
|
+
} else {
|
|
95
|
+
collapse_mobile_menus();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// @ts-expect-error legacy code
|
|
100
|
+
// Toggle menu display on account menu open/close
|
|
101
|
+
accountMenuCheckbox.addEventListener('change', (event) => {
|
|
102
|
+
// @ts-expect-error legacy code
|
|
103
|
+
if (event.target.checked) {
|
|
104
|
+
show_mobile_menus();
|
|
105
|
+
} else {
|
|
106
|
+
collapse_mobile_menus();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// get logged in/out state and display appropriate menu
|
|
111
|
+
const menuDisplay = ({ loggedOut }: { loggedOut: boolean }) => {
|
|
112
|
+
if (loggedOut) {
|
|
113
|
+
// logged out so allow loggedOut menu and the compare buttons to be visible
|
|
114
|
+
document.querySelectorAll('.nav-es-container .loggedOut').forEach((element) => {
|
|
115
|
+
// @ts-expect-error legacy code
|
|
116
|
+
// eslint-disable-next-line no-param-reassign
|
|
117
|
+
element.style.display = null;
|
|
118
|
+
});
|
|
119
|
+
} else {
|
|
120
|
+
// logged in so allow logged in menu to be visible, and show name with appropriate layout
|
|
121
|
+
document.querySelectorAll('.nav-es-container .loggedIn').forEach((element) => {
|
|
122
|
+
// @ts-expect-error legacy code
|
|
123
|
+
// eslint-disable-next-line no-param-reassign
|
|
124
|
+
element.style.display = null;
|
|
125
|
+
});
|
|
126
|
+
// @ts-expect-error legacy code
|
|
127
|
+
document.querySelector('.nav-es-container .icon-dropdown .dropdown-toggle').style.display = 'flex';
|
|
128
|
+
const selector = '.nav-es-container .icon-dropdown .dropdown-toggle .first-name';
|
|
129
|
+
document.querySelectorAll(selector).forEach((element) => {
|
|
130
|
+
// @ts-expect-error legacy code
|
|
131
|
+
// eslint-disable-next-line no-param-reassign
|
|
132
|
+
element.style.display = 'block';
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
fetch('/api/account-first-name/', {
|
|
138
|
+
headers: { Accept: 'application/json' },
|
|
139
|
+
method: 'GET',
|
|
140
|
+
})
|
|
141
|
+
.then((response) => response.json())
|
|
142
|
+
.then((data) => {
|
|
143
|
+
const name = data?.first_name || null;
|
|
144
|
+
const selector = '.nav-es-container .icon-dropdown .dropdown-toggle .first-name';
|
|
145
|
+
document.querySelectorAll(selector).forEach((element) => {
|
|
146
|
+
// eslint-disable-next-line no-param-reassign
|
|
147
|
+
element.innerHTML = name;
|
|
148
|
+
});
|
|
149
|
+
menuDisplay({ loggedOut: name === null });
|
|
150
|
+
})
|
|
151
|
+
.catch((e) => {
|
|
152
|
+
// eslint-disable-next-line no-console
|
|
153
|
+
console.log('error', e);
|
|
154
|
+
menuDisplay({ loggedOut: true });
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// closes mobile menus upon navigating 'back' to the site
|
|
158
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
|
|
159
|
+
window.addEventListener('pageshow', () => {
|
|
160
|
+
collapse_mobile_menus();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// set up options for sticky nav intersection observer
|
|
164
|
+
const intersectionOptions = {
|
|
165
|
+
rootMargin: '0px',
|
|
166
|
+
threshold: 0.0,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// set up callback for sticky nav intersection observer
|
|
170
|
+
const intersectionCallback = (entries: IntersectionObserverEntry[]) => {
|
|
171
|
+
entries.forEach((entry) => {
|
|
172
|
+
if (entry.isIntersecting) {
|
|
173
|
+
entry.target.classList.remove('scrolled');
|
|
174
|
+
} else {
|
|
175
|
+
entry.target.classList.add('scrolled');
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// initialize intersection observer to detect when nav scrolls out of viewport
|
|
181
|
+
// https://www.smashingmagazine.com/2021/07/dynamic-header-intersection-observer/
|
|
182
|
+
const observer = new IntersectionObserver(intersectionCallback, intersectionOptions);
|
|
183
|
+
const targetEl = document.querySelector('#nav-main');
|
|
184
|
+
// @ts-expect-error legacy code
|
|
185
|
+
observer.observe(targetEl);
|
|
186
|
+
|
|
187
|
+
// CUSTOM GLOBAL-NAV SCRIPT ENDS
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
</script>
|
|
191
|
+
|
|
192
|
+
<template>
|
|
193
|
+
<div
|
|
194
|
+
id="nav-main"
|
|
195
|
+
class="nav-es-container">
|
|
196
|
+
<div class="content-overlay" />
|
|
197
|
+
<nav class="nav-es-global navbar navbar-expand navbar-light py-0 font-size-base">
|
|
198
|
+
<!-- mobile hamburger menu button -->
|
|
199
|
+
<div class="d-flex d-lg-none col-2 px-0">
|
|
200
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
201
|
+
<label
|
|
202
|
+
for="data--main-menu"
|
|
203
|
+
class="mb-0">
|
|
204
|
+
<icon-hamburger class="menu-toggle align-self-center" />
|
|
205
|
+
<span class="sr-only">
|
|
206
|
+
{{ globalContent.mobileNavButtonAltText }}
|
|
207
|
+
</span>
|
|
208
|
+
</label>
|
|
209
|
+
</div>
|
|
210
|
+
<!-- mobile logo -->
|
|
211
|
+
<es-nav-bar-link
|
|
212
|
+
class="d-flex d-lg-none col-8 align-self-center justify-content-center px-0"
|
|
213
|
+
:href="globalContent.home.link">
|
|
214
|
+
<div class="nav-es-logo-mobile align-items-center d-flex">
|
|
215
|
+
<slot name="logo" />
|
|
216
|
+
</div>
|
|
217
|
+
<span class="sr-only">
|
|
218
|
+
{{ globalContent.home.name }}
|
|
219
|
+
</span>
|
|
220
|
+
</es-nav-bar-link>
|
|
221
|
+
<!-- mobile account menu trigger -->
|
|
222
|
+
<div class="d-flex d-lg-none justify-content-end col-2 px-0">
|
|
223
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
224
|
+
<label
|
|
225
|
+
class="mb-0 text-decoration-none"
|
|
226
|
+
for="data--account-menu">
|
|
227
|
+
<icon-person class="align-self-center account-icon" />
|
|
228
|
+
<span class="sr-only">
|
|
229
|
+
{{ accountContent.mobileAccountButtonAltText }}
|
|
230
|
+
</span>
|
|
231
|
+
</label>
|
|
232
|
+
</div>
|
|
233
|
+
<input
|
|
234
|
+
id="data--main-menu"
|
|
235
|
+
class="menu-checkbox main-menu-checkbox"
|
|
236
|
+
aria-labelledby="data--main-menu"
|
|
237
|
+
type="checkbox" />
|
|
238
|
+
<!-- first-level menu on mobile, the whole nav on desktop-->
|
|
239
|
+
<div
|
|
240
|
+
id="navbarNavDropdown"
|
|
241
|
+
class="menu top-level-menu align-items-start d-flex flex-grow-1">
|
|
242
|
+
<!-- mobile menu header -->
|
|
243
|
+
<div class="menu-header d-lg-none d-flex align-items-center justify-content-center h-100 mb-50">
|
|
244
|
+
<div class="col-3" />
|
|
245
|
+
<div class="col-6 align-self-center text-center py-100">
|
|
246
|
+
<div class="nav-es-logo-mobile align-items-center d-flex">
|
|
247
|
+
<slot name="logo" />
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<div class="d-flex col-3 justify-content-end">
|
|
251
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
252
|
+
<label
|
|
253
|
+
for="data--main-menu"
|
|
254
|
+
class="mb-0">
|
|
255
|
+
<icon-x class="menu-toggle align-self-center" />
|
|
256
|
+
<span class="sr-only">
|
|
257
|
+
{{ globalContent.mobileCloseButtonAltText }}
|
|
258
|
+
</span>
|
|
259
|
+
</label>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
<div class="navbar-nav d-flex flex-column w-100">
|
|
263
|
+
<!-- top-level items on mobile, full top bar on desktop -->
|
|
264
|
+
<es-container
|
|
265
|
+
class="align-items-start d-flex flex-lg-nowrap justify-content-between top-level-nav">
|
|
266
|
+
<es-nav-bar-link
|
|
267
|
+
class="navbar-brand d-none d-lg-block"
|
|
268
|
+
:href="globalContent.home.link">
|
|
269
|
+
<div class="nav-es-logo-desktop pt-100">
|
|
270
|
+
<slot name="logo" />
|
|
271
|
+
</div>
|
|
272
|
+
<span class="sr-only">
|
|
273
|
+
{{ globalContent.home.name }}
|
|
274
|
+
</span>
|
|
275
|
+
</es-nav-bar-link>
|
|
276
|
+
<!-- top level menus -->
|
|
277
|
+
<es-nav-bar-top-level-menu
|
|
278
|
+
v-for="topLevelMenu in globalContent.topLevelMenus"
|
|
279
|
+
:key="topLevelMenu.name"
|
|
280
|
+
:home-name="globalContent.home.name"
|
|
281
|
+
:home-link="globalContent.home.link"
|
|
282
|
+
:close-button-text="globalContent.mobileCloseButtonAltText"
|
|
283
|
+
:featured-article="topLevelMenu.featuredArticle"
|
|
284
|
+
:icon="topLevelMenu.icon"
|
|
285
|
+
:link="topLevelMenu.link"
|
|
286
|
+
:main-menu-text="globalContent.mainMenuText"
|
|
287
|
+
:name="topLevelMenu.name"
|
|
288
|
+
:sub-heading="topLevelMenu.subHeading"
|
|
289
|
+
:topics="topLevelMenu.topics">
|
|
290
|
+
<template #logo>
|
|
291
|
+
<slot name="logo" />
|
|
292
|
+
</template>
|
|
293
|
+
</es-nav-bar-top-level-menu>
|
|
294
|
+
<!-- desktop account menu -->
|
|
295
|
+
<es-nav-bar-account-menu
|
|
296
|
+
:auth-items="accountContent.loggedIn.items"
|
|
297
|
+
class="d-none d-lg-block pt-100"
|
|
298
|
+
:logged-out="accountContent.loggedOut" />
|
|
299
|
+
</es-container>
|
|
300
|
+
<!-- mobile+desktop product menus -->
|
|
301
|
+
<es-container class="d-flex flex-lg-nowrap justify-content-lg-end product-menu">
|
|
302
|
+
<div class="row">
|
|
303
|
+
<es-nav-bar-product-menu
|
|
304
|
+
v-for="product in globalContent.products"
|
|
305
|
+
:key="product.name"
|
|
306
|
+
:home-name="globalContent.home.name"
|
|
307
|
+
:home-link="globalContent.home.link"
|
|
308
|
+
:close-button-text="globalContent.mobileCloseButtonAltText"
|
|
309
|
+
:featured-article="product.featuredArticle"
|
|
310
|
+
:items="product.items"
|
|
311
|
+
:link="product.link"
|
|
312
|
+
:main-menu-text="globalContent.mainMenuText"
|
|
313
|
+
:new-tab="product.newTab"
|
|
314
|
+
:name="product.name"
|
|
315
|
+
:see-all-text="globalContent.seeAllText"
|
|
316
|
+
:topics="product.topics">
|
|
317
|
+
<template #logo>
|
|
318
|
+
<slot name="logo" />
|
|
319
|
+
</template>
|
|
320
|
+
</es-nav-bar-product-menu>
|
|
321
|
+
</div>
|
|
322
|
+
</es-container>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
<!-- mobile account menu checkbox -->
|
|
326
|
+
<input
|
|
327
|
+
id="data--account-menu"
|
|
328
|
+
class="menu-checkbox account-menu-checkbox"
|
|
329
|
+
aria-labelledby="data--account-menu"
|
|
330
|
+
type="checkbox" />
|
|
331
|
+
<!-- mobile account menu -->
|
|
332
|
+
<div class="menu top-level-menu align-items-start d-flex d-lg-none flex-grow-1">
|
|
333
|
+
<!-- menu header -->
|
|
334
|
+
<div class="menu-header d-lg-none d-flex align-items-center justify-content-center h-100">
|
|
335
|
+
<div class="col-3" />
|
|
336
|
+
<div class="col-6 align-self-center text-center py-100">
|
|
337
|
+
<div class="nav-es-logo-mobile align-items-center d-flex">
|
|
338
|
+
<slot name="logo" />
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
<div class="d-flex col-3 justify-content-end">
|
|
342
|
+
<!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
|
|
343
|
+
<label
|
|
344
|
+
for="data--account-menu"
|
|
345
|
+
class="mb-0">
|
|
346
|
+
<icon-x class="menu-toggle align-self-center" />
|
|
347
|
+
<span class="sr-only">
|
|
348
|
+
{{ globalContent.mobileCloseButtonAltText }}
|
|
349
|
+
</span>
|
|
350
|
+
</label>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
<!-- logged in menu -->
|
|
354
|
+
<ul
|
|
355
|
+
class="loggedIn navbar-nav w-100"
|
|
356
|
+
style="display: none">
|
|
357
|
+
<li
|
|
358
|
+
v-for="item in accountContent.loggedIn.items"
|
|
359
|
+
:key="item.name">
|
|
360
|
+
<es-nav-bar-link
|
|
361
|
+
class="dropdown-item nav-item nav-item-border-mobile nav-link align-items-center d-flex px-lg-100 py-lg-50 font-weight-bold"
|
|
362
|
+
:href="item.link">
|
|
363
|
+
{{ item.name }}
|
|
364
|
+
</es-nav-bar-link>
|
|
365
|
+
</li>
|
|
366
|
+
</ul>
|
|
367
|
+
<!-- logged out menu -->
|
|
368
|
+
<ul
|
|
369
|
+
class="loggedOut navbar-nav w-100"
|
|
370
|
+
style="display: none">
|
|
371
|
+
<li>
|
|
372
|
+
<es-button
|
|
373
|
+
:href="accountContent.loggedOut.signIn.link"
|
|
374
|
+
class="m-100 w-100 text-white font-weight-bold">
|
|
375
|
+
{{ accountContent.loggedOut.signIn.name }}
|
|
376
|
+
</es-button>
|
|
377
|
+
</li>
|
|
378
|
+
<li class="d-flex justify-content-center">
|
|
379
|
+
<es-button
|
|
380
|
+
:href="accountContent.loggedOut.createAccount.link"
|
|
381
|
+
:outline="true"
|
|
382
|
+
class="mx-100 w-100 font-weight-bold">
|
|
383
|
+
{{ accountContent.loggedOut.createAccount.name }}
|
|
384
|
+
</es-button>
|
|
385
|
+
</li>
|
|
386
|
+
</ul>
|
|
387
|
+
</div>
|
|
388
|
+
</nav>
|
|
389
|
+
<!-- sticky nav bar -->
|
|
390
|
+
<nav class="nav-es-sticky bg-white d-none d-lg-block position-fixed py-25">
|
|
391
|
+
<es-container class="align-items-center d-flex justify-content-between">
|
|
392
|
+
<!-- EnergySage logo -->
|
|
393
|
+
<es-nav-bar-link
|
|
394
|
+
class="navbar-brand d-none d-lg-block"
|
|
395
|
+
:href="globalContent.home.link">
|
|
396
|
+
<div class="nav-es-logo-desktop-sticky">
|
|
397
|
+
<slot name="logo" />
|
|
398
|
+
</div>
|
|
399
|
+
<span class="sr-only">
|
|
400
|
+
{{ globalContent.home.name }}
|
|
401
|
+
</span>
|
|
402
|
+
</es-nav-bar-link>
|
|
403
|
+
<!-- desktop account menu -->
|
|
404
|
+
<es-nav-bar-account-menu
|
|
405
|
+
:auth-items="accountContent.loggedIn.items"
|
|
406
|
+
class="d-none d-lg-block"
|
|
407
|
+
:logged-out="accountContent.loggedOut" />
|
|
408
|
+
</es-container>
|
|
409
|
+
</nav>
|
|
410
|
+
</div>
|
|
411
|
+
</template>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import Paginator from 'primevue/paginator';
|
|
3
|
+
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
totalRows: {
|
|
6
|
+
type: Number,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
perPage: {
|
|
10
|
+
type: Number,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
listId: {
|
|
14
|
+
type: String,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
align: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: 'left',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const model = defineModel<number>();
|
|
24
|
+
const first = ref();
|
|
25
|
+
|
|
26
|
+
watch(model, (newVal) => {
|
|
27
|
+
// @ts-expect-error I don't know
|
|
28
|
+
first.value = (newVal - 1) * props.perPage;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const updatePage = (newFirst: number) => {
|
|
32
|
+
model.value = newFirst / props.perPage + 1;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const passThrough = {
|
|
36
|
+
root: {
|
|
37
|
+
class: [
|
|
38
|
+
'pagination',
|
|
39
|
+
{ 'justify-content-center': props.align === 'center', 'justify-content-end': props.align === 'right' },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
firstPageButton: { class: 'paginator-button' },
|
|
43
|
+
previousPageButton: { class: 'paginator-button' },
|
|
44
|
+
nextPageButton: { class: 'paginator-button' },
|
|
45
|
+
lastPageButton: { class: 'paginator-button' },
|
|
46
|
+
current: { class: 'px-100 current-page-report' },
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<paginator
|
|
52
|
+
v-model:first="first"
|
|
53
|
+
:rows="perPage"
|
|
54
|
+
:total-records="totalRows"
|
|
55
|
+
template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"
|
|
56
|
+
current-page-report-template="{currentPage} of {totalPages}"
|
|
57
|
+
:aria-controls="listId"
|
|
58
|
+
:pt="passThrough"
|
|
59
|
+
@update:first="updatePage">
|
|
60
|
+
<template #prevpagelinkicon>
|
|
61
|
+
<icon-chevron-left />
|
|
62
|
+
</template>
|
|
63
|
+
<template #nextpagelinkicon>
|
|
64
|
+
<icon-chevron-right />
|
|
65
|
+
</template>
|
|
66
|
+
</paginator>
|
|
67
|
+
</template>
|