@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.
Files changed (234) hide show
  1. package/.eslintignore +9 -0
  2. package/.eslintrc.json +3 -0
  3. package/.prettierrc.json +10 -0
  4. package/README.md +0 -3
  5. package/components/es-accordion-list.vue +117 -0
  6. package/components/es-accordion.vue +7 -0
  7. package/components/es-badge.vue +20 -0
  8. package/components/es-breadcrumbs.vue +73 -0
  9. package/components/es-button.vue +122 -0
  10. package/components/es-card.vue +64 -0
  11. package/components/es-carousel.vue +316 -0
  12. package/components/es-col.vue +27 -0
  13. package/components/es-collapse.vue +83 -0
  14. package/components/es-container.vue +14 -0
  15. package/components/es-cta-banner.vue +95 -0
  16. package/components/es-cta-card.vue +60 -0
  17. package/components/es-data-table-simple.vue +73 -0
  18. package/components/es-data-table.vue +128 -0
  19. package/components/es-error-page.vue +120 -0
  20. package/components/es-file-input.vue +334 -0
  21. package/components/es-file-preview-modal.vue +61 -0
  22. package/components/es-footer.vue +163 -0
  23. package/components/es-form-checkbox.vue +40 -0
  24. package/components/es-form-input.vue +130 -0
  25. package/components/es-form-msg.vue +81 -0
  26. package/components/es-form-radio-card.vue +57 -0
  27. package/components/es-form-radio-cards.vue +78 -0
  28. package/components/es-form-textarea.vue +124 -0
  29. package/components/es-form.vue +16 -0
  30. package/components/es-modal.vue +103 -0
  31. package/components/es-nav-bar-account-menu.vue +70 -0
  32. package/components/es-nav-bar-featured-article.vue +60 -0
  33. package/components/es-nav-bar-link.vue +27 -0
  34. package/components/es-nav-bar-product-menu.vue +219 -0
  35. package/components/es-nav-bar-top-level-menu.vue +194 -0
  36. package/components/es-nav-bar-topic-menu.vue +197 -0
  37. package/components/es-nav-bar.vue +411 -0
  38. package/components/es-pagination.vue +67 -0
  39. package/components/es-popover.vue +113 -0
  40. package/components/es-progress-circle.vue +81 -0
  41. package/components/es-progress.vue +36 -0
  42. package/components/es-radio-button-group.vue +53 -0
  43. package/components/es-radio-button.vue +57 -0
  44. package/components/es-rating.vue +120 -0
  45. package/components/es-reviews-io-card-carousel.vue +279 -0
  46. package/components/es-row.vue +5 -0
  47. package/components/es-skeleton-img.vue +38 -0
  48. package/components/es-skeleton-wrapper.vue +17 -0
  49. package/components/es-skeleton.vue +97 -0
  50. package/components/es-slider.vue +218 -0
  51. package/components/es-spinner.vue +22 -0
  52. package/components/es-support-card.vue +150 -0
  53. package/components/es-support.vue +66 -0
  54. package/components/es-tab.vue +7 -0
  55. package/components/es-tabs.vue +70 -0
  56. package/components/es-verification-code.vue +94 -0
  57. package/components/es-video.vue +60 -0
  58. package/components/es-view-more.vue +64 -0
  59. package/components/es-zip-code-form.vue +204 -0
  60. package/components/icon/arrow-clockwise.vue +51 -0
  61. package/components/icon/arrow-counter-clockwise.vue +37 -0
  62. package/components/icon/arrow-cycle.vue +43 -0
  63. package/components/icon/arrow-left.vue +39 -0
  64. package/components/icon/arrow-right.vue +39 -0
  65. package/components/icon/arrow-up.vue +39 -0
  66. package/components/icon/arrow.vue +68 -0
  67. package/components/icon/bank.vue +38 -0
  68. package/components/icon/battery.vue +40 -0
  69. package/components/icon/bell.vue +42 -0
  70. package/components/icon/block.vue +46 -0
  71. package/components/icon/bolt.vue +38 -0
  72. package/components/icon/business.vue +42 -0
  73. package/components/icon/calculator.vue +37 -0
  74. package/components/icon/calendar.vue +46 -0
  75. package/components/icon/cart.vue +46 -0
  76. package/components/icon/chat-add.vue +44 -0
  77. package/components/icon/chat-approve.vue +42 -0
  78. package/components/icon/chat-bubble.vue +40 -0
  79. package/components/icon/chat-dots.vue +42 -0
  80. package/components/icon/check.vue +39 -0
  81. package/components/icon/chevron-down.vue +39 -0
  82. package/components/icon/chevron-horizontal.vue +39 -0
  83. package/components/icon/chevron-left.vue +39 -0
  84. package/components/icon/chevron-right.vue +39 -0
  85. package/components/icon/chevron-up.vue +39 -0
  86. package/components/icon/circle-alert.vue +46 -0
  87. package/components/icon/circle-check.vue +46 -0
  88. package/components/icon/circle-chevron-down.vue +47 -0
  89. package/components/icon/circle-chevron-left.vue +46 -0
  90. package/components/icon/circle-chevron-right.vue +46 -0
  91. package/components/icon/circle-chevron-up.vue +46 -0
  92. package/components/icon/circle-minus.vue +46 -0
  93. package/components/icon/circle-plus.vue +46 -0
  94. package/components/icon/circle-x.vue +46 -0
  95. package/components/icon/circle.vue +42 -0
  96. package/components/icon/clock.vue +46 -0
  97. package/components/icon/community-solar.vue +37 -0
  98. package/components/icon/companies.vue +43 -0
  99. package/components/icon/contact-us.vue +37 -0
  100. package/components/icon/copy.vue +45 -0
  101. package/components/icon/credit-card.vue +37 -0
  102. package/components/icon/document.vue +45 -0
  103. package/components/icon/electric-vehicle.vue +37 -0
  104. package/components/icon/electricity-circle.vue +39 -0
  105. package/components/icon/envelope.vue +45 -0
  106. package/components/icon/es-leaf.vue +39 -0
  107. package/components/icon/eye.vue +41 -0
  108. package/components/icon/facebook.vue +41 -0
  109. package/components/icon/file-doc.vue +72 -0
  110. package/components/icon/file-docx.vue +72 -0
  111. package/components/icon/file-pdf.vue +72 -0
  112. package/components/icon/flag.vue +37 -0
  113. package/components/icon/folder.vue +41 -0
  114. package/components/icon/gear.vue +37 -0
  115. package/components/icon/gift.vue +37 -0
  116. package/components/icon/hamburger.vue +38 -0
  117. package/components/icon/heart.vue +39 -0
  118. package/components/icon/heat-pump.vue +41 -0
  119. package/components/icon/image.vue +45 -0
  120. package/components/icon/info-blog-post.vue +47 -0
  121. package/components/icon/info.vue +45 -0
  122. package/components/icon/instagram.vue +49 -0
  123. package/components/icon/light-bulb.vue +36 -0
  124. package/components/icon/link-out.vue +38 -0
  125. package/components/icon/linkedin.vue +41 -0
  126. package/components/icon/location.vue +45 -0
  127. package/components/icon/lock-off.vue +45 -0
  128. package/components/icon/lock-on.vue +48 -0
  129. package/components/icon/marketplace.vue +43 -0
  130. package/components/icon/minus.vue +38 -0
  131. package/components/icon/money-bag.vue +37 -0
  132. package/components/icon/money.vue +35 -0
  133. package/components/icon/open-envelope.vue +45 -0
  134. package/components/icon/paper.vue +45 -0
  135. package/components/icon/payback.vue +37 -0
  136. package/components/icon/pencil.vue +45 -0
  137. package/components/icon/person-add.vue +41 -0
  138. package/components/icon/person-check.vue +41 -0
  139. package/components/icon/person-cross.vue +41 -0
  140. package/components/icon/person.vue +41 -0
  141. package/components/icon/phone.vue +41 -0
  142. package/components/icon/play.vue +41 -0
  143. package/components/icon/plus.vue +38 -0
  144. package/components/icon/roof.vue +37 -0
  145. package/components/icon/rooftop-solar.vue +37 -0
  146. package/components/icon/saving.vue +37 -0
  147. package/components/icon/search.vue +43 -0
  148. package/components/icon/settings-horizontal.vue +57 -0
  149. package/components/icon/settings-vertical.vue +57 -0
  150. package/components/icon/shield-with-check.vue +38 -0
  151. package/components/icon/shield.vue +41 -0
  152. package/components/icon/shopping-bag.vue +39 -0
  153. package/components/icon/solar.vue +37 -0
  154. package/components/icon/sound-down.vue +45 -0
  155. package/components/icon/sound-off.vue +41 -0
  156. package/components/icon/sound-on.vue +41 -0
  157. package/components/icon/sound-up.vue +41 -0
  158. package/components/icon/star-empty.vue +38 -0
  159. package/components/icon/star-full.vue +36 -0
  160. package/components/icon/star-half.vue +55 -0
  161. package/components/icon/state-ak.vue +53 -0
  162. package/components/icon/state-al.vue +38 -0
  163. package/components/icon/state-ar.vue +38 -0
  164. package/components/icon/state-az.vue +38 -0
  165. package/components/icon/state-ca.vue +38 -0
  166. package/components/icon/state-co.vue +38 -0
  167. package/components/icon/state-ct.vue +38 -0
  168. package/components/icon/state-dc.vue +52 -0
  169. package/components/icon/state-de.vue +38 -0
  170. package/components/icon/state-fl.vue +38 -0
  171. package/components/icon/state-ga.vue +38 -0
  172. package/components/icon/state-hi.vue +59 -0
  173. package/components/icon/state-ia.vue +38 -0
  174. package/components/icon/state-id.vue +38 -0
  175. package/components/icon/state-il.vue +38 -0
  176. package/components/icon/state-in.vue +38 -0
  177. package/components/icon/state-ks.vue +38 -0
  178. package/components/icon/state-ky.vue +38 -0
  179. package/components/icon/state-la.vue +38 -0
  180. package/components/icon/state-ma.vue +38 -0
  181. package/components/icon/state-md.vue +39 -0
  182. package/components/icon/state-me.vue +38 -0
  183. package/components/icon/state-mi.vue +38 -0
  184. package/components/icon/state-mn.vue +38 -0
  185. package/components/icon/state-mo.vue +38 -0
  186. package/components/icon/state-ms.vue +38 -0
  187. package/components/icon/state-mt.vue +38 -0
  188. package/components/icon/state-nc.vue +38 -0
  189. package/components/icon/state-nd.vue +38 -0
  190. package/components/icon/state-ne.vue +38 -0
  191. package/components/icon/state-nh.vue +38 -0
  192. package/components/icon/state-nj.vue +37 -0
  193. package/components/icon/state-nm.vue +38 -0
  194. package/components/icon/state-nv.vue +38 -0
  195. package/components/icon/state-ny.vue +41 -0
  196. package/components/icon/state-oh.vue +38 -0
  197. package/components/icon/state-ok.vue +38 -0
  198. package/components/icon/state-or.vue +38 -0
  199. package/components/icon/state-pa.vue +38 -0
  200. package/components/icon/state-ri.vue +38 -0
  201. package/components/icon/state-sc.vue +38 -0
  202. package/components/icon/state-sd.vue +38 -0
  203. package/components/icon/state-tn.vue +38 -0
  204. package/components/icon/state-tx.vue +38 -0
  205. package/components/icon/state-ut.vue +38 -0
  206. package/components/icon/state-va.vue +38 -0
  207. package/components/icon/state-vt.vue +38 -0
  208. package/components/icon/state-wa.vue +38 -0
  209. package/components/icon/state-wi.vue +38 -0
  210. package/components/icon/state-wv.vue +38 -0
  211. package/components/icon/state-wy.vue +38 -0
  212. package/components/icon/thumbs-up.vue +39 -0
  213. package/components/icon/trash-can.vue +41 -0
  214. package/components/icon/tree.vue +37 -0
  215. package/components/icon/twitter.vue +43 -0
  216. package/components/icon/upload.vue +41 -0
  217. package/components/icon/verified.vue +40 -0
  218. package/components/icon/video-play.vue +41 -0
  219. package/components/icon/wifi.vue +38 -0
  220. package/components/icon/x.vue +38 -0
  221. package/components/icon/youtube.vue +45 -0
  222. package/composables/forms.ts +124 -0
  223. package/nuxt.config.ts +83 -1
  224. package/package.json +47 -13
  225. package/tsconfig.json +4 -0
  226. package/types/es-carousel.ts +12 -0
  227. package/types/index.ts +1 -0
  228. package/utils/forms.ts +120 -0
  229. package/utils/get-es-footer-content.ts +90 -0
  230. package/utils/get-es-nav-bar-account-content.ts +55 -0
  231. package/utils/get-es-nav-bar-global-content.ts +482 -0
  232. package/utils/mime-type-finder.ts +48 -0
  233. package/utils/vuelidate-keys.ts +39 -0
  234. 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">&nbsp;</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>