@energysage/es-ds-components 3.0.0-alpha.6 → 3.0.0-alpha.7

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 (224) hide show
  1. package/.eslintignore +9 -0
  2. package/.eslintrc.json +3 -0
  3. package/.prettierrc.json +10 -0
  4. package/components/es-accordion-list.vue +112 -0
  5. package/components/es-accordion.vue +7 -0
  6. package/components/es-badge.vue +20 -0
  7. package/components/es-breadcrumbs.vue +43 -32
  8. package/components/es-button.vue +112 -0
  9. package/components/es-card.vue +64 -0
  10. package/components/es-carousel.vue +160 -0
  11. package/components/{b-col.vue → es-col.vue} +11 -11
  12. package/components/es-collapse.vue +38 -36
  13. package/components/es-cta-banner.vue +95 -0
  14. package/components/es-cta-card.vue +60 -0
  15. package/components/es-data-table-simple.vue +73 -0
  16. package/components/es-data-table.vue +126 -0
  17. package/components/es-error-page.vue +120 -0
  18. package/components/es-file-input.vue +331 -0
  19. package/components/es-file-preview-modal.vue +61 -0
  20. package/components/es-footer.vue +163 -0
  21. package/components/es-form-checkbox.vue +40 -0
  22. package/components/es-form-input.vue +130 -0
  23. package/components/es-form-msg.vue +81 -0
  24. package/components/es-form-radio-card.vue +57 -0
  25. package/components/es-form-radio-cards.vue +78 -0
  26. package/components/es-form-textarea.vue +124 -0
  27. package/components/es-form.vue +16 -0
  28. package/components/es-modal.vue +103 -0
  29. package/components/es-nav-bar-account-menu.vue +67 -0
  30. package/components/es-nav-bar-featured-article.vue +60 -0
  31. package/components/es-nav-bar-link.vue +27 -0
  32. package/components/es-nav-bar-product-menu.vue +215 -0
  33. package/components/es-nav-bar-top-level-menu.vue +193 -0
  34. package/components/es-nav-bar-topic-menu.vue +194 -0
  35. package/components/es-nav-bar.vue +396 -0
  36. package/components/es-pagination.vue +66 -0
  37. package/components/es-popover.vue +113 -0
  38. package/components/es-progress-circle.vue +81 -0
  39. package/components/es-progress.vue +36 -0
  40. package/components/es-radio-button-group.vue +53 -0
  41. package/components/es-radio-button.vue +50 -57
  42. package/components/es-rating.vue +120 -0
  43. package/components/es-reviews-io-card-carousel.vue +275 -0
  44. package/components/es-slider.vue +147 -0
  45. package/components/es-spinner.vue +22 -0
  46. package/components/es-support-card.vue +150 -0
  47. package/components/es-support.vue +66 -0
  48. package/components/es-tab.vue +7 -0
  49. package/components/es-tabs.vue +67 -0
  50. package/components/es-verification-code.vue +94 -0
  51. package/components/es-view-more.vue +63 -0
  52. package/components/es-zip-code-form.vue +204 -0
  53. package/components/icon/arrow-clockwise.vue +51 -0
  54. package/components/icon/arrow-counter-clockwise.vue +37 -0
  55. package/components/icon/arrow-cycle.vue +43 -0
  56. package/components/icon/arrow-left.vue +39 -0
  57. package/components/icon/arrow-right.vue +39 -0
  58. package/components/icon/arrow-up.vue +39 -0
  59. package/components/icon/arrow.vue +68 -0
  60. package/components/icon/bank.vue +38 -0
  61. package/components/icon/battery.vue +40 -0
  62. package/components/icon/bell.vue +42 -0
  63. package/components/icon/block.vue +46 -0
  64. package/components/icon/bolt.vue +38 -0
  65. package/components/icon/business.vue +42 -0
  66. package/components/icon/calculator.vue +37 -0
  67. package/components/icon/calendar.vue +46 -0
  68. package/components/icon/cart.vue +46 -0
  69. package/components/icon/chat-add.vue +44 -0
  70. package/components/icon/chat-approve.vue +42 -0
  71. package/components/icon/chat-bubble.vue +40 -0
  72. package/components/icon/chat-dots.vue +42 -0
  73. package/components/icon/check.vue +39 -0
  74. package/components/{icon-chevron-down.vue → icon/chevron-down.vue} +16 -16
  75. package/components/icon/chevron-horizontal.vue +39 -0
  76. package/components/icon/chevron-left.vue +39 -0
  77. package/components/{icon-chevron-right.vue → icon/chevron-right.vue} +16 -16
  78. package/components/icon/chevron-up.vue +39 -0
  79. package/components/icon/circle-alert.vue +46 -0
  80. package/components/icon/circle-check.vue +46 -0
  81. package/components/icon/circle-chevron-down.vue +47 -0
  82. package/components/icon/circle-chevron-left.vue +46 -0
  83. package/components/icon/circle-chevron-right.vue +46 -0
  84. package/components/icon/circle-chevron-up.vue +46 -0
  85. package/components/icon/circle-minus.vue +46 -0
  86. package/components/icon/circle-plus.vue +46 -0
  87. package/components/icon/circle-x.vue +46 -0
  88. package/components/icon/circle.vue +42 -0
  89. package/components/icon/clock.vue +46 -0
  90. package/components/icon/community-solar.vue +37 -0
  91. package/components/icon/companies.vue +43 -0
  92. package/components/icon/contact-us.vue +37 -0
  93. package/components/icon/copy.vue +45 -0
  94. package/components/icon/credit-card.vue +37 -0
  95. package/components/icon/document.vue +45 -0
  96. package/components/icon/electric-vehicle.vue +37 -0
  97. package/components/icon/electricity-circle.vue +39 -0
  98. package/components/icon/envelope.vue +45 -0
  99. package/components/icon/es-leaf.vue +39 -0
  100. package/components/icon/eye.vue +41 -0
  101. package/components/icon/facebook.vue +41 -0
  102. package/components/icon/file-doc.vue +72 -0
  103. package/components/icon/file-docx.vue +72 -0
  104. package/components/icon/file-pdf.vue +72 -0
  105. package/components/icon/flag.vue +37 -0
  106. package/components/icon/folder.vue +41 -0
  107. package/components/icon/gear.vue +37 -0
  108. package/components/icon/gift.vue +37 -0
  109. package/components/icon/hamburger.vue +38 -0
  110. package/components/icon/heart.vue +39 -0
  111. package/components/icon/heat-pump.vue +41 -0
  112. package/components/icon/image.vue +45 -0
  113. package/components/icon/info-blog-post.vue +47 -0
  114. package/components/icon/info.vue +45 -0
  115. package/components/icon/instagram.vue +49 -0
  116. package/components/icon/light-bulb.vue +36 -0
  117. package/components/icon/link-out.vue +38 -0
  118. package/components/icon/linkedin.vue +41 -0
  119. package/components/icon/location.vue +45 -0
  120. package/components/icon/lock-off.vue +45 -0
  121. package/components/icon/lock-on.vue +48 -0
  122. package/components/icon/marketplace.vue +43 -0
  123. package/components/icon/minus.vue +38 -0
  124. package/components/icon/money-bag.vue +37 -0
  125. package/components/icon/money.vue +35 -0
  126. package/components/icon/open-envelope.vue +45 -0
  127. package/components/icon/paper.vue +45 -0
  128. package/components/icon/payback.vue +37 -0
  129. package/components/icon/pencil.vue +45 -0
  130. package/components/icon/person-add.vue +41 -0
  131. package/components/icon/person-check.vue +41 -0
  132. package/components/icon/person-cross.vue +41 -0
  133. package/components/icon/person.vue +41 -0
  134. package/components/icon/phone.vue +41 -0
  135. package/components/icon/play.vue +41 -0
  136. package/components/icon/plus.vue +38 -0
  137. package/components/icon/roof.vue +37 -0
  138. package/components/icon/rooftop-solar.vue +37 -0
  139. package/components/icon/saving.vue +37 -0
  140. package/components/icon/search.vue +43 -0
  141. package/components/icon/settings-horizontal.vue +57 -0
  142. package/components/icon/settings-vertical.vue +57 -0
  143. package/components/icon/shield-with-check.vue +38 -0
  144. package/components/icon/shield.vue +41 -0
  145. package/components/icon/shopping-bag.vue +39 -0
  146. package/components/icon/solar.vue +37 -0
  147. package/components/icon/sound-down.vue +45 -0
  148. package/components/icon/sound-off.vue +41 -0
  149. package/components/icon/sound-on.vue +41 -0
  150. package/components/icon/sound-up.vue +41 -0
  151. package/components/icon/star-empty.vue +38 -0
  152. package/components/icon/star-full.vue +36 -0
  153. package/components/icon/star-half.vue +55 -0
  154. package/components/icon/state-ak.vue +53 -0
  155. package/components/icon/state-al.vue +38 -0
  156. package/components/icon/state-ar.vue +38 -0
  157. package/components/icon/state-az.vue +38 -0
  158. package/components/icon/state-ca.vue +38 -0
  159. package/components/icon/state-co.vue +38 -0
  160. package/components/icon/state-ct.vue +38 -0
  161. package/components/icon/state-dc.vue +52 -0
  162. package/components/icon/state-de.vue +38 -0
  163. package/components/icon/state-fl.vue +38 -0
  164. package/components/icon/state-ga.vue +38 -0
  165. package/components/icon/state-hi.vue +59 -0
  166. package/components/icon/state-ia.vue +38 -0
  167. package/components/icon/state-id.vue +38 -0
  168. package/components/icon/state-il.vue +38 -0
  169. package/components/icon/state-in.vue +38 -0
  170. package/components/icon/state-ks.vue +38 -0
  171. package/components/icon/state-ky.vue +38 -0
  172. package/components/icon/state-la.vue +38 -0
  173. package/components/icon/state-ma.vue +38 -0
  174. package/components/icon/state-md.vue +39 -0
  175. package/components/icon/state-me.vue +38 -0
  176. package/components/icon/state-mi.vue +38 -0
  177. package/components/icon/state-mn.vue +38 -0
  178. package/components/icon/state-mo.vue +38 -0
  179. package/components/icon/state-ms.vue +38 -0
  180. package/components/icon/state-mt.vue +38 -0
  181. package/components/icon/state-nc.vue +38 -0
  182. package/components/icon/state-nd.vue +38 -0
  183. package/components/icon/state-ne.vue +38 -0
  184. package/components/icon/state-nh.vue +38 -0
  185. package/components/icon/state-nj.vue +37 -0
  186. package/components/icon/state-nm.vue +38 -0
  187. package/components/icon/state-nv.vue +38 -0
  188. package/components/icon/state-ny.vue +41 -0
  189. package/components/icon/state-oh.vue +38 -0
  190. package/components/icon/state-ok.vue +38 -0
  191. package/components/icon/state-or.vue +38 -0
  192. package/components/icon/state-pa.vue +38 -0
  193. package/components/icon/state-ri.vue +38 -0
  194. package/components/icon/state-sc.vue +38 -0
  195. package/components/icon/state-sd.vue +38 -0
  196. package/components/icon/state-tn.vue +38 -0
  197. package/components/icon/state-tx.vue +38 -0
  198. package/components/icon/state-ut.vue +38 -0
  199. package/components/icon/state-va.vue +38 -0
  200. package/components/icon/state-vt.vue +38 -0
  201. package/components/icon/state-wa.vue +38 -0
  202. package/components/icon/state-wi.vue +38 -0
  203. package/components/icon/state-wv.vue +38 -0
  204. package/components/icon/state-wy.vue +38 -0
  205. package/components/icon/thumbs-up.vue +39 -0
  206. package/components/icon/trash-can.vue +41 -0
  207. package/components/icon/tree.vue +37 -0
  208. package/components/icon/twitter.vue +43 -0
  209. package/components/icon/upload.vue +41 -0
  210. package/components/icon/verified.vue +40 -0
  211. package/components/icon/video-play.vue +41 -0
  212. package/components/icon/wifi.vue +38 -0
  213. package/components/icon/x.vue +38 -0
  214. package/components/icon/youtube.vue +45 -0
  215. package/composables/forms.ts +124 -0
  216. package/lib-utils/mime-type-finder.js +48 -0
  217. package/nuxt.config.ts +40 -9
  218. package/package.json +29 -5
  219. package/tsconfig.json +2 -2
  220. package/utils/get-es-footer-content.js +90 -0
  221. package/utils/get-es-nav-bar-account-content.js +55 -0
  222. package/utils/get-es-nav-bar-global-content.js +474 -0
  223. /package/components/{b-container.vue → es-container.vue} +0 -0
  224. /package/components/{b-row.vue → es-row.vue} +0 -0
package/.eslintignore ADDED
@@ -0,0 +1,9 @@
1
+ # don't ever lint node_modules
2
+ node_modules
3
+ # don't lint build output (make sure it's set to your correct build folder name)
4
+ dist
5
+ .nuxt
6
+ .output
7
+ # don't lint coverage output
8
+ coverage
9
+ *.json
package/.eslintrc.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": ["../es-ds-docs/.eslintrc.json"]
3
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "printWidth": 119,
3
+ "useTabs": false,
4
+ "singleQuote": true,
5
+ "trailingComma": "all",
6
+ "bracketSpacing": true,
7
+ "bracketSameLine": true,
8
+ "singleAttributePerLine": true,
9
+ "tabWidth": 4
10
+ }
@@ -0,0 +1,112 @@
1
+ <script setup lang="ts">
2
+ import Accordion from 'primevue/accordion';
3
+ import AccordionTab from 'primevue/accordiontab';
4
+
5
+ interface Props {
6
+ allowMultipleExpand?: boolean;
7
+ initialExpandedId?: string;
8
+ variant?: string;
9
+ }
10
+
11
+ const props = withDefaults(defineProps<Props>(), {
12
+ allowMultipleExpand: false,
13
+ initialExpandedId: '',
14
+ variant: 'default',
15
+ });
16
+
17
+ // eslint-disable-next-line vue/require-prop-types
18
+ const model = defineModel();
19
+
20
+ const children = useSlots().default?.() || [];
21
+
22
+ const activeIndex = ref();
23
+
24
+ watch(model, (newVal) => {
25
+ if (newVal) {
26
+ activeIndex.value = children.findIndex((child) => child.props.id === newVal);
27
+ }
28
+ });
29
+
30
+ const accordionTabs = children.map((child, index) => {
31
+ if (child.props.id === props.initialExpandedId || child.props.id === model.value) {
32
+ activeIndex.value = index;
33
+ }
34
+ return child.children;
35
+ });
36
+
37
+ const updateActiveIndex = (index) => {
38
+ if (model.value) {
39
+ model.value = children[index]?.props.id || '';
40
+ }
41
+ };
42
+ </script>
43
+
44
+ <template>
45
+ <accordion
46
+ :multiple="allowMultipleExpand"
47
+ :active-index="activeIndex"
48
+ :pt="{
49
+ root: {
50
+ class: `es-accordion-list es-accordion-list--${variant}`,
51
+ },
52
+ }"
53
+ @update:active-index="updateActiveIndex">
54
+ <template #collapseicon> </template>
55
+ <template #expandicon> </template>
56
+ <accordion-tab
57
+ v-for="(tab, index) in accordionTabs"
58
+ :key="index"
59
+ :pt="{
60
+ root: ({ context }) => ({
61
+ class: [
62
+ `es-accordion es-accordion--${variant}`,
63
+ {
64
+ expanded: context.active,
65
+ },
66
+ ],
67
+ }),
68
+ header: {
69
+ class: 'position-relative d-block',
70
+ },
71
+ headerAction: ({ context }) => ({
72
+ class: [
73
+ // eslint-disable-next-line max-len
74
+ 'es-accordion-heading mb-0 align-items-center d-flex font-weight-bold justify-content-between py-100',
75
+ {
76
+ 'es-accordion-heading--visible': context.active,
77
+ 'font-size-100 px-100 px-sm-200': variant !== 'minimal',
78
+ 'h3 px-0': variant === 'minimal',
79
+ },
80
+ ],
81
+ }),
82
+ transition: {
83
+ name: 'v-transition',
84
+ },
85
+ content: {
86
+ class: [
87
+ 'es-accordion-content pb-25',
88
+ {
89
+ 'bg-white pt-100 px-100 px-sm-200': variant !== 'minimal',
90
+ },
91
+ ],
92
+ },
93
+ }">
94
+ <template #header>
95
+ <span
96
+ role="heading"
97
+ aria-level="3"
98
+ :class="{ 'h3 mb-0': variant === 'minimal' }">
99
+ <component
100
+ :is="item"
101
+ v-for="item in tab.title()"
102
+ :key="item" />
103
+ </span>
104
+ <icon-chevron-down class="es-accordion-icon flex-shrink-0 ml-200" />
105
+ </template>
106
+ <component
107
+ :is="item"
108
+ v-for="item in tab.default()"
109
+ :key="item" />
110
+ </accordion-tab>
111
+ </accordion>
112
+ </template>
@@ -0,0 +1,7 @@
1
+ <!-- eslint-disable vue/valid-template-root -->
2
+ <template>
3
+ <!--
4
+ While this file needs to exist to keep Nuxt happy, it doesn't actually do anything.
5
+ Instances of es-accordion are placed inside es-accordion-list, and es-accordion-list handles their display.
6
+ -->
7
+ </template>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ defineProps({
3
+ variant: {
4
+ type: String,
5
+ default: 'primary',
6
+ required: false,
7
+ },
8
+ });
9
+ </script>
10
+
11
+ <template>
12
+ <span
13
+ class="badge"
14
+ :class="`badge-${variant}`">
15
+ <!--
16
+ @slot Badge Content
17
+ -->
18
+ <slot />
19
+ </span>
20
+ </template>
@@ -1,17 +1,45 @@
1
+ <script setup lang="ts">
2
+ import Breadcrumb from 'primevue/breadcrumb';
3
+
4
+ const props = defineProps({
5
+ items: {
6
+ type: Array,
7
+ required: true,
8
+ },
9
+ });
10
+ const route = useRoute();
11
+ const model = computed(() => {
12
+ if (!props.items) {
13
+ return [];
14
+ }
15
+
16
+ return props.items.map((item) => ({
17
+ ...item,
18
+ // mark breadcrumb as active if manually set or if it matches this route
19
+ active: item.active || route.path === item.to || route.path === item.href,
20
+ label: item.text,
21
+ url: item.href,
22
+ }));
23
+ });
24
+ </script>
25
+
1
26
  <template>
2
27
  <breadcrumb
3
28
  :model="model"
4
29
  :pt="{
5
30
  menu: 'breadcrumb',
6
- menuitem: 'breadcrumb-item'
31
+ menuitem: 'breadcrumb-item',
7
32
  }">
8
- <template #item="{ item, props }">
33
+ <template #item="{ item }">
9
34
  <!--
10
35
  primevue breadcrumb doesn't support an active non-link state out of the box,
11
36
  so we have to implement it via this slot
12
37
  https://v3.primevue.org/breadcrumb/#api.options.MenuItem
13
38
  -->
14
- <span v-if="item.active" aria-current="location" class="font-weight-bold">
39
+ <span
40
+ v-if="item.active"
41
+ aria-current="location"
42
+ class="font-weight-bold">
15
43
  {{ item.label }}
16
44
  </span>
17
45
  <!--
@@ -19,10 +47,15 @@
19
47
  so we have to implement it via this slot
20
48
  https://v3.primevue.org/breadcrumb/#router
21
49
  -->
22
- <nuxt-link v-else-if="item.to" :to="item.to">
50
+ <nuxt-link
51
+ v-else-if="item.to"
52
+ :to="item.to">
23
53
  {{ item.label }}
24
54
  </nuxt-link>
25
- <a v-else-if="item.url" :href="item.url" :target="item.target">
55
+ <a
56
+ v-else-if="item.url"
57
+ :href="item.url"
58
+ :target="item.target">
26
59
  {{ item.label }}
27
60
  </a>
28
61
  <span v-else>
@@ -30,33 +63,11 @@
30
63
  </span>
31
64
  </template>
32
65
  <template #separator>
33
- <span aria-hidden class="mx-50">/</span>
66
+ <span
67
+ aria-hidden="true"
68
+ class="mx-50"
69
+ >/</span
70
+ >
34
71
  </template>
35
72
  </breadcrumb>
36
73
  </template>
37
-
38
- <script setup lang="ts">
39
- import Breadcrumb from 'primevue/breadcrumb';
40
-
41
- const props = defineProps({
42
- items: {
43
- type: Array,
44
- required: true
45
- }
46
- });
47
-
48
- const route = useRoute();
49
- const model = computed(() => {
50
- if (!props.items) {
51
- return [];
52
- }
53
-
54
- return props.items.map(item => ({
55
- ...item,
56
- // mark breadcrumb as active if manually set or if it matches this route
57
- active: item.active || route.path === item.to || route.path === item.href,
58
- label: item.text,
59
- url: item.href
60
- }));
61
- });
62
- </script>
@@ -0,0 +1,112 @@
1
+ <script setup lang="ts">
2
+ // Cannot import as Button due to issue with native element Button
3
+ import PrimeButton from 'primevue/button';
4
+
5
+ /*
6
+ severity:
7
+
8
+ Prime severity (variant="dark-bg" in particular) doesn't map to
9
+ "success" | "help" | "secondary" | "info" | "warning" | "danger" | "contrast"
10
+
11
+ size:
12
+ Prime size "small" | "large" doesn't map to our 3-sizes in the design-system
13
+
14
+ icon usage:
15
+ Prime provides icon & loadingIcon slots which can hook into the loading property,
16
+ currently we're not using this (but we may want to re-visit)
17
+ */
18
+
19
+ const props = defineProps({
20
+ /**
21
+ * Button Variant
22
+ *
23
+ */
24
+ variant: {
25
+ type: String,
26
+ default: 'primary',
27
+ required: false,
28
+ },
29
+ /**
30
+ * Outline only button
31
+ */
32
+ outline: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ /**
37
+ * Size of button
38
+ */
39
+ size: {
40
+ type: String,
41
+ validator: (val) => ['lg', 'md', 'sm'].includes(String(val)),
42
+ default: 'md',
43
+ },
44
+ /**
45
+ * Only works for 'link' variant buttons.
46
+ * Removes the fixed height and padding so the button can fit nicely within a block of text.
47
+ */
48
+ inline: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
52
+
53
+ // PrimeVue Arguments with es-ds defaults
54
+ rounded: {
55
+ type: Boolean,
56
+ default: true,
57
+ },
58
+ // Url when using button as a link
59
+ href: {
60
+ type: String,
61
+ default: null,
62
+ },
63
+ // Url when using button as a link to an internal page
64
+ to: {
65
+ type: String,
66
+ default: null,
67
+ },
68
+ });
69
+
70
+ const getRootClasses = computed(() => {
71
+ const withOutline = props.outline ? '-outline' : '';
72
+ // eslint-disable-next-line no-nested-ternary
73
+ const btnVariant =
74
+ props.variant === 'link'
75
+ ? 'btn-link'
76
+ : props.variant === 'dark-bg'
77
+ ? `btn${withOutline}-dark-bg`
78
+ : `btn${withOutline}-primary`;
79
+ const btnInline = props.inline ? 'inline' : '';
80
+ const btnSize = props.size ? `btn-${props.size}` : 'btn-md';
81
+ return `btn ${btnVariant} ${btnInline} ${btnSize}`;
82
+ });
83
+ </script>
84
+
85
+ <template>
86
+ <nuxt-link
87
+ v-if="props.href || props.to"
88
+ :href="props.href || undefined"
89
+ :to="props.to || undefined"
90
+ :class="getRootClasses">
91
+ <slot />
92
+ </nuxt-link>
93
+ <prime-button
94
+ v-else
95
+ :pt="{
96
+ root: { class: getRootClasses },
97
+ }">
98
+ <slot />
99
+ </prime-button>
100
+ </template>
101
+
102
+ <style lang="scss" scoped>
103
+ .btn-link.inline {
104
+ /* use normal CSS here so users can override with utility classes as necessary */
105
+ border: 0;
106
+ height: auto;
107
+ line-height: inherit;
108
+ margin: 0;
109
+ padding: 0;
110
+ vertical-align: baseline;
111
+ }
112
+ </style>
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ // specific workaround for getting a reference to an auto-imported but not globally registered
3
+ // component like NuxtLink, so that it can be used in a <component :is=""> context.
4
+ // this resolves to an import statement, according to:
5
+ // https://github.com/nuxt/nuxt/issues/13659#issuecomment-1573568006
6
+ const NuxtLink = resolveComponent('NuxtLink');
7
+
8
+ const props = defineProps({
9
+ href: {
10
+ type: String,
11
+ default: undefined,
12
+ },
13
+ tag: {
14
+ type: String,
15
+ default: 'div',
16
+ },
17
+ to: {
18
+ type: String,
19
+ default: undefined,
20
+ },
21
+ variant: {
22
+ type: String,
23
+ default: 'display',
24
+ required: false,
25
+ },
26
+ });
27
+
28
+ const actualVariant = computed(() => {
29
+ // if href is specified, force variant to be interactive
30
+ if (props.href) {
31
+ return 'interactive';
32
+ }
33
+ // if no href provided, honor the specified variant
34
+ return props.variant;
35
+ });
36
+ const defaultTag = computed(() => {
37
+ // if an href is provided and no alternate link tag was provided (e.g. nuxt-link),
38
+ // force the tag to be a nuxt-link, no matter the variant
39
+ if (props.href && props.tag === 'div') {
40
+ return 'nuxt-link';
41
+ }
42
+
43
+ // otherwise, honor the tag passed in if it's display variant
44
+ // or something other than the default tag was provided
45
+ if (props.variant !== 'interactive' || props.tag !== 'div') {
46
+ return props.tag;
47
+ }
48
+
49
+ // if we reach this point, variant is interactive, tag is div, and no href was provided
50
+ // and any non-link clickable element should be a button
51
+ return 'button';
52
+ });
53
+ </script>
54
+
55
+ <template>
56
+ <component
57
+ :is="defaultTag == 'nuxt-link' ? NuxtLink : defaultTag"
58
+ class="es-card"
59
+ :class="actualVariant"
60
+ :to="to ? to : href"
61
+ v-bind="$attrs">
62
+ <slot />
63
+ </component>
64
+ </template>
@@ -0,0 +1,160 @@
1
+ <script setup lang="ts">
2
+ import Carousel from 'primevue/carousel';
3
+
4
+ const responsiveOptions = ref([
5
+ {
6
+ // xl: 1200px
7
+ breakpoint: '1199px',
8
+ numVisible: 4,
9
+ numScroll: 1,
10
+ },
11
+ {
12
+ // lg: 992px
13
+ breakpoint: '991px',
14
+ numVisible: 3,
15
+ numScroll: 1,
16
+ },
17
+ {
18
+ // md: 768px
19
+ breakpoint: '767px',
20
+ numVisible: 2,
21
+ numScroll: 1,
22
+ },
23
+ {
24
+ // sm: 576px
25
+ breakpoint: '575px',
26
+ numVisible: 1,
27
+ numScroll: 1,
28
+ },
29
+ ]);
30
+
31
+ const props = defineProps({
32
+ autoscroll: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ dots: {
37
+ type: Boolean,
38
+ default: true,
39
+ },
40
+ items: {
41
+ type: Array,
42
+ default: () => [],
43
+ required: true,
44
+ },
45
+ });
46
+
47
+ const autoplayInterval = ref(props.autoscroll ? 3000 : 0);
48
+ const key = ref('');
49
+
50
+ const stopAutoplay = () => {
51
+ if (autoplayInterval.value > 0) {
52
+ autoplayInterval.value = 0;
53
+ key.value = 'stopAutoplay';
54
+ }
55
+ };
56
+
57
+ onMounted(() => {
58
+ document.addEventListener('keyup', (e) => {
59
+ if (e.key === 'Escape') {
60
+ // Stop carousel when user presses Escape key, in lieu of pause button
61
+ // https://www.w3.org/WAI/WCAG22/Techniques/general/G187.html
62
+ stopAutoplay();
63
+ }
64
+ });
65
+ });
66
+ </script>
67
+
68
+ <template>
69
+ <carousel
70
+ :key="key"
71
+ :autoplay-interval="autoplayInterval"
72
+ circular
73
+ :num-visible="4"
74
+ :responsive-options="responsiveOptions"
75
+ :show-indicators="dots"
76
+ :value="items"
77
+ :pt="{
78
+ container: {
79
+ class: 'd-flex',
80
+ },
81
+ indicator: {
82
+ class: 'dot',
83
+ },
84
+ indicators: {
85
+ class: 'd-flex justify-content-center',
86
+ style: 'gap: 12px;',
87
+ },
88
+ itemsContent: {
89
+ class: 'w-100 overflow-hidden',
90
+ },
91
+ itemsContainer: {
92
+ class: 'd-flex',
93
+ },
94
+ item: {
95
+ class: 'p-carousel-item p-1',
96
+ },
97
+ itemCloned: {
98
+ class: 'p-carousel-item p-1',
99
+ },
100
+ previousButton: {
101
+ style: 'border: unset; background: unset; color: #64748b;',
102
+ },
103
+ nextButton: {
104
+ style: 'border: unset; background: unset; color: #64748b;',
105
+ },
106
+ }">
107
+ <template #item="item">
108
+ <slot
109
+ name="item"
110
+ :item="item.data" />
111
+ </template>
112
+ </carousel>
113
+ </template>
114
+
115
+ <style lang="scss" scoped>
116
+ @use '@energysage/es-ds-styles/scss/variables' as variables;
117
+ @use '@energysage/es-ds-styles/scss/mixins/breakpoints' as breakpoints;
118
+
119
+ :deep(.p-carousel-item) {
120
+ flex: 1 0 100%;
121
+ }
122
+
123
+ @include breakpoints.media-breakpoint-up(sm) {
124
+ :deep(.p-carousel-item) {
125
+ flex: 1 0 calc(100% / 2);
126
+ }
127
+ }
128
+
129
+ @include breakpoints.media-breakpoint-up(md) {
130
+ :deep(.p-carousel-item) {
131
+ flex: 1 0 calc(100% / 3);
132
+ }
133
+ }
134
+
135
+ @include breakpoints.media-breakpoint-up(lg) {
136
+ :deep(.p-carousel-item) {
137
+ flex: 1 0 calc(100% / 4);
138
+ }
139
+ }
140
+
141
+ :deep(.dot) {
142
+ list-style-type: none;
143
+
144
+ &[data-p-highlight='true'] button {
145
+ background-color: variables.$orange-800;
146
+ }
147
+
148
+ button {
149
+ background-color: variables.$gray-100;
150
+ border: none;
151
+ border-radius: 50%;
152
+ height: 0.875rem;
153
+ width: 0.875rem;
154
+
155
+ &:hover {
156
+ opacity: 0.8;
157
+ }
158
+ }
159
+ }
160
+ </style>
@@ -1,3 +1,14 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ cols?: string;
4
+ sm?: string;
5
+ md?: string;
6
+ lg?: string;
7
+ xl?: string;
8
+ xxl?: string;
9
+ }>();
10
+ </script>
11
+
1
12
  <template>
2
13
  <div
3
14
  class="col"
@@ -12,14 +23,3 @@
12
23
  <slot />
13
24
  </div>
14
25
  </template>
15
-
16
- <script setup lang="ts">
17
- const props = defineProps<{
18
- cols?: string,
19
- sm?: string,
20
- md?: string,
21
- lg?: string,
22
- xl?: string,
23
- xxl?: string
24
- }>();
25
- </script>