@energysage/es-ds-components 3.0.7 → 3.0.8

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.
@@ -1,408 +0,0 @@
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
- '.nav-es-container .nav-item .dropdown-toggle, .nav-es-container .nav-item .dropdown-menu, .nav-es-container .nav-item.has-dropdown',
75
- )
76
- .forEach((element) => {
77
- element.addEventListener('mouseover', () => {
78
- show_overlay(true);
79
- });
80
- element.addEventListener('mouseout', () => {
81
- // @ts-expect-error legacy code
82
- // Hide overlay on mouseout on desktop not mobile
83
- show_overlay(mainMenuCheckbox.checked || accountMenuCheckbox.checked);
84
- });
85
- });
86
-
87
- // @ts-expect-error legacy code
88
- // Toggle menu display on main menu open/close
89
- mainMenuCheckbox.addEventListener('change', (event) => {
90
- // @ts-expect-error legacy code
91
- if (event.target.checked) {
92
- show_mobile_menus();
93
- } else {
94
- collapse_mobile_menus();
95
- }
96
- });
97
-
98
- // @ts-expect-error legacy code
99
- // Toggle menu display on account menu open/close
100
- accountMenuCheckbox.addEventListener('change', (event) => {
101
- // @ts-expect-error legacy code
102
- if (event.target.checked) {
103
- show_mobile_menus();
104
- } else {
105
- collapse_mobile_menus();
106
- }
107
- });
108
-
109
- // get logged in/out state and display appropriate menu
110
- const menuDisplay = ({ loggedOut }: { loggedOut: boolean }) => {
111
- if (loggedOut) {
112
- // logged out so allow loggedOut menu and the compare buttons to be visible
113
- document.querySelectorAll('.nav-es-container .loggedOut').forEach((element) => {
114
- // @ts-expect-error legacy code
115
-
116
- element.style.display = null;
117
- });
118
- } else {
119
- // logged in so allow logged in menu to be visible, and show name with appropriate layout
120
- document.querySelectorAll('.nav-es-container .loggedIn').forEach((element) => {
121
- // @ts-expect-error legacy code
122
-
123
- element.style.display = null;
124
- });
125
- // @ts-expect-error legacy code
126
- document.querySelector('.nav-es-container .icon-dropdown .dropdown-toggle').style.display = 'flex';
127
- const selector = '.nav-es-container .icon-dropdown .dropdown-toggle .first-name';
128
- document.querySelectorAll(selector).forEach((element) => {
129
- // @ts-expect-error legacy code
130
-
131
- element.style.display = 'block';
132
- });
133
- }
134
- };
135
-
136
- fetch('/api/account-first-name/', {
137
- headers: { Accept: 'application/json' },
138
- method: 'GET',
139
- })
140
- .then((response) => response.json())
141
- .then((data) => {
142
- const name = data?.first_name || null;
143
- const selector = '.nav-es-container .icon-dropdown .dropdown-toggle .first-name';
144
- document.querySelectorAll(selector).forEach((element) => {
145
- element.innerHTML = name;
146
- });
147
- menuDisplay({ loggedOut: name === null });
148
- })
149
- .catch((e) => {
150
- console.log('error', e);
151
- menuDisplay({ loggedOut: true });
152
- });
153
-
154
- // closes mobile menus upon navigating 'back' to the site
155
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
156
- window.addEventListener('pageshow', () => {
157
- collapse_mobile_menus();
158
- });
159
-
160
- // set up options for sticky nav intersection observer
161
- const intersectionOptions = {
162
- rootMargin: '0px',
163
- threshold: 0.0,
164
- };
165
-
166
- // set up callback for sticky nav intersection observer
167
- const intersectionCallback = (entries: IntersectionObserverEntry[]) => {
168
- entries.forEach((entry) => {
169
- if (entry.isIntersecting) {
170
- entry.target.classList.remove('scrolled');
171
- } else {
172
- entry.target.classList.add('scrolled');
173
- }
174
- });
175
- };
176
-
177
- // initialize intersection observer to detect when nav scrolls out of viewport
178
- // https://www.smashingmagazine.com/2021/07/dynamic-header-intersection-observer/
179
- const observer = new IntersectionObserver(intersectionCallback, intersectionOptions);
180
- const targetEl = document.querySelector('#nav-main');
181
- // @ts-expect-error legacy code
182
- observer.observe(targetEl);
183
-
184
- // CUSTOM GLOBAL-NAV SCRIPT ENDS
185
- },
186
- };
187
- </script>
188
-
189
- <template>
190
- <div
191
- id="nav-main"
192
- class="nav-es-container">
193
- <div class="content-overlay" />
194
- <nav class="nav-es-global navbar navbar-expand navbar-light py-0 font-size-base">
195
- <!-- mobile hamburger menu button -->
196
- <div class="d-flex d-lg-none col-2 px-0">
197
- <!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
198
- <label
199
- for="data--main-menu"
200
- class="mb-0">
201
- <icon-hamburger class="menu-toggle align-self-center" />
202
- <span class="sr-only">
203
- {{ globalContent.mobileNavButtonAltText }}
204
- </span>
205
- </label>
206
- </div>
207
- <!-- mobile logo -->
208
- <es-nav-bar-link
209
- class="d-flex d-lg-none col-8 align-self-center justify-content-center px-0"
210
- :href="globalContent.home.link">
211
- <div class="nav-es-logo-mobile align-items-center d-flex">
212
- <slot name="logo" />
213
- </div>
214
- <span class="sr-only">
215
- {{ globalContent.home.name }}
216
- </span>
217
- </es-nav-bar-link>
218
- <!-- mobile account menu trigger -->
219
- <div class="d-flex d-lg-none justify-content-end col-2 px-0">
220
- <!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
221
- <label
222
- class="mb-0 text-decoration-none"
223
- for="data--account-menu">
224
- <icon-person class="align-self-center account-icon" />
225
- <span class="sr-only">
226
- {{ accountContent.mobileAccountButtonAltText }}
227
- </span>
228
- </label>
229
- </div>
230
- <input
231
- id="data--main-menu"
232
- class="menu-checkbox main-menu-checkbox"
233
- aria-labelledby="data--main-menu"
234
- type="checkbox" />
235
- <!-- first-level menu on mobile, the whole nav on desktop-->
236
- <div
237
- id="navbarNavDropdown"
238
- class="menu top-level-menu align-items-start d-flex flex-grow-1">
239
- <!-- mobile menu header -->
240
- <div class="menu-header d-lg-none d-flex align-items-center justify-content-center h-100 mb-50">
241
- <div class="col-3" />
242
- <div class="col-6 align-self-center text-center py-100">
243
- <div class="nav-es-logo-mobile align-items-center d-flex">
244
- <slot name="logo" />
245
- </div>
246
- </div>
247
- <div class="d-flex col-3 justify-content-end">
248
- <!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
249
- <label
250
- for="data--main-menu"
251
- class="mb-0">
252
- <icon-x class="menu-toggle align-self-center" />
253
- <span class="sr-only">
254
- {{ globalContent.mobileCloseButtonAltText }}
255
- </span>
256
- </label>
257
- </div>
258
- </div>
259
- <div class="navbar-nav d-flex flex-column w-100">
260
- <!-- top-level items on mobile, full top bar on desktop -->
261
- <es-container
262
- class="align-items-start d-flex flex-lg-nowrap justify-content-between top-level-nav">
263
- <es-nav-bar-link
264
- class="navbar-brand d-none d-lg-block"
265
- :href="globalContent.home.link">
266
- <div class="nav-es-logo-desktop pt-100">
267
- <slot name="logo" />
268
- </div>
269
- <span class="sr-only">
270
- {{ globalContent.home.name }}
271
- </span>
272
- </es-nav-bar-link>
273
- <!-- top level menus -->
274
- <es-nav-bar-top-level-menu
275
- v-for="topLevelMenu in globalContent.topLevelMenus"
276
- :key="topLevelMenu.name"
277
- :home-name="globalContent.home.name"
278
- :home-link="globalContent.home.link"
279
- :close-button-text="globalContent.mobileCloseButtonAltText"
280
- :featured-article="topLevelMenu.featuredArticle"
281
- :icon="topLevelMenu.icon"
282
- :link="topLevelMenu.link"
283
- :main-menu-text="globalContent.mainMenuText"
284
- :name="topLevelMenu.name"
285
- :sub-heading="topLevelMenu.subHeading"
286
- :topics="topLevelMenu.topics">
287
- <template #logo>
288
- <slot name="logo" />
289
- </template>
290
- </es-nav-bar-top-level-menu>
291
- <!-- desktop account menu -->
292
- <es-nav-bar-account-menu
293
- :auth-items="accountContent.loggedIn.items"
294
- class="d-none d-lg-block pt-100"
295
- :logged-out="accountContent.loggedOut" />
296
- </es-container>
297
- <!-- mobile+desktop product menus -->
298
- <es-container class="d-flex flex-lg-nowrap justify-content-lg-end product-menu">
299
- <div class="row">
300
- <es-nav-bar-product-menu
301
- v-for="product in globalContent.products"
302
- :key="product.name"
303
- :home-name="globalContent.home.name"
304
- :home-link="globalContent.home.link"
305
- :close-button-text="globalContent.mobileCloseButtonAltText"
306
- :featured-article="product.featuredArticle"
307
- :items="product.items"
308
- :link="product.link"
309
- :main-menu-text="globalContent.mainMenuText"
310
- :new-tab="product.newTab"
311
- :name="product.name"
312
- :see-all-text="globalContent.seeAllText"
313
- :topics="product.topics">
314
- <template #logo>
315
- <slot name="logo" />
316
- </template>
317
- </es-nav-bar-product-menu>
318
- </div>
319
- </es-container>
320
- </div>
321
- </div>
322
- <!-- mobile account menu checkbox -->
323
- <input
324
- id="data--account-menu"
325
- class="menu-checkbox account-menu-checkbox"
326
- aria-labelledby="data--account-menu"
327
- type="checkbox" />
328
- <!-- mobile account menu -->
329
- <div class="menu top-level-menu align-items-start d-flex d-lg-none flex-grow-1">
330
- <!-- menu header -->
331
- <div class="menu-header d-lg-none d-flex align-items-center justify-content-center h-100">
332
- <div class="col-3" />
333
- <div class="col-6 align-self-center text-center py-100">
334
- <div class="nav-es-logo-mobile align-items-center d-flex">
335
- <slot name="logo" />
336
- </div>
337
- </div>
338
- <div class="d-flex col-3 justify-content-end">
339
- <!-- eslint-disable-next-line vuejs-accessibility/label-has-for -->
340
- <label
341
- for="data--account-menu"
342
- class="mb-0">
343
- <icon-x class="menu-toggle align-self-center" />
344
- <span class="sr-only">
345
- {{ globalContent.mobileCloseButtonAltText }}
346
- </span>
347
- </label>
348
- </div>
349
- </div>
350
- <!-- logged in menu -->
351
- <ul
352
- class="loggedIn navbar-nav w-100"
353
- style="display: none">
354
- <li
355
- v-for="item in accountContent.loggedIn.items"
356
- :key="item.name">
357
- <es-nav-bar-link
358
- 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"
359
- :href="item.link">
360
- {{ item.name }}
361
- </es-nav-bar-link>
362
- </li>
363
- </ul>
364
- <!-- logged out menu -->
365
- <ul
366
- class="loggedOut navbar-nav w-100"
367
- style="display: none">
368
- <li>
369
- <es-button
370
- :href="accountContent.loggedOut.signIn.link"
371
- class="m-100 w-100 text-white font-weight-bold">
372
- {{ accountContent.loggedOut.signIn.name }}
373
- </es-button>
374
- </li>
375
- <li class="d-flex justify-content-center">
376
- <es-button
377
- :href="accountContent.loggedOut.createAccount.link"
378
- :outline="true"
379
- class="mx-100 w-100 font-weight-bold">
380
- {{ accountContent.loggedOut.createAccount.name }}
381
- </es-button>
382
- </li>
383
- </ul>
384
- </div>
385
- </nav>
386
- <!-- sticky nav bar -->
387
- <nav class="nav-es-sticky bg-white d-none d-lg-block position-fixed py-25">
388
- <es-container class="align-items-center d-flex justify-content-between">
389
- <!-- EnergySage logo -->
390
- <es-nav-bar-link
391
- class="navbar-brand d-none d-lg-block"
392
- :href="globalContent.home.link">
393
- <div class="nav-es-logo-desktop-sticky">
394
- <slot name="logo" />
395
- </div>
396
- <span class="sr-only">
397
- {{ globalContent.home.name }}
398
- </span>
399
- </es-nav-bar-link>
400
- <!-- desktop account menu -->
401
- <es-nav-bar-account-menu
402
- :auth-items="accountContent.loggedIn.items"
403
- class="d-none d-lg-block"
404
- :logged-out="accountContent.loggedOut" />
405
- </es-container>
406
- </nav>
407
- </div>
408
- </template>
@@ -1,91 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
-
3
- // keeping COMMUNITY_SOLAR_DOMAIN, HEAT_PUMPS_DOMAIN and NEWS_DOMAIN for now to keep function argument order intact
4
- // and to minimize breaking change to consuming applications, but they are now deprecated in this function
5
- export default (
6
- ES_DOMAIN = process.env.ES_DOMAIN || 'https://www.energysage.com',
7
- NEWS_DOMAIN = process.env.NEWS_DOMAIN || 'https://www.energysage.com',
8
- COMMUNITY_SOLAR_DOMAIN = process.env.COMMUNITY_SOLAR_DOMAIN || 'https://communitysolar.energysage.com',
9
- HEAT_PUMPS_DOMAIN = process.env.HEAT_PUMPS_DOMAIN || 'https://heatpumps.energysage.com',
10
- ) => ({
11
- banner: {
12
- headline: 'Make an impact.',
13
- subHeadline: "It's never been easier.",
14
- body: `We developed our one-of-a-kind marketplace with funding from the U.S. Department of Energy to make
15
- clean home energy solutions affordable and accessible to all.`,
16
- },
17
- home: {
18
- name: 'EnergySage',
19
- link: ES_DOMAIN,
20
- },
21
- columns: [
22
- // TODO: remove new tab option once other verticals adopt global nav
23
- {
24
- title: 'Our offerings',
25
- links: [
26
- { text: 'Home solar', url: `${ES_DOMAIN}/shop/home-solar/` },
27
- { text: 'Community solar', url: `${ES_DOMAIN}/shop/community-solar/` },
28
- { text: 'Heating & cooling', url: `${ES_DOMAIN}/shop/heat-pumps/` },
29
- { text: 'Backup power', url: `${ES_DOMAIN}/energy-storage/` },
30
- { text: 'EV charging', url: `${ES_DOMAIN}/ev-charging/` },
31
- { text: 'For your business', url: `${ES_DOMAIN}/businesses/` },
32
- { text: 'Other energy options', url: `${ES_DOMAIN}/other-clean-options/` },
33
- ],
34
- },
35
- {
36
- title: 'Resources',
37
- links: [
38
- { text: 'Solar calculator', url: `${ES_DOMAIN}/solar/calculator/` },
39
- { text: 'Solar rebates', url: `${ES_DOMAIN}/market/equipment-rebates/` },
40
- { text: 'News', url: `${ES_DOMAIN}/blog/` },
41
- { text: 'Home solar guide', url: `${ES_DOMAIN}/shop/home-solar/` },
42
- { text: 'Market intel', url: `${ES_DOMAIN}/data/` },
43
- { text: 'Refer a friend', url: `${ES_DOMAIN}/refer-a-friend/` },
44
- ],
45
- },
46
- {
47
- title: 'About us',
48
- links: [
49
- { text: 'Mission & values', url: `${ES_DOMAIN}/about-us/company/` },
50
- { text: 'How it works', url: `${ES_DOMAIN}/shop/home-solar/` },
51
- { text: 'Careers', url: `${ES_DOMAIN}/about-us/careers/` },
52
- { text: 'Contact us', url: `${ES_DOMAIN}/contact/` },
53
- { text: 'Editorial guidelines', url: `${ES_DOMAIN}/editorial-guidelines/` },
54
- ],
55
- },
56
- {
57
- title: 'Work with us',
58
- links: [
59
- { text: 'Solar & HVAC installers', url: `${ES_DOMAIN}/installers/` },
60
- { text: 'Corporate partnerships', url: `${ES_DOMAIN}/partners/corporations` },
61
- { text: 'Community programs', url: `${ES_DOMAIN}/partners/non-profits` },
62
- { text: 'Utility programs', url: `${ES_DOMAIN}/partners/utilities` },
63
- { text: 'Others', url: `${ES_DOMAIN}/partners/` },
64
- ],
65
- },
66
- ],
67
- socialLinks: [
68
- { text: 'Facebook', url: 'https://www.facebook.com/EnergySage', icon: 'icon-facebook' },
69
- { text: 'LinkedIn', url: 'https://www.linkedin.com/company/energysage/', icon: 'icon-linkedin' },
70
- { text: 'Instagram', url: 'https://www.instagram.com/energysage_official/', icon: 'icon-instagram' },
71
- { text: 'X', url: 'https://X.com/energysage', icon: 'icon-twitter' },
72
- { text: 'YouTube', url: 'https://www.youtube.com/c/EnergySage', icon: 'icon-youtube' },
73
- ],
74
- legalLinks: [
75
- { text: 'Terms of use', url: `${ES_DOMAIN}/terms-of-use/` },
76
- { text: 'Privacy policy', url: `${ES_DOMAIN}/privacy-policy/` },
77
- { text: 'Mobile terms of use', url: `${ES_DOMAIN}/mobile-terms-of-use/` },
78
- { text: 'Non-discrimination policy', url: `${ES_DOMAIN}/nondiscrimination/` },
79
- // { text: 'Your privacy choices' },
80
- ],
81
- copyrightText: '© Copyright 2009-{currentYear} EnergySage, Inc. All rights reserved.',
82
- trademarkText: `ENERGYSAGE is a registered trademark and the EnergySage logo is a trademark of EnergySage, Inc.
83
- Other trademarks are the property of either EnergySage, Inc. or our licensors and are used with permission.`,
84
- departmentOfEnergy: {
85
- learnMore: {
86
- link: 'https://www.energy.gov/eere/solar/articles/eere-success-story-doe-funding-helps-build-one-stop-shop-rooftop-pv-systems',
87
- text: 'Learn more about our success working with the U.S. Department of Energy.',
88
- },
89
- logoUrl: 'https://www-static.energysage.com/static/img/doe/doe-logo-179.943fe6467b04.png',
90
- },
91
- });
@@ -1,55 +0,0 @@
1
- // rooftop account links
2
- export default (
3
- ES_DOMAIN = process.env.ES_DOMAIN || 'https://www.energysage.com',
4
- ACCOUNTS_DOMAIN = process.env.ACCOUNTS_DOMAIN || 'https://accounts.energysage.com',
5
- REGISTER_LINK = process.env.REGISTER_LINK || `${ACCOUNTS_DOMAIN}/register/?next=${ES_DOMAIN}/register-thanks/`,
6
- ) => ({
7
- mobileAccountButtonAltText: 'Open account menu',
8
- loggedIn: {
9
- items: [
10
- {
11
- name: 'My profile',
12
- link: `${ES_DOMAIN}/profile/`,
13
- },
14
- {
15
- name: 'My quotes',
16
- link: `${ES_DOMAIN}/your-marketplace/`,
17
- },
18
- {
19
- name: 'My messages',
20
- link: `${ES_DOMAIN}/message/`,
21
- },
22
- {
23
- name: 'My project preferences',
24
- link: `${ES_DOMAIN}/market/solarpv/update/`,
25
- },
26
- {
27
- name: 'Account settings',
28
- link: `${ES_DOMAIN}/account-settings/router/`,
29
- },
30
- {
31
- name: 'How it works',
32
- link: `${ES_DOMAIN}/market-process/`,
33
- },
34
- {
35
- name: 'Write a review',
36
- link: `${ES_DOMAIN}/share-your-experience/`,
37
- },
38
- {
39
- name: 'Sign out',
40
- link: `${ES_DOMAIN}/logout/`,
41
- },
42
- ],
43
- },
44
- loggedOut: {
45
- menuButtonText: 'Sign in',
46
- signIn: {
47
- name: 'Sign in',
48
- link: `${ES_DOMAIN}/login/`,
49
- },
50
- createAccount: {
51
- name: 'Create an account',
52
- link: REGISTER_LINK,
53
- },
54
- },
55
- });