@energysage/es-ds-components 3.0.0-alpha.13 → 3.0.0-alpha.15
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.
|
@@ -14,8 +14,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
14
14
|
variant: 'default',
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
const model = defineModel();
|
|
17
|
+
const model = defineModel<string>();
|
|
19
18
|
|
|
20
19
|
// get the list of elements provided as children to the default slot
|
|
21
20
|
const initialChildren = useSlots().default?.() || [];
|
|
@@ -29,7 +28,9 @@ initialChildren.forEach((child) => {
|
|
|
29
28
|
}
|
|
30
29
|
});
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
type ActiveChildren = null | number | number[];
|
|
32
|
+
|
|
33
|
+
const activeIndex: Ref<ActiveChildren> = ref(null);
|
|
33
34
|
|
|
34
35
|
watch(model, (newVal) => {
|
|
35
36
|
if (newVal) {
|
|
@@ -39,19 +40,30 @@ watch(model, (newVal) => {
|
|
|
39
40
|
|
|
40
41
|
const accordionTabs = children.map((child, index) => {
|
|
41
42
|
if (child.props.id === props.initialExpandedId || child.props.id === model.value) {
|
|
42
|
-
|
|
43
|
+
if (props.allowMultipleExpand) {
|
|
44
|
+
activeIndex.value = [index];
|
|
45
|
+
} else {
|
|
46
|
+
activeIndex.value = index;
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
return child.children;
|
|
45
50
|
});
|
|
46
51
|
|
|
47
|
-
const updateActiveIndex = (index:
|
|
52
|
+
const updateActiveIndex = (index: ActiveChildren) => {
|
|
48
53
|
if (model.value) {
|
|
49
|
-
|
|
54
|
+
if (typeof index === 'number') {
|
|
55
|
+
model.value = children[index]?.props.id || '';
|
|
56
|
+
} else if (index === null) {
|
|
57
|
+
model.value = '';
|
|
58
|
+
}
|
|
59
|
+
// There's another case where index will be an array. In that case, v-model is unsupported as specified
|
|
60
|
+
// in the documentation, so no update is made
|
|
50
61
|
}
|
|
51
62
|
};
|
|
52
63
|
</script>
|
|
53
64
|
|
|
54
65
|
<template>
|
|
66
|
+
<!-- @vue-expect-error PrimeVue's type information is wrong -->
|
|
55
67
|
<accordion
|
|
56
68
|
:multiple="allowMultipleExpand"
|
|
57
69
|
:active-index="activeIndex"
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
- circular has quirky behavior when numVisible doesn't match numScroll
|
|
5
5
|
- you can see this in the circular autoplay example
|
|
6
6
|
- i'm not sure if this is fixable
|
|
7
|
-
- figure out peek behavior
|
|
8
7
|
- prop to position the arrows at the bottom two corners of a full-width slide, like homepage
|
|
9
8
|
*/
|
|
10
9
|
|
|
@@ -35,6 +34,8 @@ interface IProps {
|
|
|
35
34
|
items: Array<any>;
|
|
36
35
|
numScroll?: number;
|
|
37
36
|
numVisible?: number;
|
|
37
|
+
peekDesktop?: string;
|
|
38
|
+
peekMobile?: string;
|
|
38
39
|
showArrows?: boolean;
|
|
39
40
|
showDots?: boolean;
|
|
40
41
|
slideGap?: number;
|
|
@@ -50,6 +51,8 @@ const props = withDefaults(defineProps<IProps>(), {
|
|
|
50
51
|
items: () => [],
|
|
51
52
|
numScroll: 1,
|
|
52
53
|
numVisible: 1,
|
|
54
|
+
peekDesktop: '',
|
|
55
|
+
peekMobile: '',
|
|
53
56
|
showArrows: true,
|
|
54
57
|
showDots: true,
|
|
55
58
|
slideGap: 16,
|
|
@@ -114,22 +117,34 @@ const dotsMarginTop = computed(() => `${props.controlGap / BASE_FONT_SIZE}rem`);
|
|
|
114
117
|
|
|
115
118
|
// the number of dots visible at each breakpoint
|
|
116
119
|
const numDotsXs = computed(() =>
|
|
117
|
-
props.showDots
|
|
120
|
+
props.showDots
|
|
121
|
+
? Math.ceil((props.items.length - numVisibleXs.value) / numScrollXs.value) + 1
|
|
122
|
+
: ARROW_SPACING_WHEN_NO_DOTS,
|
|
118
123
|
);
|
|
119
124
|
const numDotsSm = computed(() =>
|
|
120
|
-
props.showDots
|
|
125
|
+
props.showDots
|
|
126
|
+
? Math.ceil((props.items.length - numVisibleSm.value) / numScrollSm.value) + 1
|
|
127
|
+
: ARROW_SPACING_WHEN_NO_DOTS,
|
|
121
128
|
);
|
|
122
129
|
const numDotsMd = computed(() =>
|
|
123
|
-
props.showDots
|
|
130
|
+
props.showDots
|
|
131
|
+
? Math.ceil((props.items.length - numVisibleMd.value) / numScrollMd.value) + 1
|
|
132
|
+
: ARROW_SPACING_WHEN_NO_DOTS,
|
|
124
133
|
);
|
|
125
134
|
const numDotsLg = computed(() =>
|
|
126
|
-
props.showDots
|
|
135
|
+
props.showDots
|
|
136
|
+
? Math.ceil((props.items.length - numVisibleLg.value) / numScrollLg.value) + 1
|
|
137
|
+
: ARROW_SPACING_WHEN_NO_DOTS,
|
|
127
138
|
);
|
|
128
139
|
const numDotsXl = computed(() =>
|
|
129
|
-
props.showDots
|
|
140
|
+
props.showDots
|
|
141
|
+
? Math.ceil((props.items.length - numVisibleXl.value) / numScrollXl.value) + 1
|
|
142
|
+
: ARROW_SPACING_WHEN_NO_DOTS,
|
|
130
143
|
);
|
|
131
144
|
const numDotsXxl = computed(() =>
|
|
132
|
-
props.showDots
|
|
145
|
+
props.showDots
|
|
146
|
+
? Math.ceil((props.items.length - numVisibleXxl.value) / numScrollXxl.value) + 1
|
|
147
|
+
: ARROW_SPACING_WHEN_NO_DOTS,
|
|
133
148
|
);
|
|
134
149
|
|
|
135
150
|
// calculate the arrow position from center based on the number of dots
|
|
@@ -292,7 +307,13 @@ onMounted(() => {
|
|
|
292
307
|
class: 'd-block',
|
|
293
308
|
},
|
|
294
309
|
itemsContent: {
|
|
295
|
-
class:
|
|
310
|
+
class: [
|
|
311
|
+
'w-100 overflow-hidden',
|
|
312
|
+
{
|
|
313
|
+
'es-carousel-peek-desktop': peekDesktop,
|
|
314
|
+
'es-carousel-peek-mobile': peekMobile,
|
|
315
|
+
},
|
|
316
|
+
],
|
|
296
317
|
},
|
|
297
318
|
itemsContainer: {
|
|
298
319
|
class: 'd-flex',
|
|
@@ -372,6 +393,18 @@ $num-dots-supported: 8;
|
|
|
372
393
|
:deep(.es-carousel-container) {
|
|
373
394
|
margin-left: v-bind(negativeMargin);
|
|
374
395
|
margin-right: v-bind(negativeMargin);
|
|
396
|
+
|
|
397
|
+
> div.es-carousel-peek-desktop {
|
|
398
|
+
@include breakpoints.media-breakpoint-up(lg) {
|
|
399
|
+
padding-right: v-bind(peekDesktop);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
> div.es-carousel-peek-mobile {
|
|
404
|
+
@include breakpoints.media-breakpoint-down(sm) {
|
|
405
|
+
padding-right: v-bind(peekMobile);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
375
408
|
}
|
|
376
409
|
|
|
377
410
|
/* card sizing, based on num visible at each breakpoint */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import Column from 'primevue/column';
|
|
3
|
+
import type { ComponentOptionsMixin } from 'vue';
|
|
4
|
+
|
|
5
|
+
// magic solution for wrapping Column successfully
|
|
6
|
+
// https://www.reddit.com/r/vuejs/comments/1g17u7u/comment/lvjv91h/
|
|
7
|
+
defineOptions({
|
|
8
|
+
name: 'Column',
|
|
9
|
+
extends: (Column as unknown as ComponentOptionsMixin).extends,
|
|
10
|
+
inheritAttrs: false,
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<!-- eslint-disable vue/valid-template-root -->
|
|
15
|
+
<template>
|
|
16
|
+
<!--
|
|
17
|
+
While this file needs to exist to keep Nuxt happy, it doesn't actually do anything.
|
|
18
|
+
Instances of es-data-table-column are placed inside es-data-table, and es-data-table handles their display.
|
|
19
|
+
-->
|
|
20
|
+
</template>
|
|
@@ -1,75 +1,38 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import DataTable from 'primevue/datatable';
|
|
3
|
-
import Column from 'primevue/column';
|
|
4
3
|
|
|
5
4
|
const props = defineProps({
|
|
6
|
-
fields: {
|
|
7
|
-
type: Array,
|
|
8
|
-
default: null,
|
|
9
|
-
},
|
|
10
5
|
items: {
|
|
11
6
|
type: Array,
|
|
12
7
|
required: true,
|
|
13
8
|
},
|
|
14
|
-
|
|
9
|
+
scrollable: {
|
|
15
10
|
type: Boolean,
|
|
16
11
|
default: false,
|
|
17
12
|
},
|
|
18
|
-
|
|
19
|
-
type:
|
|
20
|
-
default:
|
|
13
|
+
scrollHeight: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: '',
|
|
21
16
|
},
|
|
22
17
|
});
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// Code is taken from BootStrap Vue to implemnt <b-table> feature that automatically
|
|
32
|
-
// samples the first row to extract field name and "humanize" by converting kebab-case,
|
|
33
|
-
// snake_case, and camelCase to individual words and capitalizes each word.
|
|
34
|
-
// Doc: https://bootstrap-vue.org/docs/components/table
|
|
35
|
-
// Source Code: https://github.com/bootstrap-vue/bootstrap-vue/blob/5173dd19f6f46dc9d125cd7233fb59ccd2ef9296/src/utils/string.js#L30
|
|
36
|
-
const startCase = (str: string) =>
|
|
37
|
-
str
|
|
38
|
-
.replace(/_/g, ' ')
|
|
39
|
-
.replace(/([a-z])([A-Z])/g, (_, $1, $2) => `${$1} ${$2}`)
|
|
40
|
-
.replace(/(\s|^)(\w)/g, (_, $1, $2) => $1 + $2.toUpperCase());
|
|
41
|
-
|
|
42
|
-
const label = (col: any) => {
|
|
43
|
-
if (typeof col === 'string') {
|
|
44
|
-
return startCase(col);
|
|
19
|
+
// avoid passing in default scrollHeight value when scrollable is false
|
|
20
|
+
// otherwise it will limit the height when we don't want it to
|
|
21
|
+
const defaultScrollHeight = computed(() => {
|
|
22
|
+
if (props.scrollable) {
|
|
23
|
+
return props.scrollHeight || '305px';
|
|
45
24
|
}
|
|
46
|
-
return col?.label ? col.label : startCase(col?.key);
|
|
47
|
-
};
|
|
48
25
|
|
|
49
|
-
const columns = computed(() => {
|
|
50
|
-
if (props.fields) {
|
|
51
|
-
return props.fields;
|
|
52
|
-
}
|
|
53
|
-
// @ts-expect-error not sure
|
|
54
|
-
return Object.keys(props.items[0]);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const scrollHeight = computed(() => {
|
|
58
|
-
if (props.stickyHeader) {
|
|
59
|
-
if (typeof props.stickyHeader === 'string') {
|
|
60
|
-
return props.stickyHeader;
|
|
61
|
-
}
|
|
62
|
-
return '300px';
|
|
63
|
-
}
|
|
64
26
|
return '';
|
|
65
27
|
});
|
|
66
28
|
</script>
|
|
29
|
+
|
|
67
30
|
<template>
|
|
68
31
|
<data-table
|
|
69
|
-
|
|
32
|
+
class="border table__data-table table-spacing table"
|
|
70
33
|
:pt="{
|
|
71
34
|
table: {
|
|
72
|
-
class: 'font-size-75 font-size-md-100',
|
|
35
|
+
class: 'font-size-75 font-size-md-100 w-100',
|
|
73
36
|
style: 'border-collapse: separate; border-spacing: 0;',
|
|
74
37
|
},
|
|
75
38
|
wrapper: {
|
|
@@ -79,50 +42,34 @@ const scrollHeight = computed(() => {
|
|
|
79
42
|
style: 'top: 0px; z-index: 2',
|
|
80
43
|
},
|
|
81
44
|
}"
|
|
82
|
-
:
|
|
83
|
-
|
|
84
|
-
:
|
|
85
|
-
|
|
86
|
-
<column
|
|
87
|
-
v-for="(col, index) of columns"
|
|
88
|
-
:key="col?.key ? col.key : col"
|
|
89
|
-
:field="col?.key ? col.key : col"
|
|
90
|
-
:header="label(col)"
|
|
91
|
-
:sortable="col?.sortable"
|
|
92
|
-
:frozen="checkFrozenRow(index)"
|
|
93
|
-
align-frozen="left"
|
|
94
|
-
:pt="{
|
|
95
|
-
sortIcon: {
|
|
96
|
-
style: 'display: none',
|
|
97
|
-
},
|
|
98
|
-
headerCell: (options) => ({
|
|
99
|
-
class: [
|
|
100
|
-
{
|
|
101
|
-
sortable: options.props.sortable,
|
|
102
|
-
stickyFirstColHeader: options.props.frozen,
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
}),
|
|
106
|
-
bodyCell: (options) => ({
|
|
107
|
-
class: [
|
|
108
|
-
{
|
|
109
|
-
stickyFirstCol: options.props.frozen,
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
}),
|
|
113
|
-
}">
|
|
114
|
-
</column>
|
|
45
|
+
:scrollable="scrollable"
|
|
46
|
+
:scroll-height="defaultScrollHeight"
|
|
47
|
+
:value="items">
|
|
48
|
+
<slot />
|
|
115
49
|
</data-table>
|
|
116
50
|
</template>
|
|
51
|
+
|
|
117
52
|
<style scoped lang="scss">
|
|
118
|
-
:deep(
|
|
119
|
-
|
|
53
|
+
:deep(th[data-p-sortable-column='true']) {
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
user-select: none;
|
|
56
|
+
|
|
57
|
+
div[data-pc-section='headercontent'] {
|
|
58
|
+
align-items: center;
|
|
59
|
+
display: flex;
|
|
60
|
+
}
|
|
61
|
+
span[data-pc-section='sort'] {
|
|
62
|
+
display: inline-block;
|
|
63
|
+
margin-left: 0.5rem;
|
|
64
|
+
}
|
|
120
65
|
}
|
|
121
|
-
|
|
66
|
+
|
|
67
|
+
:deep(td[data-p-frozen-column='true']),
|
|
68
|
+
:deep(th[data-p-frozen-column='true']) {
|
|
122
69
|
position: sticky !important;
|
|
123
|
-
background: inherit;
|
|
124
70
|
}
|
|
125
|
-
|
|
126
|
-
|
|
71
|
+
|
|
72
|
+
:deep(td[data-p-frozen-column='true']) {
|
|
73
|
+
background: inherit;
|
|
127
74
|
}
|
|
128
75
|
</style>
|