@ulu/frontend-vue 0.1.3-beta.2 → 0.1.3-beta.20
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/frontend-vue.css +1 -1
- package/dist/frontend-vue.js +3315 -2668
- package/dist/types/components/collapsible/UluAccordionGroup.vue.d.ts +20 -0
- package/dist/types/components/collapsible/UluAccordionGroup.vue.d.ts.map +1 -1
- package/dist/types/components/elements/UluList.vue.d.ts.map +1 -1
- package/dist/types/components/elements/UluRule.vue.d.ts +19 -0
- package/dist/types/components/elements/UluRule.vue.d.ts.map +1 -0
- package/dist/types/components/forms/UluFormRadio.vue.d.ts +4 -4
- package/dist/types/components/index.d.ts +12 -0
- package/dist/types/components/layout/UluDataGrid.vue.d.ts +16 -1
- package/dist/types/components/layout/UluDataGrid.vue.d.ts.map +1 -1
- package/dist/types/components/layout/UluWhenBreakpoint.vue.d.ts.map +1 -1
- package/dist/types/components/systems/facets/UluFacetsFilterSelects.vue.d.ts +21 -2
- package/dist/types/components/systems/facets/UluFacetsFilterSelects.vue.d.ts.map +1 -1
- package/dist/types/components/systems/facets/UluFacetsSearch.vue.d.ts.map +1 -1
- package/dist/types/components/systems/index.d.ts +4 -0
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts +20 -58
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts.map +1 -1
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsHeadlessSection.vue.d.ts +27 -0
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsHeadlessSection.vue.d.ts.map +1 -0
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNav.vue.d.ts +17 -13
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNav.vue.d.ts.map +1 -1
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue.d.ts +27 -30
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue.d.ts.map +1 -1
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsSection.vue.d.ts +27 -45
- package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsSection.vue.d.ts.map +1 -1
- package/dist/types/components/systems/scroll-anchors/useScrollAnchorSection.d.ts +9 -0
- package/dist/types/components/systems/scroll-anchors/useScrollAnchorSection.d.ts.map +1 -0
- package/dist/types/components/systems/scroll-anchors/useScrollAnchorSections.d.ts +8 -0
- package/dist/types/components/systems/scroll-anchors/useScrollAnchorSections.d.ts.map +1 -0
- package/dist/types/components/systems/scroll-anchors/useScrollAnchors.d.ts +14 -0
- package/dist/types/components/systems/scroll-anchors/useScrollAnchors.d.ts.map +1 -0
- package/dist/types/plugins/popovers/defaults.d.ts.map +1 -1
- package/dist/types/plugins/popovers/index.d.ts.map +1 -1
- package/lib/components/_index.scss +1 -0
- package/lib/components/collapsible/UluAccordionGroup.vue +39 -5
- package/lib/components/collapsible/UluModal.vue +8 -8
- package/lib/components/elements/UluList.vue +3 -4
- package/lib/components/elements/UluRule.vue +49 -0
- package/lib/components/forms/UluFormRadio.vue +2 -2
- package/lib/components/index.js +12 -0
- package/lib/components/layout/UluDataGrid.vue +55 -15
- package/lib/components/layout/UluWhenBreakpoint.vue +14 -4
- package/lib/components/navigation/UluSkipLink.vue +1 -1
- package/lib/components/systems/facets/UluFacetsFilterSelects.vue +34 -7
- package/lib/components/systems/facets/UluFacetsSearch.vue +3 -3
- package/lib/components/systems/facets/UluFacetsSort.vue +3 -3
- package/lib/components/systems/index.js +4 -0
- package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +46 -145
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsHeadlessSection.vue +50 -0
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsNav.vue +18 -16
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue +100 -89
- package/lib/components/systems/scroll-anchors/UluScrollAnchorsSection.vue +65 -51
- package/lib/components/systems/scroll-anchors/_scroll-anchors-nav-animated.scss +67 -0
- package/lib/components/systems/scroll-anchors/useScrollAnchorSection.js +60 -0
- package/lib/components/systems/scroll-anchors/useScrollAnchorSections.js +15 -0
- package/lib/components/systems/scroll-anchors/useScrollAnchors.js +158 -0
- package/lib/plugins/popovers/defaults.js +10 -10
- package/lib/plugins/popovers/index.js +9 -0
- package/package.json +2 -2
- package/dist/types/components/systems/scroll-anchors/symbols.d.ts +0 -7
- package/dist/types/components/systems/scroll-anchors/symbols.d.ts.map +0 -1
- package/lib/components/systems/scroll-anchors/symbols.js +0 -6
|
@@ -7,10 +7,23 @@
|
|
|
7
7
|
@update:modelValue="(newValue) => handleToggle(index, newValue)"
|
|
8
8
|
:trigger-text="item.title"
|
|
9
9
|
:classes="item.classes"
|
|
10
|
+
:trigger-text-element="triggerTextElement"
|
|
11
|
+
:modifiers="modifiers"
|
|
12
|
+
:animate="animate"
|
|
10
13
|
>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
</
|
|
14
|
+
<template #trigger="{ isOpen }" v-if="$slots.trigger">
|
|
15
|
+
<slot name="trigger" :item="item" :index="index" :isOpen="isOpen"></slot>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<template #icon="{ isOpen }" v-if="$slots.icon">
|
|
19
|
+
<slot name="icon" :item="item" :index="index" :isOpen="isOpen"></slot>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<template #default="{ isOpen, toggle }">
|
|
23
|
+
<slot name="item" :item="item" :index="index" :isOpen="isOpen" :toggle="toggle">
|
|
24
|
+
{{ item.content }}
|
|
25
|
+
</slot>
|
|
26
|
+
</template>
|
|
14
27
|
</UluAccordion>
|
|
15
28
|
</div>
|
|
16
29
|
</template>
|
|
@@ -27,7 +40,28 @@ const props = defineProps({
|
|
|
27
40
|
items: {
|
|
28
41
|
type: Array,
|
|
29
42
|
default: () => []
|
|
30
|
-
}
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* If using summary text sets the inner element the text is wrapped in, usually a headline or strong
|
|
46
|
+
*/
|
|
47
|
+
triggerTextElement: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: "strong"
|
|
50
|
+
},
|
|
51
|
+
/**
|
|
52
|
+
* Class modifiers (ie. 'transparent', 'secondary', etc)
|
|
53
|
+
*/
|
|
54
|
+
modifiers: [String, Array],
|
|
55
|
+
/**
|
|
56
|
+
* Enable or configure animations.
|
|
57
|
+
* - `false` (default) to disable all animations.
|
|
58
|
+
* - `true` to enable animations with default settings.
|
|
59
|
+
* - An object to provide custom options to auto-animate (e.g., { duration: 100, easing: 'linear' }).
|
|
60
|
+
*/
|
|
61
|
+
animate: {
|
|
62
|
+
type: [Boolean, Object],
|
|
63
|
+
default: true
|
|
64
|
+
},
|
|
31
65
|
});
|
|
32
66
|
|
|
33
67
|
const internalItems = ref([]);
|
|
@@ -51,4 +85,4 @@ function handleToggle(selectedIndex, newValue) {
|
|
|
51
85
|
internalItems.value[selectedIndex].isOpen = false;
|
|
52
86
|
}
|
|
53
87
|
}
|
|
54
|
-
</script>
|
|
88
|
+
</script>
|
|
@@ -216,14 +216,14 @@
|
|
|
216
216
|
// Define the internal modifiers object as a computed property (so it can react to changes)
|
|
217
217
|
const internalModifiers = computed(() => ({
|
|
218
218
|
[props.position]: props.position,
|
|
219
|
-
"resize": props.allowResize,
|
|
220
|
-
"no-resize": !props.allowResize,
|
|
221
|
-
"no-header": !hasHeader.value,
|
|
222
|
-
"body-fills": props.bodyFills,
|
|
223
|
-
"no-backdrop": props.noBackdrop,
|
|
224
|
-
"no-min-height": props.noMinHeight,
|
|
225
|
-
"non-modal": props.nonModal,
|
|
226
|
-
"resizer-active": resizerEnabled.value,
|
|
219
|
+
"resize" : props.allowResize,
|
|
220
|
+
"no-resize" : !props.allowResize,
|
|
221
|
+
"no-header" : !hasHeader.value,
|
|
222
|
+
"body-fills" : props.bodyFills,
|
|
223
|
+
"no-backdrop" : props.noBackdrop,
|
|
224
|
+
"no-min-height" : props.noMinHeight,
|
|
225
|
+
"non-modal" : props.nonModal,
|
|
226
|
+
"resizer-active" : resizerEnabled.value,
|
|
227
227
|
}));
|
|
228
228
|
|
|
229
229
|
const { resolvedModifiers } = useModifiers({
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
:style="{
|
|
14
14
|
listStyleType: listStyleType
|
|
15
15
|
}"
|
|
16
|
-
:reversed="reversed"
|
|
16
|
+
:reversed="isOrdered ? reversed : null"
|
|
17
17
|
:start="start"
|
|
18
18
|
>
|
|
19
19
|
<li
|
|
@@ -79,7 +79,6 @@
|
|
|
79
79
|
listStyleType: String,
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
});
|
|
82
|
+
const isOrdered = computed(() => props.ordered || props.forceOrdered);
|
|
83
|
+
const listElement = computed(() => isOrdered.value ? "ol" : "ul");
|
|
85
84
|
</script>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<hr v-if="semantic" class="rule" :class="resolvedModifiers">
|
|
3
|
+
<div v-else class="rule" :class="resolvedModifiers"></div>
|
|
4
|
+
</template>
|
|
5
|
+
|
|
6
|
+
<script setup>
|
|
7
|
+
import { computed } from "vue";
|
|
8
|
+
import { useModifiers } from "../../composables/useModifiers.js";
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
/**
|
|
12
|
+
* Whether to use the actual <hr> vs superficial <div></div> for rule element
|
|
13
|
+
*/
|
|
14
|
+
semantic: Boolean,
|
|
15
|
+
/**
|
|
16
|
+
* Use short modifier
|
|
17
|
+
*/
|
|
18
|
+
short: Boolean,
|
|
19
|
+
/**
|
|
20
|
+
* Optional margin (keyword from your rule margins config in frontend)
|
|
21
|
+
*/
|
|
22
|
+
margin: String,
|
|
23
|
+
/**
|
|
24
|
+
* Add light modifier (if set, usually exists, this is for convenience, use modifiers prop if you have custom naming)
|
|
25
|
+
*/
|
|
26
|
+
light: Boolean,
|
|
27
|
+
/**
|
|
28
|
+
* Add large modifier (if set, usually exists, this is for convenience, use modifiers prop if you have custom naming)
|
|
29
|
+
*/
|
|
30
|
+
large: Boolean,
|
|
31
|
+
/**
|
|
32
|
+
* Modifiers (to add any modifier classes based on base class [ie. 'tertiary'])
|
|
33
|
+
*/
|
|
34
|
+
modifiers: [String, Array]
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const internalModifiers = computed(() => ({
|
|
38
|
+
"short" : props.short,
|
|
39
|
+
"light" : props.light,
|
|
40
|
+
"large" : props.large,
|
|
41
|
+
[`margin-${ props.margin }`] : props.margin
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
const { resolvedModifiers } = useModifiers({
|
|
45
|
+
props,
|
|
46
|
+
baseClass: "rule",
|
|
47
|
+
internal: internalModifiers
|
|
48
|
+
});
|
|
49
|
+
</script>
|
|
@@ -27,11 +27,11 @@ defineProps({
|
|
|
27
27
|
/**
|
|
28
28
|
* The value of the selected radio button in the group (for v-model).
|
|
29
29
|
*/
|
|
30
|
-
modelValue: String,
|
|
30
|
+
modelValue: [String, Number],
|
|
31
31
|
/**
|
|
32
32
|
* The value of this radio button.
|
|
33
33
|
*/
|
|
34
|
-
value: String,
|
|
34
|
+
value: [String, Number],
|
|
35
35
|
/**
|
|
36
36
|
* The name of the radio button group.
|
|
37
37
|
*/
|
package/lib/components/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* - Used in main plugin and bundle exports
|
|
5
5
|
*/
|
|
6
6
|
export { default as UluAccordion } from './collapsible/UluAccordion.vue';
|
|
7
|
+
export { default as UluAccordionGroup } from './collapsible/UluAccordionGroup.vue';
|
|
7
8
|
export { default as UluCollapsible } from './collapsible/UluCollapsible.vue';
|
|
8
9
|
export { default as UluDropdown } from './collapsible/UluDropdown.vue';
|
|
9
10
|
export { default as UluModal } from './collapsible/UluModal.vue';
|
|
@@ -25,6 +26,7 @@ export { default as UluExternalLink } from './elements/UluExternalLink.vue';
|
|
|
25
26
|
export { default as UluIcon } from './elements/UluIcon.vue';
|
|
26
27
|
export { default as UluList } from './elements/UluList.vue';
|
|
27
28
|
export { default as UluMain } from './elements/UluMain.vue';
|
|
29
|
+
export { default as UluRule } from './elements/UluRule.vue';
|
|
28
30
|
export { default as UluSpokeSpinner } from './elements/UluSpokeSpinner.vue';
|
|
29
31
|
export { default as UluTag } from './elements/UluTag.vue';
|
|
30
32
|
export { default as UluSelectableMenu } from './forms/UluSelectableMenu.vue';
|
|
@@ -34,9 +36,19 @@ export { default as UluFormMessage } from './forms/UluFormMessage.vue';
|
|
|
34
36
|
export { default as UluFormSelect } from './forms/UluFormSelect.vue';
|
|
35
37
|
export { default as UluFormText } from './forms/UluFormText.vue';
|
|
36
38
|
export { default as UluSearchForm } from './forms/UluSearchForm.vue';
|
|
39
|
+
export { default as UluForm } from './forms/UluForm.vue';
|
|
40
|
+
export { default as UluFormActions } from './forms/UluFormActions.vue';
|
|
41
|
+
export { default as UluFormCheckbox } from './forms/UluFormCheckbox.vue';
|
|
42
|
+
export { default as UluFormFieldset } from './forms/UluFormFieldset.vue';
|
|
43
|
+
export { default as UluFormItem } from './forms/UluFormItem.vue';
|
|
44
|
+
export { default as UluFormItemsInline } from './forms/UluFormItemsInline.vue';
|
|
45
|
+
export { default as UluFormRadio } from './forms/UluFormRadio.vue';
|
|
46
|
+
export { default as UluFormRequiredChar } from './forms/UluFormRequiredChar.vue';
|
|
47
|
+
export { default as UluFormTextarea } from './forms/UluFormTextarea.vue';
|
|
37
48
|
export { default as UluAdaptiveLayout } from './layout/UluAdaptiveLayout.vue';
|
|
38
49
|
export { default as UluDataGrid } from './layout/UluDataGrid.vue';
|
|
39
50
|
export { default as UluTitleRail } from './layout/UluTitleRail.vue';
|
|
51
|
+
export { default as UluWhenBreakpoint } from './layout/UluWhenBreakpoint.vue';
|
|
40
52
|
export { default as UluBreadcrumb } from './navigation/UluBreadcrumb.vue';
|
|
41
53
|
export { default as UluMenu } from './navigation/UluMenu.vue';
|
|
42
54
|
export { default as UluMenuStack } from './navigation/UluMenuStack.vue';
|
|
@@ -16,26 +16,66 @@
|
|
|
16
16
|
-->
|
|
17
17
|
|
|
18
18
|
<template>
|
|
19
|
-
<
|
|
19
|
+
<component
|
|
20
|
+
:is="element"
|
|
21
|
+
:data-grid-init="initialized"
|
|
22
|
+
ref="rootElement"
|
|
23
|
+
>
|
|
20
24
|
<slot />
|
|
21
|
-
</
|
|
25
|
+
</component>
|
|
22
26
|
</template>
|
|
23
27
|
|
|
24
|
-
<script>
|
|
25
|
-
import {
|
|
28
|
+
<script setup>
|
|
29
|
+
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
|
|
26
30
|
import { debounce } from "@ulu/utils/performance.js";
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
import { setPositionClasses } from "@ulu/frontend/js/utils/dom.js";
|
|
32
|
+
|
|
33
|
+
const props = defineProps({
|
|
34
|
+
/**
|
|
35
|
+
* The element to use on data-grid container
|
|
36
|
+
*/
|
|
37
|
+
element: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: "div"
|
|
34
40
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Tell the component when this grid is actually in a hidden container
|
|
43
|
+
* - When value changes the component will properly update position classes
|
|
44
|
+
*/
|
|
45
|
+
hidden: Boolean // New prop from SSR version
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const rootElement = ref(null); // Ref for the template root element
|
|
49
|
+
const initialized = ref(null);
|
|
50
|
+
let setThisPositionClasses = null; // To store the setPositionClasses function
|
|
51
|
+
let resizeHandler = null; // To store the debounced resize handler
|
|
52
|
+
|
|
53
|
+
onMounted(async () => {
|
|
54
|
+
setThisPositionClasses = () => {
|
|
55
|
+
if (rootElement.value) {
|
|
56
|
+
setPositionClasses(rootElement.value);
|
|
38
57
|
}
|
|
58
|
+
};
|
|
59
|
+
setThisPositionClasses(); // Initial call
|
|
60
|
+
initialized.value = true;
|
|
61
|
+
resizeHandler = debounce(setThisPositionClasses, 200, false); // `this` context is not needed in setup
|
|
62
|
+
window.addEventListener("resize", resizeHandler);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
onBeforeUnmount(() => {
|
|
66
|
+
if (resizeHandler) {
|
|
67
|
+
resizeHandler.cancel();
|
|
68
|
+
window.removeEventListener("resize", resizeHandler);
|
|
69
|
+
resizeHandler = null;
|
|
70
|
+
setThisPositionClasses = null; // Clear the function reference
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Watcher for the hidden prop
|
|
75
|
+
watch(() => props.hidden, (newVal, oldVal) => {
|
|
76
|
+
// Only run setClasses if it was hidden and now it's not, and the function exists
|
|
77
|
+
if (oldVal && !newVal && setThisPositionClasses) {
|
|
78
|
+
setThisPositionClasses();
|
|
39
79
|
}
|
|
40
|
-
};
|
|
80
|
+
});
|
|
41
81
|
</script>
|
|
@@ -58,9 +58,19 @@
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
const tearDownHandlers = () => {
|
|
61
|
-
if (uluBreakpointManager) {
|
|
61
|
+
if (uluBreakpointManager.value) {
|
|
62
62
|
handlers.value.forEach(({ name, direction, handler }) => {
|
|
63
|
-
uluBreakpointManager.at(name)
|
|
63
|
+
const breakpoint = uluBreakpointManager.value.at(name);
|
|
64
|
+
if (breakpoint) {
|
|
65
|
+
try {
|
|
66
|
+
// HACK: The breakpoint.remove method is bugged, this is the correct implementation
|
|
67
|
+
if (breakpoint.directions[direction]) {
|
|
68
|
+
breakpoint.directions[direction].remove(handler);
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error(error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
64
74
|
});
|
|
65
75
|
}
|
|
66
76
|
handlers.value = [];
|
|
@@ -77,9 +87,9 @@
|
|
|
77
87
|
// Watch all the props and update if they change
|
|
78
88
|
// - Using array syntax to avoid "deep" flag
|
|
79
89
|
watch([() => props.max, () => props.min, () => props.only], () => {
|
|
80
|
-
if (uluBreakpointManager && handlersSetup.value) {
|
|
90
|
+
if (uluBreakpointManager.value && handlersSetup.value) {
|
|
81
91
|
tearDownHandlers();
|
|
82
|
-
setupHandlers(uluBreakpointManager);
|
|
92
|
+
setupHandlers(uluBreakpointManager.value);
|
|
83
93
|
}
|
|
84
94
|
});
|
|
85
95
|
|
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="facets-dropdown-filters">
|
|
2
|
+
<div class="facets-dropdown-filters" :class="classes.container">
|
|
3
3
|
<div
|
|
4
4
|
class="facets-dropdown-filters__group"
|
|
5
|
+
:class="classes.group"
|
|
5
6
|
v-for="group in facets"
|
|
6
7
|
:key="group.uid"
|
|
7
8
|
>
|
|
8
|
-
<label
|
|
9
|
-
{
|
|
9
|
+
<label
|
|
10
|
+
:for="`facet-dropdown-${ group.uid }`"
|
|
11
|
+
class="facets-dropdown-filters__label"
|
|
12
|
+
:class="classes.label"
|
|
13
|
+
>
|
|
14
|
+
<slot name="label">
|
|
15
|
+
{{ group.name }}
|
|
16
|
+
</slot>
|
|
10
17
|
</label>
|
|
11
18
|
<select
|
|
12
19
|
:id="`facet-dropdown-${group.uid}`"
|
|
13
20
|
class="facets-dropdown-filters__select"
|
|
21
|
+
:class="classes.select"
|
|
14
22
|
@change="onFilterChange(group, $event)"
|
|
15
23
|
>
|
|
16
|
-
<option value="">
|
|
24
|
+
<option value="">
|
|
25
|
+
<slot name="optionAll" :group="group">
|
|
26
|
+
All {{ group.name }}s
|
|
27
|
+
</slot>
|
|
28
|
+
</option>
|
|
17
29
|
<option
|
|
18
|
-
v-for="option in group.children"
|
|
30
|
+
v-for="(option, index) in group.children"
|
|
19
31
|
:key="option.uid"
|
|
20
32
|
:value="option.uid"
|
|
21
33
|
:selected="option.selected"
|
|
22
34
|
>
|
|
23
|
-
|
|
35
|
+
<slot name="option" :group="group" :option="option" :index="index">
|
|
36
|
+
{{ option.label }}
|
|
37
|
+
</slot>
|
|
24
38
|
</option>
|
|
25
39
|
</select>
|
|
26
40
|
</div>
|
|
@@ -29,12 +43,25 @@
|
|
|
29
43
|
|
|
30
44
|
<script setup>
|
|
31
45
|
const props = defineProps({
|
|
46
|
+
/**
|
|
47
|
+
* Facets Array
|
|
48
|
+
*/
|
|
32
49
|
facets: {
|
|
33
50
|
type: Array,
|
|
34
51
|
default: () => []
|
|
35
|
-
}
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Optional classes bindings for all elements { container, group, label, select }
|
|
55
|
+
*/
|
|
56
|
+
classes: {
|
|
57
|
+
type: Object,
|
|
58
|
+
default: () => ({})
|
|
59
|
+
},
|
|
36
60
|
});
|
|
37
61
|
|
|
62
|
+
console.log(props);
|
|
63
|
+
|
|
64
|
+
|
|
38
65
|
const emit = defineEmits(['facet-change']);
|
|
39
66
|
|
|
40
67
|
function onFilterChange(group, event) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="facets-search">
|
|
3
|
-
<label :class="classes.
|
|
2
|
+
<div class="facets-search" :class="classes.container">
|
|
3
|
+
<label :class="classes.label" :for="id">
|
|
4
4
|
<strong>Search</strong>
|
|
5
5
|
</label>
|
|
6
6
|
<input
|
|
7
7
|
:id="id"
|
|
8
|
-
:class="classes.
|
|
8
|
+
:class="classes.input"
|
|
9
9
|
v-model="localValue"
|
|
10
10
|
type="text"
|
|
11
11
|
:placeholder="placeholder"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="facets-sort" :class="classes.
|
|
2
|
+
<div class="facets-sort" :class="classes.container">
|
|
3
3
|
<label
|
|
4
4
|
:for="sortId"
|
|
5
|
-
:class="classes.
|
|
5
|
+
:class="classes.label"
|
|
6
6
|
>
|
|
7
7
|
<slot>Sort:</slot>
|
|
8
8
|
</label>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
:value="modelValue"
|
|
11
11
|
@change="emit('update:modelValue', $event.target.value)"
|
|
12
12
|
:id="sortId"
|
|
13
|
-
:class="classes.
|
|
13
|
+
:class="classes.select"
|
|
14
14
|
>
|
|
15
15
|
<option v-for="(item, key) in sortTypes" :value="key" :key="key">
|
|
16
16
|
{{ item.text }}
|
|
@@ -11,10 +11,14 @@ export { default as UluFacetsSidebarLayout } from './facets/UluFacetsSidebarLayo
|
|
|
11
11
|
export { default as UluFacetsSort } from './facets/UluFacetsSort.vue';
|
|
12
12
|
export { default as UluFacetsList } from './facets/UluFacetsList.vue';
|
|
13
13
|
|
|
14
|
+
export { useScrollAnchors } from './scroll-anchors/useScrollAnchors.js';
|
|
15
|
+
export { useScrollAnchorSection } from './scroll-anchors/useScrollAnchorSection.js';
|
|
16
|
+
export { useScrollAnchorSections } from './scroll-anchors/useScrollAnchorSections.js';
|
|
14
17
|
export { default as UluScrollAnchors } from './scroll-anchors/UluScrollAnchors.vue';
|
|
15
18
|
export { default as UluScrollAnchorsNav } from './scroll-anchors/UluScrollAnchorsNav.vue';
|
|
16
19
|
export { default as UluScrollAnchorsNavAnimated } from './scroll-anchors/UluScrollAnchorsNavAnimated.vue';
|
|
17
20
|
export { default as UluScrollAnchorsSection } from './scroll-anchors/UluScrollAnchorsSection.vue';
|
|
21
|
+
export { default as UluScrollAnchorsHeadlessSection } from './scroll-anchors/UluScrollAnchorsHeadlessSection.vue';
|
|
18
22
|
|
|
19
23
|
export { default as UluShowSkeleton } from './skeleton/UluShowSkeleton.vue';
|
|
20
24
|
export { default as UluSkeletonContent } from './skeleton/UluSkeletonContent.vue';
|
|
@@ -1,153 +1,54 @@
|
|
|
1
|
-
<!-- Version: 0.0.2? (NEED to diff, unsure of changes) -->
|
|
2
1
|
<template>
|
|
3
|
-
<div class="scroll-anchors">
|
|
2
|
+
<div class="scroll-anchors" ref="componentEl">
|
|
4
3
|
<slot/>
|
|
5
4
|
</div>
|
|
6
5
|
</template>
|
|
7
6
|
|
|
8
|
-
<script>
|
|
9
|
-
import { computed } from "vue";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
emits: ["section-change"],
|
|
14
|
-
props: {
|
|
15
|
-
firstItemActive: Boolean,
|
|
16
|
-
/**
|
|
17
|
-
* Observe
|
|
18
|
-
*/
|
|
19
|
-
observerOptions: {
|
|
20
|
-
type: Object,
|
|
21
|
-
default: () => ({
|
|
22
|
-
root: null,
|
|
23
|
-
threshhold: [0,1],
|
|
24
|
-
rootMargin: "-25% 0px -55% 0px"
|
|
25
|
-
// root: null,
|
|
26
|
-
// threshhold: [0,1],
|
|
27
|
-
// rootMargin: "25% 0px 75% 0px"
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
data() {
|
|
32
|
-
return {
|
|
33
|
-
isMounted: false,
|
|
34
|
-
sections: [], // Child components will section themselves
|
|
35
|
-
};
|
|
36
|
-
},
|
|
7
|
+
<script setup>
|
|
8
|
+
import { ref, computed, provide } from "vue";
|
|
9
|
+
import { useScrollAnchors } from "./useScrollAnchors.js";
|
|
10
|
+
|
|
11
|
+
const props = defineProps({
|
|
37
12
|
/**
|
|
38
|
-
*
|
|
39
|
-
* - Uses symbols
|
|
13
|
+
* Make the first item active by default on load
|
|
40
14
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.update();
|
|
55
|
-
},
|
|
56
|
-
[UNREGISTER]: (instance) => {
|
|
57
|
-
const sections = this.sections;
|
|
58
|
-
const index = sections.findIndex(r => r.instance === instance);
|
|
59
|
-
if (index > -1) {
|
|
60
|
-
sections.splice(index, 1);
|
|
61
|
-
}
|
|
62
|
-
this.update();
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
methods: {
|
|
67
|
-
update() {
|
|
68
|
-
if (this.isMounted) {
|
|
69
|
-
this.observeItems();
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
getSectionIndex(el) {
|
|
73
|
-
return this.sections.findIndex(({ element }) => el === element);
|
|
74
|
-
},
|
|
75
|
-
/**
|
|
76
|
-
* Sets up a new observer to watch the section visibility
|
|
77
|
-
*/
|
|
78
|
-
createObserver() {
|
|
79
|
-
const { observerOptions, sections, removeActive, firstItemActive } = this;
|
|
80
|
-
let lastY = 0;
|
|
81
|
-
// Observer callback, basically just sets active state for a given slide
|
|
82
|
-
// - isIntersecting will change when the element enters and leaves
|
|
83
|
-
const onObserve = (entries) => {
|
|
84
|
-
entries.forEach(({ target, isIntersecting }) => {
|
|
85
|
-
const index = this.getSectionIndex(target);
|
|
86
|
-
const y = target.offsetTop;
|
|
87
|
-
const section = sections[index];
|
|
88
|
-
const firstExiting = index === 0 && lastY > y;
|
|
89
|
-
const lastExiting = index === sections.length - 1 && lastY < y;
|
|
90
|
-
if (section) {
|
|
91
|
-
this.$nextTick(() => {
|
|
92
|
-
if (isIntersecting) {
|
|
93
|
-
removeActive(section);
|
|
94
|
-
section.active = true;
|
|
95
|
-
// Only allow first and last to
|
|
96
|
-
} else if (firstExiting && !firstItemActive) {
|
|
97
|
-
removeActive();
|
|
98
|
-
} else if (lastExiting && section.active) {
|
|
99
|
-
removeActive();
|
|
100
|
-
}
|
|
101
|
-
this.$emit("section-change", {
|
|
102
|
-
section,
|
|
103
|
-
sections,
|
|
104
|
-
active: isIntersecting
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
// Add non-reactive prop for removal and changes to targets
|
|
111
|
-
this.observer = new IntersectionObserver(onObserve, observerOptions);
|
|
112
|
-
},
|
|
113
|
-
/**
|
|
114
|
-
* Add all slide elements as targets in observer
|
|
115
|
-
*/
|
|
116
|
-
observeItems() {
|
|
117
|
-
const { observer, sections } = this;
|
|
118
|
-
observer.disconnect();
|
|
119
|
-
sections.forEach(({ element }) => {
|
|
120
|
-
if (element) {
|
|
121
|
-
observer.observe(element);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
},
|
|
125
|
-
removeActive(except = null) {
|
|
126
|
-
this.sections.forEach(s => {
|
|
127
|
-
if (s !== except) {
|
|
128
|
-
s.active = false;
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
},
|
|
132
|
-
/**
|
|
133
|
-
* Remove observer and it's internal DOM references (GC)
|
|
134
|
-
*/
|
|
135
|
-
destroyObserver() {
|
|
136
|
-
this.observer.disconnect();
|
|
137
|
-
this.observer = null;
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
mounted() {
|
|
141
|
-
const first = this.sections[0];
|
|
142
|
-
if (this.firstItemActive && first) {
|
|
143
|
-
first.active = true;
|
|
144
|
-
}
|
|
145
|
-
this.createObserver();
|
|
146
|
-
this.observeItems();
|
|
147
|
-
this.isMounted = true;
|
|
148
|
-
},
|
|
149
|
-
unmounted() {
|
|
150
|
-
this.destroyObserver();
|
|
15
|
+
firstItemActive: Boolean,
|
|
16
|
+
/**
|
|
17
|
+
* IntersectionObserver options
|
|
18
|
+
* - Defaults: { root: null, threshold: 0, rootMargin: "-25% 0px -55% 0px" }
|
|
19
|
+
* See: https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver
|
|
20
|
+
*/
|
|
21
|
+
observerOptions: {
|
|
22
|
+
type: Object,
|
|
23
|
+
default: () => ({
|
|
24
|
+
root: null,
|
|
25
|
+
threshold: 0,
|
|
26
|
+
rootMargin: "-25% 0px -55% 0px"
|
|
27
|
+
})
|
|
151
28
|
},
|
|
152
|
-
|
|
153
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Enable debug logging for the IntersectionObserver
|
|
31
|
+
*/
|
|
32
|
+
debug: Boolean
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const emit = defineEmits(["section-change"]);
|
|
36
|
+
|
|
37
|
+
const sections = ref([]);
|
|
38
|
+
const componentEl = ref(null);
|
|
39
|
+
|
|
40
|
+
useScrollAnchors({ sections, props, emit, componentElRef: componentEl });
|
|
41
|
+
|
|
42
|
+
provide('uluScrollAnchorsSections', computed(() => sections.value));
|
|
43
|
+
|
|
44
|
+
provide('uluScrollAnchorsRegister', (section) => {
|
|
45
|
+
sections.value.push(section);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
provide('uluScrollAnchorsUnregister', (sectionId) => {
|
|
49
|
+
const index = sections.value.findIndex(r => r.id === sectionId);
|
|
50
|
+
if (index > -1) {
|
|
51
|
+
sections.value.splice(index, 1);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
</script>
|