@energysage/es-ds-components 3.0.10 → 3.1.0
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/components/es-collapse.vue +5 -2
- package/components/es-popover.vue +130 -102
- package/components/es-tabs.vue +5 -2
- package/components/es-tooltip.vue +171 -0
- package/components/es-video.vue +1 -1
- package/nuxt.config.ts +1 -0
- package/package.json +3 -2
|
@@ -20,6 +20,7 @@ const props = defineProps({
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
const userDeterminedState: Ref<boolean | null> = ref(null);
|
|
23
|
+
const uniqueId = useId();
|
|
23
24
|
|
|
24
25
|
// directly determines the expanded/collapsed state of the panel
|
|
25
26
|
const expanded = computed(() => {
|
|
@@ -52,7 +53,7 @@ const onClick = ({ value }: { value: boolean }) => {
|
|
|
52
53
|
<template>
|
|
53
54
|
<panel
|
|
54
55
|
:collapsed="!expanded"
|
|
55
|
-
:
|
|
56
|
+
:toggle-button-props="{ 'aria-labelledby': uniqueId }"
|
|
56
57
|
:pt="{
|
|
57
58
|
header: 'd-flex flex-column justify-content-center position-relative py-100',
|
|
58
59
|
icons: 'h-100 position-absolute w-100',
|
|
@@ -74,7 +75,9 @@ const onClick = ({ value }: { value: boolean }) => {
|
|
|
74
75
|
toggleable
|
|
75
76
|
@toggle="onClick">
|
|
76
77
|
<template #header>
|
|
77
|
-
<
|
|
78
|
+
<div :id="uniqueId">
|
|
79
|
+
<slot name="title" />
|
|
80
|
+
</div>
|
|
78
81
|
</template>
|
|
79
82
|
<template #togglericon>
|
|
80
83
|
<icon-chevron-down />
|
|
@@ -1,113 +1,141 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
const props = defineProps({
|
|
5
|
-
target: {
|
|
6
|
-
type: String,
|
|
7
|
-
required: true,
|
|
8
|
-
},
|
|
9
|
-
triggers: {
|
|
10
|
-
type: String,
|
|
11
|
-
required: false,
|
|
12
|
-
default: 'focus',
|
|
13
|
-
},
|
|
14
|
-
show: {
|
|
15
|
-
type: Boolean,
|
|
16
|
-
required: false,
|
|
17
|
-
default: false,
|
|
18
|
-
},
|
|
19
|
-
variant: {
|
|
20
|
-
type: String,
|
|
21
|
-
required: false,
|
|
22
|
-
default: 'dark',
|
|
23
|
-
validator: (val: string) => ['light', 'dark'].includes(val as string),
|
|
24
|
-
},
|
|
25
|
-
});
|
|
2
|
+
import { PopoverArrow, PopoverClose, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui';
|
|
26
3
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
targetElement.addEventListener(trigger, showPanel);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
4
|
+
interface IProps {
|
|
5
|
+
collisionPadding?: number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>;
|
|
6
|
+
show?: boolean | undefined;
|
|
7
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
8
|
+
triggerClass?: string;
|
|
9
|
+
triggerDescription?: string;
|
|
10
|
+
variant?: 'light' | 'dark';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
withDefaults(defineProps<IProps>(), {
|
|
14
|
+
collisionPadding: 0,
|
|
15
|
+
show: undefined,
|
|
16
|
+
side: 'top',
|
|
17
|
+
triggerClass: '',
|
|
18
|
+
triggerDescription: 'More information',
|
|
19
|
+
variant: 'dark',
|
|
46
20
|
});
|
|
47
21
|
|
|
48
|
-
|
|
49
|
-
() => props.show,
|
|
50
|
-
(newVal) => {
|
|
51
|
-
if (newVal) {
|
|
52
|
-
const targetElement = document.getElementById(props.target);
|
|
53
|
-
if (targetElement) {
|
|
54
|
-
const event = new MouseEvent('click', {
|
|
55
|
-
view: window,
|
|
56
|
-
bubbles: true,
|
|
57
|
-
cancelable: true,
|
|
58
|
-
});
|
|
59
|
-
targetElement.dispatchEvent(event);
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
closePanel();
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
);
|
|
22
|
+
const emit = defineEmits(['update:show']);
|
|
66
23
|
</script>
|
|
67
24
|
|
|
68
25
|
<template>
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class="
|
|
91
|
-
@click="closePanel">
|
|
92
|
-
<icon-x
|
|
93
|
-
height="20px"
|
|
94
|
-
width="20px" />
|
|
95
|
-
</button>
|
|
96
|
-
</h3>
|
|
97
|
-
</template>
|
|
98
|
-
<!-- Popover Content -->
|
|
99
|
-
<div class="popover-body">
|
|
100
|
-
<div class="d-flex">
|
|
101
|
-
<slot />
|
|
102
|
-
<button
|
|
103
|
-
v-if="!hasTitle"
|
|
104
|
-
class="es-popover-close p-0 pl-50 mb-auto bg-transparent"
|
|
105
|
-
@click="closePanel">
|
|
26
|
+
<popover-root
|
|
27
|
+
:open="show"
|
|
28
|
+
@update:open="(val) => emit('update:show', val)">
|
|
29
|
+
<popover-trigger
|
|
30
|
+
class="es-popover-trigger p-0"
|
|
31
|
+
:class="{ [triggerClass]: true }">
|
|
32
|
+
<span class="sr-only">{{ triggerDescription }}</span>
|
|
33
|
+
<slot name="trigger" />
|
|
34
|
+
</popover-trigger>
|
|
35
|
+
<popover-portal>
|
|
36
|
+
<popover-content
|
|
37
|
+
class="es-popover-content position-relative"
|
|
38
|
+
:class="{
|
|
39
|
+
'text-white': variant === 'dark',
|
|
40
|
+
'es-popover-content--light': variant === 'light',
|
|
41
|
+
}"
|
|
42
|
+
:collision-padding="collisionPadding"
|
|
43
|
+
:side="side">
|
|
44
|
+
<popover-close
|
|
45
|
+
class="es-popover-close position-absolute"
|
|
46
|
+
:class="{ 'es-popover-close--light': variant === 'light' }">
|
|
47
|
+
<span class="sr-only">Close</span>
|
|
106
48
|
<icon-x
|
|
107
49
|
height="20px"
|
|
108
50
|
width="20px" />
|
|
109
|
-
</
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
51
|
+
</popover-close>
|
|
52
|
+
<popover-arrow
|
|
53
|
+
class="es-popover-arrow"
|
|
54
|
+
:class="{ 'es-popover-arrow--light': variant === 'light' }"
|
|
55
|
+
:height="12"
|
|
56
|
+
rounded
|
|
57
|
+
:width="22" />
|
|
58
|
+
<div class="pr-300">
|
|
59
|
+
<slot />
|
|
60
|
+
</div>
|
|
61
|
+
<slot name="cta" />
|
|
62
|
+
</popover-content>
|
|
63
|
+
</popover-portal>
|
|
64
|
+
</popover-root>
|
|
113
65
|
</template>
|
|
66
|
+
|
|
67
|
+
<style lang="scss" scoped>
|
|
68
|
+
@use '@energysage/es-ds-styles/scss/mixins/border-radius' as border-radius;
|
|
69
|
+
@use '@energysage/es-ds-styles/scss/variables' as variables;
|
|
70
|
+
|
|
71
|
+
@keyframes fadeIn {
|
|
72
|
+
from {
|
|
73
|
+
opacity: 0;
|
|
74
|
+
}
|
|
75
|
+
to {
|
|
76
|
+
opacity: 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@keyframes fadeOut {
|
|
81
|
+
from {
|
|
82
|
+
opacity: 1;
|
|
83
|
+
}
|
|
84
|
+
to {
|
|
85
|
+
opacity: 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.es-popover-trigger {
|
|
90
|
+
align-items: center;
|
|
91
|
+
background-color: transparent;
|
|
92
|
+
border: none;
|
|
93
|
+
display: inline-flex;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
vertical-align: middle;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
:deep(.es-popover-content) {
|
|
99
|
+
background-color: variables.$dark-blue;
|
|
100
|
+
@include border-radius.border-radius(variables.$popover-border-radius);
|
|
101
|
+
box-shadow: variables.$popover-box-shadow;
|
|
102
|
+
padding: variables.$popover-header-padding-y variables.$popover-header-padding-x;
|
|
103
|
+
width: 250px;
|
|
104
|
+
z-index: variables.$zindex-popover;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:deep(.es-popover-content[data-state='open']) {
|
|
108
|
+
animation: fadeIn 150ms ease;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
:deep(.es-popover-content[data-state='closed']) {
|
|
112
|
+
animation: fadeOut 150ms ease;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
:deep(.es-popover-content--light) {
|
|
116
|
+
background-color: variables.$white;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:deep(.es-popover-arrow) {
|
|
120
|
+
fill: variables.$dark-blue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
:deep(.es-popover-arrow--light) {
|
|
124
|
+
fill: variables.$white;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
:deep(.es-popover-close) {
|
|
128
|
+
background-color: transparent;
|
|
129
|
+
border: none;
|
|
130
|
+
color: variables.$white;
|
|
131
|
+
height: 28px;
|
|
132
|
+
right: 1rem;
|
|
133
|
+
padding: 0;
|
|
134
|
+
top: 0.75rem;
|
|
135
|
+
width: 28px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
:deep(.es-popover-close--light) {
|
|
139
|
+
color: variables.$blue-600;
|
|
140
|
+
}
|
|
141
|
+
</style>
|
package/components/es-tabs.vue
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import TabPanel from 'primevue/tabpanel';
|
|
3
3
|
import TabView from 'primevue/tabview';
|
|
4
|
+
import { Comment } from 'vue';
|
|
4
5
|
|
|
5
6
|
// allow use of v-model on this component
|
|
6
7
|
const model = defineModel<number>();
|
|
7
8
|
|
|
8
|
-
// get the list of elements provided as children to the default slot
|
|
9
|
-
const
|
|
9
|
+
// get the list of elements provided as children to the default slot - filtering out comments
|
|
10
|
+
const rawChildren = useSlots().default?.() || [];
|
|
11
|
+
const initialChildren = rawChildren.filter((child) => child.type !== Comment);
|
|
12
|
+
|
|
10
13
|
const panels: any[] = [];
|
|
11
14
|
initialChildren.forEach((child) => {
|
|
12
15
|
// unless this has a v-for element and we instead need to access its children
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from 'reka-ui';
|
|
3
|
+
|
|
4
|
+
interface IProps {
|
|
5
|
+
collisionPadding?: number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>;
|
|
6
|
+
delayDuration?: number;
|
|
7
|
+
show?: boolean | undefined;
|
|
8
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
9
|
+
triggerClass?: string;
|
|
10
|
+
variant?: 'light' | 'dark';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
withDefaults(defineProps<IProps>(), {
|
|
14
|
+
collisionPadding: 0,
|
|
15
|
+
delayDuration: 0,
|
|
16
|
+
show: undefined,
|
|
17
|
+
side: 'top',
|
|
18
|
+
triggerClass: '',
|
|
19
|
+
variant: 'dark',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const emit = defineEmits(['update:show']);
|
|
23
|
+
|
|
24
|
+
const deviceSupportsTouch = ref(false);
|
|
25
|
+
const internalShow = ref(false);
|
|
26
|
+
|
|
27
|
+
// provide a workaround for the case where scroll-flipping causes the tooltip
|
|
28
|
+
// to get in a state where it won't reopen on hover (allow user to click to open)
|
|
29
|
+
const handleClick = () => {
|
|
30
|
+
internalShow.value = true;
|
|
31
|
+
emit('update:show', true);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// keep the internal boolean up to date when the state changes
|
|
35
|
+
// and also emit the update event up and out
|
|
36
|
+
const handleUpdateOpen = (val: boolean) => {
|
|
37
|
+
internalShow.value = val;
|
|
38
|
+
emit('update:show', val);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
onMounted(() => {
|
|
42
|
+
// detect if the device supports touch events or not
|
|
43
|
+
const mediaQueryResult = window.matchMedia('(hover: none)') as MediaQueryList;
|
|
44
|
+
deviceSupportsTouch.value = mediaQueryResult?.matches || false;
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<tooltip-provider
|
|
50
|
+
v-if="!deviceSupportsTouch"
|
|
51
|
+
:delay-duration="delayDuration"
|
|
52
|
+
:disable-closing-trigger="true">
|
|
53
|
+
<tooltip-root
|
|
54
|
+
:open="show || internalShow"
|
|
55
|
+
@update:open="handleUpdateOpen">
|
|
56
|
+
<tooltip-trigger
|
|
57
|
+
class="es-tooltip-trigger p-0"
|
|
58
|
+
:class="{ [triggerClass]: true }"
|
|
59
|
+
@click="handleClick">
|
|
60
|
+
<slot name="trigger" />
|
|
61
|
+
</tooltip-trigger>
|
|
62
|
+
<tooltip-portal>
|
|
63
|
+
<tooltip-content
|
|
64
|
+
class="es-tooltip-content"
|
|
65
|
+
:class="{
|
|
66
|
+
'text-white': variant === 'dark',
|
|
67
|
+
'es-tooltip-content--light': variant === 'light',
|
|
68
|
+
}"
|
|
69
|
+
:collision-padding="collisionPadding"
|
|
70
|
+
:side="side">
|
|
71
|
+
<tooltip-arrow
|
|
72
|
+
class="es-tooltip-arrow"
|
|
73
|
+
:class="{ 'es-tooltip-arrow--light': variant === 'light' }"
|
|
74
|
+
:height="12"
|
|
75
|
+
rounded
|
|
76
|
+
:width="22" />
|
|
77
|
+
<slot />
|
|
78
|
+
</tooltip-content>
|
|
79
|
+
</tooltip-portal>
|
|
80
|
+
</tooltip-root>
|
|
81
|
+
</tooltip-provider>
|
|
82
|
+
<es-popover
|
|
83
|
+
v-else
|
|
84
|
+
:collision-padding="collisionPadding"
|
|
85
|
+
:show="show"
|
|
86
|
+
:side="side"
|
|
87
|
+
:trigger-class="triggerClass"
|
|
88
|
+
:variant="variant"
|
|
89
|
+
@update:show="(val) => emit('update:show', val)">
|
|
90
|
+
<template #trigger>
|
|
91
|
+
<slot name="trigger" />
|
|
92
|
+
</template>
|
|
93
|
+
<slot />
|
|
94
|
+
</es-popover>
|
|
95
|
+
</template>
|
|
96
|
+
|
|
97
|
+
<style lang="scss" scoped>
|
|
98
|
+
@use '@energysage/es-ds-styles/scss/mixins/border-radius' as border-radius;
|
|
99
|
+
@use '@energysage/es-ds-styles/scss/variables' as variables;
|
|
100
|
+
|
|
101
|
+
@keyframes fadeIn {
|
|
102
|
+
from {
|
|
103
|
+
opacity: 0;
|
|
104
|
+
}
|
|
105
|
+
to {
|
|
106
|
+
opacity: 1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@keyframes fadeOut {
|
|
111
|
+
from {
|
|
112
|
+
opacity: 1;
|
|
113
|
+
}
|
|
114
|
+
to {
|
|
115
|
+
opacity: 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.es-tooltip-trigger {
|
|
120
|
+
align-items: center;
|
|
121
|
+
background-color: transparent;
|
|
122
|
+
border: none;
|
|
123
|
+
display: inline-flex;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
vertical-align: middle;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
:deep(.es-tooltip-content) {
|
|
129
|
+
background-color: variables.$dark-blue;
|
|
130
|
+
@include border-radius.border-radius(variables.$popover-border-radius);
|
|
131
|
+
box-shadow: variables.$popover-box-shadow;
|
|
132
|
+
padding: variables.$popover-header-padding-y variables.$popover-header-padding-x;
|
|
133
|
+
width: 250px;
|
|
134
|
+
z-index: variables.$zindex-popover;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
:deep(.es-tooltip-content[data-state='open']) {
|
|
138
|
+
animation: fadeIn 150ms ease;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
:deep(.es-tooltip-content[data-state='closed']) {
|
|
142
|
+
animation: fadeOut 150ms ease;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
:deep(.es-tooltip-content--light) {
|
|
146
|
+
background-color: variables.$white;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
:deep(.es-tooltip-arrow) {
|
|
150
|
+
fill: variables.$dark-blue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
:deep(.es-tooltip-arrow--light) {
|
|
154
|
+
fill: variables.$white;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
:deep(.es-tooltip-close) {
|
|
158
|
+
background-color: transparent;
|
|
159
|
+
border: none;
|
|
160
|
+
color: variables.$white;
|
|
161
|
+
height: 28px;
|
|
162
|
+
right: 1rem;
|
|
163
|
+
padding: 0;
|
|
164
|
+
top: 0.75rem;
|
|
165
|
+
width: 28px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
:deep(.es-tooltip-close--light) {
|
|
169
|
+
color: variables.$blue-600;
|
|
170
|
+
}
|
|
171
|
+
</style>
|
package/components/es-video.vue
CHANGED
|
@@ -12,7 +12,7 @@ const showVideo = ref(false);
|
|
|
12
12
|
|
|
13
13
|
// Methods
|
|
14
14
|
function getVideoIdFromUrl(url: string) {
|
|
15
|
-
const embedPattern = /https:\/\/www\.youtube\.com\/embed\/(?<videoId>[
|
|
15
|
+
const embedPattern = /https:\/\/www\.youtube\.com\/embed\/(?<videoId>[_A-Za-z0-9-]+)/;
|
|
16
16
|
const parsedUrl = embedPattern.exec(url);
|
|
17
17
|
if (parsedUrl) {
|
|
18
18
|
return parsedUrl?.groups?.videoId;
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@energysage/es-ds-components",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "An EnergySage Vue component library",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"author": "EnergySage",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@energysage/es-ds-styles": "^3.0
|
|
20
|
+
"@energysage/es-ds-styles": "^3.1.0",
|
|
21
21
|
"@nuxt/eslint": "^1.0.1",
|
|
22
22
|
"@nuxtjs/google-fonts": "^3.2.0",
|
|
23
23
|
"@vuelidate/core": "^2.0.3",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"nuxt-primevue": "^3.0.0",
|
|
29
29
|
"primevue": "^3.53.0",
|
|
30
30
|
"prismjs": "^1.29.0",
|
|
31
|
+
"reka-ui": "^2.2.0",
|
|
31
32
|
"vue": "^3.5.6"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|