@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.
Files changed (63) hide show
  1. package/dist/frontend-vue.css +1 -1
  2. package/dist/frontend-vue.js +3315 -2668
  3. package/dist/types/components/collapsible/UluAccordionGroup.vue.d.ts +20 -0
  4. package/dist/types/components/collapsible/UluAccordionGroup.vue.d.ts.map +1 -1
  5. package/dist/types/components/elements/UluList.vue.d.ts.map +1 -1
  6. package/dist/types/components/elements/UluRule.vue.d.ts +19 -0
  7. package/dist/types/components/elements/UluRule.vue.d.ts.map +1 -0
  8. package/dist/types/components/forms/UluFormRadio.vue.d.ts +4 -4
  9. package/dist/types/components/index.d.ts +12 -0
  10. package/dist/types/components/layout/UluDataGrid.vue.d.ts +16 -1
  11. package/dist/types/components/layout/UluDataGrid.vue.d.ts.map +1 -1
  12. package/dist/types/components/layout/UluWhenBreakpoint.vue.d.ts.map +1 -1
  13. package/dist/types/components/systems/facets/UluFacetsFilterSelects.vue.d.ts +21 -2
  14. package/dist/types/components/systems/facets/UluFacetsFilterSelects.vue.d.ts.map +1 -1
  15. package/dist/types/components/systems/facets/UluFacetsSearch.vue.d.ts.map +1 -1
  16. package/dist/types/components/systems/index.d.ts +4 -0
  17. package/dist/types/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts +20 -58
  18. package/dist/types/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts.map +1 -1
  19. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsHeadlessSection.vue.d.ts +27 -0
  20. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsHeadlessSection.vue.d.ts.map +1 -0
  21. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNav.vue.d.ts +17 -13
  22. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNav.vue.d.ts.map +1 -1
  23. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue.d.ts +27 -30
  24. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue.d.ts.map +1 -1
  25. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsSection.vue.d.ts +27 -45
  26. package/dist/types/components/systems/scroll-anchors/UluScrollAnchorsSection.vue.d.ts.map +1 -1
  27. package/dist/types/components/systems/scroll-anchors/useScrollAnchorSection.d.ts +9 -0
  28. package/dist/types/components/systems/scroll-anchors/useScrollAnchorSection.d.ts.map +1 -0
  29. package/dist/types/components/systems/scroll-anchors/useScrollAnchorSections.d.ts +8 -0
  30. package/dist/types/components/systems/scroll-anchors/useScrollAnchorSections.d.ts.map +1 -0
  31. package/dist/types/components/systems/scroll-anchors/useScrollAnchors.d.ts +14 -0
  32. package/dist/types/components/systems/scroll-anchors/useScrollAnchors.d.ts.map +1 -0
  33. package/dist/types/plugins/popovers/defaults.d.ts.map +1 -1
  34. package/dist/types/plugins/popovers/index.d.ts.map +1 -1
  35. package/lib/components/_index.scss +1 -0
  36. package/lib/components/collapsible/UluAccordionGroup.vue +39 -5
  37. package/lib/components/collapsible/UluModal.vue +8 -8
  38. package/lib/components/elements/UluList.vue +3 -4
  39. package/lib/components/elements/UluRule.vue +49 -0
  40. package/lib/components/forms/UluFormRadio.vue +2 -2
  41. package/lib/components/index.js +12 -0
  42. package/lib/components/layout/UluDataGrid.vue +55 -15
  43. package/lib/components/layout/UluWhenBreakpoint.vue +14 -4
  44. package/lib/components/navigation/UluSkipLink.vue +1 -1
  45. package/lib/components/systems/facets/UluFacetsFilterSelects.vue +34 -7
  46. package/lib/components/systems/facets/UluFacetsSearch.vue +3 -3
  47. package/lib/components/systems/facets/UluFacetsSort.vue +3 -3
  48. package/lib/components/systems/index.js +4 -0
  49. package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +46 -145
  50. package/lib/components/systems/scroll-anchors/UluScrollAnchorsHeadlessSection.vue +50 -0
  51. package/lib/components/systems/scroll-anchors/UluScrollAnchorsNav.vue +18 -16
  52. package/lib/components/systems/scroll-anchors/UluScrollAnchorsNavAnimated.vue +100 -89
  53. package/lib/components/systems/scroll-anchors/UluScrollAnchorsSection.vue +65 -51
  54. package/lib/components/systems/scroll-anchors/_scroll-anchors-nav-animated.scss +67 -0
  55. package/lib/components/systems/scroll-anchors/useScrollAnchorSection.js +60 -0
  56. package/lib/components/systems/scroll-anchors/useScrollAnchorSections.js +15 -0
  57. package/lib/components/systems/scroll-anchors/useScrollAnchors.js +158 -0
  58. package/lib/plugins/popovers/defaults.js +10 -10
  59. package/lib/plugins/popovers/index.js +9 -0
  60. package/package.json +2 -2
  61. package/dist/types/components/systems/scroll-anchors/symbols.d.ts +0 -7
  62. package/dist/types/components/systems/scroll-anchors/symbols.d.ts.map +0 -1
  63. package/lib/components/systems/scroll-anchors/symbols.js +0 -6
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <component
3
+ :is="element"
4
+ :class="[
5
+ 'scroll-anchors__section',
6
+ { 'is-active': isActive }
7
+ ]"
8
+ :data-scrollpoint-state="sectionState"
9
+ ref="sectionRef"
10
+ >
11
+ <slot :isActive="isActive" :titleId="titleId" :section="section" :inactiveFrom="inactiveFrom" :activeFrom="activeFrom" :sectionState="sectionState" />
12
+ </component>
13
+ </template>
14
+
15
+ <script setup>
16
+ import { computed } from "vue";
17
+ import { useScrollAnchorSection } from "./useScrollAnchorSection";
18
+
19
+ const props = defineProps({
20
+ /**
21
+ * The title of the section, used for navigation and generating a default ID
22
+ */
23
+ title: {
24
+ type: String,
25
+ required: true
26
+ },
27
+ /**
28
+ * A custom ID to use for the section anchor, overriding the auto-generated one
29
+ */
30
+ customTitleId: String,
31
+ /**
32
+ * Element to use
33
+ */
34
+ element: {
35
+ type: String,
36
+ default: "div"
37
+ }
38
+ });
39
+
40
+ const { sectionRef, titleId, isActive, inactiveFrom, activeFrom, section } = useScrollAnchorSection(props);
41
+
42
+ const sectionState = computed(() => {
43
+ if (isActive.value) {
44
+ if (activeFrom.value) return `enter-${activeFrom.value}`;
45
+ } else {
46
+ if (inactiveFrom.value) return `exit-${inactiveFrom.value}`;
47
+ }
48
+ return null;
49
+ });
50
+ </script>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <component
3
- v-if="sections.length"
3
+ v-if="sections && sections.length"
4
4
  :is="element"
5
5
  class="scroll-anchors__nav"
6
6
  >
@@ -13,25 +13,27 @@
13
13
  :class="{ 'is-active' : item.active }"
14
14
  :href="`#${ item.titleId }`"
15
15
  >
16
- {{ item.title }}
16
+ <slot :item="item" :index="index">
17
+ {{ item.title }}
18
+ </slot>
17
19
  </a>
18
20
  </li>
19
21
  </ul>
20
22
  </component>
21
23
  </template>
22
24
 
23
- <script>
24
- import { SECTIONS } from "./symbols.js";
25
- export default {
26
- name: "ScrollAnchorsNav",
27
- inject: {
28
- sections: { from: SECTIONS }
29
- },
30
- props: {
31
- element: {
32
- type: String,
33
- default: "nav"
34
- }
25
+ <script setup>
26
+ import { useScrollAnchorSections } from "./useScrollAnchorSections.js";
27
+
28
+ defineProps({
29
+ /**
30
+ * The HTML element to use for the navigation root
31
+ */
32
+ element: {
33
+ type: String,
34
+ default: "nav"
35
35
  }
36
- };
37
- </script>
36
+ });
37
+
38
+ const sections = useScrollAnchorSections();
39
+ </script>
@@ -1,16 +1,11 @@
1
- <!--
2
- Version: 0.0.2
3
- Changes:
4
- - 0.0.2 | Added transition initial state/class so the indicator
5
- doesn't transition at first
6
- -->
7
1
  <template>
8
2
  <component
9
- v-if="sections.length"
3
+ v-if="sections && sections.length"
10
4
  :is="element"
11
- class="scroll-anchors__nav scroll-anchors__nav--animated"
5
+ class="scroll-anchors__nav scroll-anchors__nav--animated scroll-anchors-nav-animated"
6
+ :style="{ '--ulu-sa-nav-rail-width': `${ railWidth }px` }"
12
7
  >
13
- <ul class="scroll-anchors__rail">
8
+ <ul class="scroll-anchors-nav-animated__rail">
14
9
  <li
15
10
  v-for="(item, index) in sections" :key="index"
16
11
  :class="{ 'is-active' : item.active }"
@@ -20,105 +15,121 @@ Changes:
20
15
  :ref="(el) => addLinkRef(index, el)"
21
16
  :href="`#${ item.titleId }`"
22
17
  >
23
- {{ item.title }}
18
+ <slot :item="item" :index="index">
19
+ {{ item.title }}
20
+ </slot>
24
21
  </a>
25
22
  </li>
26
23
  </ul>
27
24
  <div
28
- class="scroll-anchors__indicator"
25
+ class="scroll-anchors-nav-animated__indicator"
29
26
  :class="{
30
- 'scroll-anchors__indicator--can-transition' : indicatorAnimReady
27
+ 'scroll-anchors-nav-animated__indicator--can-transition' : indicatorAnimReady
31
28
  }"
32
29
  ref="indicator"
33
- :style="{
30
+ :style="{
34
31
  opacity: indicatorStyles ? '1' : '0',
35
- transform: `translateY(${ indicatorStyles.y }px)`,
36
- height: `${ indicatorStyles.height }px`,
32
+ transform: `translateY(${ indicatorStyles ? indicatorStyles.y : 0 }px)`,
33
+ height: `${ indicatorStyles ? indicatorStyles.height : 0 }px`,
34
+ width: `${ indicatorStyles ? indicatorStyles.width : 0 }px`
37
35
  }"
38
36
  ></div>
39
37
  </component>
40
38
  </template>
41
39
 
42
- <script>
40
+ <script setup>
41
+ import { ref, computed, watch } from 'vue';
43
42
  import { runAfterFramePaint } from "@ulu/utils/browser/performance.js";
44
- import { SECTIONS } from "./symbols.js";
45
- export default {
46
- name: "ScrollAnchorsNavAnimated",
47
- inject: {
48
- sections: { from: SECTIONS }
43
+ import { useScrollAnchorSections } from './useScrollAnchorSections.js';
44
+
45
+ const props = defineProps({
46
+ /**
47
+ * The HTML element to use for the navigation root
48
+ */
49
+ element: {
50
+ type: String,
51
+ default: "nav"
49
52
  },
50
- props: {
51
- /**
52
- * Element to use for container
53
- */
54
- element: {
55
- type: String,
56
- default: "nav"
57
- },
53
+ /**
54
+ * The width of the navigation rail
55
+ */
56
+ railWidth: {
57
+ type: Number,
58
+ default: 3
58
59
  },
59
- data() {
60
- return {
61
- linkRefs: {},
62
- indicatorAnimReady: false
63
- };
60
+ /**
61
+ * The width of the indicator, defaults to railWidth
62
+ */
63
+ indicatorWidth: {
64
+ type: Number,
65
+ default: null
64
66
  },
65
- computed: {
66
- indicatorStyles() {
67
- const { sections, linkRefs } = this;
68
- const linkCount = Object.keys(linkRefs).length;
69
- // Checking for sections and link refs incase
70
- // we were waiting for the components to mount, etc
71
- if (!sections || !linkCount) {
72
- return false;
73
- }
74
- const activeIndex = sections.findIndex(s => s.active);
75
- if (activeIndex === -1) {
76
- return false;
77
- }
78
- const link = this.linkRefs[activeIndex];
79
- const { offsetTop, offsetHeight } = link;
80
- return {
81
- y: offsetTop,
82
- height: offsetHeight,
83
- initial: this.inidica
84
- };
85
- }
67
+ /**
68
+ * If set, creates a static height, centered indicator
69
+ */
70
+ indicatorHeight: {
71
+ type: Number,
72
+ default: null
86
73
  },
87
- watch: {
88
- indicatorStyles(val) {
89
- if (val && !this.indicatorAnimReady) {
90
- runAfterFramePaint(() => {
91
- this.indicatorAnimReady = true;
92
- });
93
- }
94
- }
74
+ /**
75
+ * Vertical alignment of the indicator relative to the link
76
+ */
77
+ indicatorAlignment: {
78
+ type: String,
79
+ default: 'center' // options: center, top
95
80
  },
96
- methods: {
97
- addLinkRef(index, el) {
98
- this.linkRefs[index] = el;
99
- }
81
+ /**
82
+ * Pixel offset for the indicator's vertical alignment
83
+ */
84
+ indicatorAlignmentOffset: {
85
+ type: Number,
86
+ default: 0
100
87
  }
101
- };
102
- </script>
88
+ });
103
89
 
104
- <style lang="scss">
105
- // User can override these styles
106
- // - Think this is better than props/etc
107
- // - Refactored from props to just plain css to be overridden
108
- .scroll-anchors__rail {
109
- border-left: 3px solid rgb(220, 220, 220);
110
- padding-left: 1rem;
111
- }
112
- .scroll-anchors__indicator {
113
- position: absolute;
114
- top: 0;
115
- left: 0;
116
- width: 3px;
117
- background-color: black;
118
- }
119
- .scroll-anchors__indicator--can-transition {
120
- transition-property: height, transform;
121
- transition-timing-function: ease-in-out;
122
- transition-duration: 250ms;
90
+ const sections = useScrollAnchorSections();
91
+
92
+ const linkRefs = ref({});
93
+ const indicatorAnimReady = ref(false);
94
+ const indicator = ref(null);
95
+
96
+ const indicatorStyles = computed(() => {
97
+ if (!sections || !sections.value || !sections.value.length) {
98
+ return false;
99
+ }
100
+ const activeIndex = sections.value.findIndex(s => s.active);
101
+ if (activeIndex === -1) {
102
+ return false;
103
+ }
104
+ const link = linkRefs.value[activeIndex];
105
+ if (!link) return false; // Link might not be rendered yet
106
+
107
+ const { offsetTop, offsetHeight } = link;
108
+ const isStatic = props.indicatorHeight != null;
109
+ const width = props.indicatorWidth ?? props.railWidth;
110
+ const height = isStatic ? props.indicatorHeight : offsetHeight;
111
+
112
+ let y = offsetTop; // Default to 'top' alignment
113
+ if (props.indicatorAlignment === 'center') {
114
+ y = offsetTop + (offsetHeight / 2) - (height / 2);
115
+ }
116
+
117
+ y += props.indicatorAlignmentOffset;
118
+
119
+ return { y, height, width };
120
+ });
121
+
122
+ watch(indicatorStyles, (val) => {
123
+ if (val && !indicatorAnimReady.value) {
124
+ runAfterFramePaint(() => {
125
+ indicatorAnimReady.value = true;
126
+ });
127
+ }
128
+ });
129
+
130
+ function addLinkRef(index, el) {
131
+ if (el) {
132
+ linkRefs.value[index] = el;
133
+ }
123
134
  }
124
- </style>
135
+ </script>
@@ -1,63 +1,77 @@
1
1
  <template>
2
- <div :class="[wrapperClass, { [activeClass] : activeClass && section?.active }]" ref="element">
2
+ <component
3
+ :is="element"
4
+ :class="[wrapperClass, { [activeClass]: activeClass && isActive }]"
5
+ :data-scrollpoint-state="sectionState"
6
+ ref="sectionRef"
7
+ >
3
8
  <component :is="titleElement" :class="titleClass" :id="titleId">
4
- {{ title }}
9
+ <slot name="title">
10
+ {{ title }}
11
+ </slot>
5
12
  </component>
6
13
  <slot :section="section"></slot>
7
- </div>
14
+ </component>
8
15
  </template>
9
16
 
10
- <script>
17
+ <script setup>
11
18
  import { computed } from "vue";
12
- import { urlize } from "@ulu/utils/string.js";
13
- import { REGISTER, UNREGISTER, SECTIONS } from "./symbols.js";
14
- export default {
15
- name: "ScrollAnchorsSection",
16
- props: {
17
- title: String,
18
- titleElement: {
19
- type: String,
20
- default: "h2"
21
- },
22
- titleClass: {
23
- type: String,
24
- default: "h2"
25
- },
26
- anchorId: String,
27
- wrapperClass: {
28
- type: String,
29
- default: "scroll-anchors__section"
30
- },
31
- activeClass: {
32
- type: String,
33
- default: 'is-active'
34
- }
35
- },
36
- inject: {
37
- register: { from: REGISTER },
38
- unregister: { from: UNREGISTER },
39
- sections: { from: SECTIONS, default: () => computed(() => []) }
19
+ import { useScrollAnchorSection } from "./useScrollAnchorSection";
20
+
21
+ const props = defineProps({
22
+ /**
23
+ * The title of the section, used for navigation and generating a default ID
24
+ */
25
+ title: String,
26
+ /**
27
+ * The HTML element to use for the title
28
+ */
29
+ titleElement: {
30
+ type: String,
31
+ default: "h2"
40
32
  },
41
- data() {
42
- const { anchorId, title } = this;
43
- return {
44
- titleId: anchorId || `sas-title-${ urlize(title) }`
45
- };
33
+ /**
34
+ * The class to apply to the title element
35
+ */
36
+ titleClass: {
37
+ type: String,
38
+ default: "h2"
46
39
  },
47
- computed: {
48
- section() {
49
- return this.sections.find(s => s.instance === this);
50
- }
40
+ /**
41
+ * A custom ID to use for the section anchor, overriding the auto-generated one
42
+ */
43
+ customTitleId: String,
44
+ /**
45
+ * The class to apply to the section's wrapper div
46
+ */
47
+ wrapperClass: {
48
+ type: String,
49
+ default: "scroll-anchors__section"
51
50
  },
52
- mounted() {
53
- if (this.register) {
54
- this.register(this);
55
- }
51
+ /**
52
+ * The class to apply to the wrapper div when the section is active
53
+ */
54
+ activeClass: {
55
+ type: String,
56
+ default: 'is-active'
56
57
  },
57
- unmounted() {
58
- if (this.unregister) {
59
- this.unregister(this);
60
- }
58
+ /**
59
+ * The HTML element to use for the section root
60
+ */
61
+ element: {
62
+ type: String,
63
+ default: 'section'
64
+ }
65
+ });
66
+
67
+ const { sectionRef, titleId, isActive, inactiveFrom, activeFrom, section } = useScrollAnchorSection(props);
68
+
69
+ const sectionState = computed(() => {
70
+ if (isActive.value) {
71
+ if (activeFrom.value) return `enter-${activeFrom.value}`;
72
+ } else {
73
+ if (inactiveFrom.value) return `exit-${inactiveFrom.value}`;
61
74
  }
62
- };
63
- </script>
75
+ return null;
76
+ });
77
+ </script>
@@ -0,0 +1,67 @@
1
+ ////
2
+ /// @group scroll-anchors-nav-animated
3
+ /// For use with UluScrollAnchorsNavAnimated vue component.
4
+ ////
5
+
6
+ @use "sass:map";
7
+ @use "sass:meta";
8
+
9
+ @use "@ulu/frontend/scss/selector";
10
+ @use "@ulu/frontend/scss/utils";
11
+ @use "@ulu/frontend/scss/color";
12
+
13
+ // Used for function fallback
14
+ $-fallbacks: () !default;
15
+
16
+ /// Module Settings
17
+ /// @type Map
18
+ $config: (
19
+ "rail-border-color": #dcdcdc,
20
+ "rail-padding": 1rem,
21
+ "indicator-color": #000,
22
+ "indicator-clip-path": null,
23
+ "transition-duration": 250ms,
24
+ "transition-timing-function": ease-in-out
25
+ ) !default;
26
+
27
+ /// Change modules $config
28
+ /// @param {Map} $changes Map of changes
29
+ @mixin set($changes) {
30
+ $config: map.merge($config, $changes) !global;
31
+ }
32
+
33
+ /// Get a config option
34
+ /// @param {Map} $name Name of property
35
+ @function get($name) {
36
+ $value: utils.require-map-get($config, $name, "scroll-anchors-nav-animated [config]");
37
+ @return utils.function-fallback($name, $value, $-fallbacks);
38
+ }
39
+
40
+ /// Prints component styles
41
+ /// @demo scroll-anchors-nav-animated
42
+ /// @example scss
43
+ /// @include ulu.component-scroll-anchors-nav-animated-styles();
44
+
45
+ @mixin styles {
46
+ $prefix: selector.class("scroll-anchors-nav-animated");
47
+
48
+ #{ $prefix } {
49
+ position: relative;
50
+ }
51
+ #{ $prefix }__rail {
52
+ border-left: var(--ulu-sa-nav-rail-width, 3px) solid color.get(get("rail-border-color"));
53
+ padding-left: get("rail-padding");
54
+ }
55
+ #{ $prefix }__indicator {
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ background-color: color.get(get("indicator-color"));
60
+ clip-path: get("indicator-clip-path");
61
+ }
62
+ #{ $prefix }__indicator--can-transition {
63
+ transition-property: height, transform, width;
64
+ transition-timing-function: get("transition-timing-function");
65
+ transition-duration: get("transition-duration");
66
+ }
67
+ }
@@ -0,0 +1,60 @@
1
+ import { ref, onMounted, onUnmounted, inject, computed, reactive, watch } from 'vue';
2
+ import { urlize } from '@ulu/utils/string.js';
3
+
4
+ /**
5
+ * Composable for a component that acts as a section within the Scroll Anchors system.
6
+ * It handles registering the section with the parent `UluScrollAnchors` component,
7
+ * manages its active state, and provides reactive properties for use in the template.
8
+ * @param {object} props The component props, requires `title` and optional `customTitleId`.
9
+ * @returns {object} An object with reactive properties for the section: `sectionRef` (the ref to bind), `titleId`, `isActive`, and the raw `section` object.
10
+ */
11
+ export function useScrollAnchorSection(props) {
12
+ const sectionRef = ref(null); // for the user to bind to their root element
13
+
14
+ const register = inject('uluScrollAnchorsRegister');
15
+ const unregister = inject('uluScrollAnchorsUnregister');
16
+ const newId = title => `ulu-sa-${ urlize(title) }`;
17
+
18
+ const titleId = computed(() => props.customTitleId || newId(props.title));
19
+
20
+ const section = reactive({
21
+ id: Symbol('section-id'),
22
+ title: props.title,
23
+ titleId: titleId.value,
24
+ element: null, // will be set on mount
25
+ active: false,
26
+ inactiveFrom: null,
27
+ activeFrom: null
28
+ });
29
+
30
+ // Keep title and titleId in sync with props
31
+ watch(() => props.title, (newTitle) => {
32
+ section.title = newTitle;
33
+ section.titleId = props.customTitleId || newId(newTitle);
34
+ });
35
+ watch(() => props.customTitleId, (newTitleId) => {
36
+ section.titleId = newTitleId || newId(props.title);
37
+ });
38
+
39
+ onMounted(() => {
40
+ if (register && sectionRef.value) {
41
+ section.element = sectionRef.value;
42
+ register(section);
43
+ }
44
+ });
45
+
46
+ onUnmounted(() => {
47
+ if (unregister) {
48
+ unregister(section.id);
49
+ }
50
+ });
51
+
52
+ return {
53
+ sectionRef, // the ref for the user to attach
54
+ titleId,
55
+ isActive: computed(() => section.active),
56
+ inactiveFrom: computed(() => section.inactiveFrom),
57
+ activeFrom: computed(() => section.activeFrom),
58
+ section
59
+ };
60
+ }
@@ -0,0 +1,15 @@
1
+ import { inject } from 'vue';
2
+
3
+ /**
4
+ * Composable that provides a reactive list of all registered scroll anchor sections.
5
+ * This is the recommended way to access section data for building custom navigation.
6
+ * Must be used within a component that is a descendant of `UluScrollAnchors`.
7
+ * @returns {object} A reactive ref containing an array of section objects.
8
+ */
9
+ export function useScrollAnchorSections() {
10
+ const sections = inject('uluScrollAnchorsSections');
11
+ if (!sections) {
12
+ console.warn('useScrollAnchorSections() must be used within an UluScrollAnchors component provider.');
13
+ }
14
+ return sections;
15
+ }