@ulu/frontend-vue 0.1.0-beta.33 → 0.1.0-beta.35
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/dist/{breakpoints-BIA00Qir.js → breakpoints-B-Iw5aP7.js} +1 -1
- package/dist/frontend-vue.css +1 -1
- package/dist/frontend-vue.js +1 -1
- package/dist/{index-DYjzFpxo.js → index-BTzKF3bW.js} +988 -949
- package/lib/components/collapsible/UluCollapsibleRegion.vue +7 -7
- package/lib/components/forms/UluSelectableMenu.vue +9 -4
- package/lib/components/systems/facets/UluFacetsFilterLists.vue +4 -4
- package/lib/components/systems/facets/UluFacetsFilterPopovers.vue +3 -1
- package/lib/components/systems/facets/UluFacetsFilterSelects.vue +6 -6
- package/lib/components/systems/facets/UluFacetsHeaderLayout.vue +4 -4
- package/lib/components/systems/facets/UluFacetsList.vue +1 -1
- package/lib/components/systems/facets/UluFacetsResults.vue +10 -10
- package/lib/components/systems/facets/UluFacetsSearch.vue +1 -1
- package/lib/components/systems/facets/UluFacetsSidebarLayout.vue +55 -16
- package/lib/components/systems/facets/UluFacetsSort.vue +1 -1
- package/package.json +1 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
class="
|
|
3
|
+
class="collapsible-region"
|
|
4
4
|
@keydown.esc="handleEscape"
|
|
5
5
|
:class="{
|
|
6
|
-
'
|
|
7
|
-
'
|
|
8
|
-
'
|
|
6
|
+
'collapsible-region--open' : isOpen,
|
|
7
|
+
'collapsible-region--closed' : !isOpen,
|
|
8
|
+
'collapsible-region--transitioning' : isTransitioning
|
|
9
9
|
}"
|
|
10
10
|
>
|
|
11
11
|
<button
|
|
12
|
-
class="
|
|
12
|
+
class="collapsible-region__toggle"
|
|
13
13
|
:id="toggleId"
|
|
14
14
|
:aria-controls="contentId"
|
|
15
15
|
:aria-expanded="isOpen"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</slot>
|
|
21
21
|
</button>
|
|
22
22
|
<div
|
|
23
|
-
class="
|
|
23
|
+
class="collapsible-region__content"
|
|
24
24
|
tabindex="-1"
|
|
25
25
|
ref="content"
|
|
26
26
|
:id="contentId"
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
as they interfere with getting accurate measurements of the content
|
|
35
35
|
when it's hidden (scrollHeight)
|
|
36
36
|
-->
|
|
37
|
-
<div class="
|
|
37
|
+
<div class="collapsible-region__content-inner">
|
|
38
38
|
<slot/>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="menu-stack form-theme"
|
|
4
|
+
:class="{ 'menu-stack--hide-inputs' : hideInputs }"
|
|
5
|
+
:role="groupRole"
|
|
6
|
+
:aria-labelledby="legendId"
|
|
7
|
+
>
|
|
3
8
|
<div v-if="legend" :id="legendId" class="hidden-visually">{{ legend }}</div>
|
|
4
9
|
<ul class="menu-stack__list">
|
|
5
10
|
<li class="menu-stack__item" v-for="option in options" :key="option.uid">
|
|
6
11
|
<div class="menu-stack__selectable">
|
|
7
12
|
<input
|
|
8
|
-
class="menu-stack__selectable-input"
|
|
9
13
|
:type="type"
|
|
10
14
|
:id="getId(option)"
|
|
11
15
|
:name="name"
|
|
@@ -13,7 +17,7 @@
|
|
|
13
17
|
:checked="isChecked(option)"
|
|
14
18
|
@change="handleChange(option, $event)"
|
|
15
19
|
>
|
|
16
|
-
<label
|
|
20
|
+
<label :for="getId(option)">
|
|
17
21
|
<slot :option="option">
|
|
18
22
|
{{ option?.label || option?.title || option?.text }}
|
|
19
23
|
</slot>
|
|
@@ -35,11 +39,12 @@ const props = defineProps({
|
|
|
35
39
|
default: 'checkbox',
|
|
36
40
|
},
|
|
37
41
|
modelValue: [String, Array],
|
|
42
|
+
hideInputs: Boolean
|
|
38
43
|
});
|
|
39
44
|
|
|
40
45
|
const emit = defineEmits(['update:modelValue']);
|
|
41
46
|
|
|
42
|
-
const name = computed(() => props.legend ? props.legend.toLowerCase().replace(/\s+/g, '-') : `menu-${Math.random().toString(36).substring(7)}`);
|
|
47
|
+
const name = computed(() => props.legend ? props.legend.toLowerCase().replace(/\s+/g, '-') : `menu-${ Math.random().toString(36).substring(7) }`);
|
|
43
48
|
const legendId = computed(() => name.value ? `${name.value}-legend` : null);
|
|
44
49
|
const groupRole = computed(() => props.type === 'radio' ? 'radiogroup' : 'group');
|
|
45
50
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="UluFacetsFilters">
|
|
3
3
|
<UluCollapsibleRegion
|
|
4
|
-
class="
|
|
4
|
+
class="ulu-facets__group"
|
|
5
5
|
:class="classes.group"
|
|
6
|
-
:classToggle="['
|
|
7
|
-
:classContent="['
|
|
6
|
+
:classToggle="['ulu-facets__group-toggle', classes.groupToggle]"
|
|
7
|
+
:classContent="['ulu-facets__group-content', classes.groupContent]"
|
|
8
8
|
v-for="group in facets"
|
|
9
9
|
:key="group.uid"
|
|
10
10
|
:group="group"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
/>
|
|
30
30
|
<UluCollapsibleRegion
|
|
31
31
|
v-if="group.children.length > maxVisible"
|
|
32
|
-
class="
|
|
32
|
+
class="ulu-facets__more-facets"
|
|
33
33
|
:class="classes.moreFacets"
|
|
34
34
|
:clickOutsideCloses="false"
|
|
35
35
|
:closeOnEscape="false"
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
:options="getMenuOptions(group)"
|
|
21
21
|
:model-value="selectedUids(group)"
|
|
22
22
|
@update:model-value="onFilterChange(group, $event, close)"
|
|
23
|
+
:hideInputs="hideInputs"
|
|
23
24
|
/>
|
|
24
25
|
</template>
|
|
25
26
|
</UluPopover>
|
|
@@ -46,7 +47,8 @@ const props = defineProps({
|
|
|
46
47
|
// container: null,
|
|
47
48
|
// group: null
|
|
48
49
|
})
|
|
49
|
-
}
|
|
50
|
+
},
|
|
51
|
+
hideInputs: Boolean
|
|
50
52
|
});
|
|
51
53
|
|
|
52
54
|
const emit = defineEmits(['facet-change']);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
2
|
+
<div class="facets-dropdown-filters">
|
|
3
3
|
<div
|
|
4
|
-
class="
|
|
4
|
+
class="facets-dropdown-filters__group"
|
|
5
5
|
v-for="group in facets"
|
|
6
6
|
:key="group.uid"
|
|
7
7
|
>
|
|
8
|
-
<label :for="`facet-dropdown-${group.uid}`" class="
|
|
8
|
+
<label :for="`facet-dropdown-${group.uid}`" class="facets-dropdown-filters__label">
|
|
9
9
|
{{ group.name }}
|
|
10
10
|
</label>
|
|
11
11
|
<select
|
|
12
12
|
:id="`facet-dropdown-${group.uid}`"
|
|
13
|
-
class="
|
|
13
|
+
class="facets-dropdown-filters__select"
|
|
14
14
|
@change="onFilterChange(group, $event)"
|
|
15
15
|
>
|
|
16
16
|
<option value="">All {{ group.name }}s</option>
|
|
@@ -57,13 +57,13 @@ function onFilterChange(group, event) {
|
|
|
57
57
|
</script>
|
|
58
58
|
|
|
59
59
|
<style lang="scss">
|
|
60
|
-
.
|
|
60
|
+
.facets-dropdown-filters {
|
|
61
61
|
display: flex;
|
|
62
62
|
gap: 1rem;
|
|
63
63
|
align-items: center;
|
|
64
64
|
flex-wrap: wrap;
|
|
65
65
|
}
|
|
66
|
-
.
|
|
66
|
+
.facets-dropdown-filters__group {
|
|
67
67
|
display: flex;
|
|
68
68
|
gap: 0.5rem;
|
|
69
69
|
align-items: center;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
3
|
-
<div class="
|
|
2
|
+
<div class="facets-header-layout">
|
|
3
|
+
<div class="facets-header-layout__header">
|
|
4
4
|
<slot name="header"></slot>
|
|
5
5
|
</div>
|
|
6
|
-
<div class="
|
|
6
|
+
<div class="facets-header-layout__main">
|
|
7
7
|
<slot name="main"></slot>
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<style lang="scss">
|
|
17
|
-
.
|
|
17
|
+
.facets-header-layout__header {
|
|
18
18
|
display: flex;
|
|
19
19
|
gap: 1rem;
|
|
20
20
|
align-items: center;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
2
|
+
<div class="facets-results">
|
|
3
3
|
<transition-group
|
|
4
4
|
v-if="items.length"
|
|
5
5
|
:tag="tag"
|
|
6
6
|
:name="transitionName"
|
|
7
|
-
class="
|
|
7
|
+
class="facets-results__list"
|
|
8
8
|
:class="classes.list"
|
|
9
9
|
>
|
|
10
10
|
<li
|
|
11
|
-
class="
|
|
11
|
+
class="facets-results__item"
|
|
12
12
|
:class="classes.item"
|
|
13
13
|
v-for="(item, index) in items"
|
|
14
14
|
:key="item.id || index"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<slot name="item" :item="item" :index="index"></slot>
|
|
17
17
|
</li>
|
|
18
18
|
</transition-group>
|
|
19
|
-
<div v-else class="
|
|
19
|
+
<div v-else class="facets-results__empty">
|
|
20
20
|
<slot name="empty">
|
|
21
21
|
<p>No matching items found.</p>
|
|
22
22
|
</slot>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
transitionName: {
|
|
38
38
|
type: String,
|
|
39
|
-
default: '
|
|
39
|
+
default: 'facets-fade'
|
|
40
40
|
},
|
|
41
41
|
classes: {
|
|
42
42
|
type: Object,
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
</script>
|
|
47
47
|
|
|
48
48
|
<style lang="scss">
|
|
49
|
-
.
|
|
49
|
+
.facets-results__list {
|
|
50
50
|
list-style: none;
|
|
51
51
|
padding: 0;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
.
|
|
55
|
-
.
|
|
54
|
+
.facets-fade-enter-active,
|
|
55
|
+
.facets-fade-leave-active {
|
|
56
56
|
transition: opacity 0.25s ease;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
.
|
|
60
|
-
.
|
|
59
|
+
.facets-fade-enter-from,
|
|
60
|
+
.facets-fade-leave-to {
|
|
61
61
|
opacity: 0;
|
|
62
62
|
}
|
|
63
63
|
</style>
|
|
@@ -1,31 +1,70 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
class="facets-sidebar-layout"
|
|
4
|
+
:class="{ 'facets-sidebar-layout--filters-hidden' : isMobile }"
|
|
5
|
+
>
|
|
6
|
+
<div class="facets-sidebar-layout__header">
|
|
4
7
|
<slot name="header"></slot>
|
|
5
8
|
</div>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
<div v-show="isMobile" class="facets-sidebar-layout__mobile-controls">
|
|
11
|
+
<button class="button" @click="showMobileFilters = true">Filters & Sort</button>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="facets-sidebar-layout__body">
|
|
15
|
+
<!-- Desktop container for the sidebar -->
|
|
16
|
+
<div v-show="!isMobile" class="facets-sidebar-layout__sidebar" ref="desktopTarget"></div>
|
|
17
|
+
|
|
18
|
+
<div class="facets-sidebar-layout__main">
|
|
11
19
|
<slot name="main"></slot>
|
|
12
20
|
</div>
|
|
13
21
|
</div>
|
|
22
|
+
|
|
23
|
+
<UluModal
|
|
24
|
+
v-if="isMobile"
|
|
25
|
+
v-model="showMobileFilters"
|
|
26
|
+
position="right"
|
|
27
|
+
title="Filters & Sort"
|
|
28
|
+
allowResize
|
|
29
|
+
>
|
|
30
|
+
<!-- Mobile container for the sidebar -->
|
|
31
|
+
<div class="facets-sidebar-layout__sidebar" ref="mobileTarget"></div>
|
|
32
|
+
</UluModal>
|
|
33
|
+
|
|
34
|
+
<teleport :to="teleportTarget" v-if="teleportTarget">
|
|
35
|
+
<slot name="sidebar"></slot>
|
|
36
|
+
</teleport>
|
|
14
37
|
</div>
|
|
15
38
|
</template>
|
|
16
39
|
|
|
17
40
|
<script setup>
|
|
18
|
-
|
|
41
|
+
import { ref, inject, computed } from 'vue';
|
|
42
|
+
import UluModal from '../../collapsible/UluModal.vue';
|
|
43
|
+
|
|
44
|
+
const showMobileFilters = ref(false);
|
|
45
|
+
const isMobile = inject("uluIsMobile");
|
|
46
|
+
|
|
47
|
+
const desktopTarget = ref(null);
|
|
48
|
+
const mobileTarget = ref(null);
|
|
49
|
+
|
|
50
|
+
const teleportTarget = computed(() => {
|
|
51
|
+
if (isMobile.value) {
|
|
52
|
+
return mobileTarget.value;
|
|
53
|
+
} else {
|
|
54
|
+
return desktopTarget.value;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
19
57
|
</script>
|
|
20
58
|
|
|
21
59
|
<style lang="scss">
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
grid-template-columns: 1fr;
|
|
25
|
-
gap: 2rem;
|
|
26
|
-
|
|
27
|
-
@media (min-width: 768px) {
|
|
60
|
+
.facets-sidebar-layout__body {
|
|
61
|
+
display: grid;
|
|
28
62
|
grid-template-columns: 250px 1fr;
|
|
63
|
+
gap: 2rem;
|
|
64
|
+
}
|
|
65
|
+
.facets-sidebar-layout--filters-hidden {
|
|
66
|
+
.facets-sidebar-layout__body {
|
|
67
|
+
grid-template-columns: 1fr;
|
|
68
|
+
}
|
|
29
69
|
}
|
|
30
|
-
|
|
31
|
-
</style>
|
|
70
|
+
</style>
|