@asd20/ui-next 2.0.1 → 2.0.2
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/CHANGELOG.md +7 -0
- package/package.json +1 -2
- package/src/directives/scroll-track.js +175 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.2](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.0.1...ui-next-v2.0.2) (2026-03-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* replace basicscroll scroll-track runtime ([c0fe361](https://github.com/academydistrict20/asd20-ui-next/commit/c0fe361c301bbf1d132eac7876c5e02cabe4a5b0))
|
|
9
|
+
|
|
3
10
|
## [2.0.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.0.0...ui-next-v2.0.1) (2026-03-27)
|
|
4
11
|
|
|
5
12
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asd20/ui-next",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "ASD20 UI component library for Vue 3.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"axios": "^1.13.6",
|
|
37
|
-
"basicscroll": "^3.0.2",
|
|
38
37
|
"countup.js": "^2.0.0",
|
|
39
38
|
"date-fns": "^2.30.0",
|
|
40
39
|
"date-fns-tz": "^1.1.7",
|
|
@@ -1,32 +1,190 @@
|
|
|
1
|
-
|
|
1
|
+
const DEFAULT_VARIABLE_NAME = 'scroll-progress'
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function clamp(value, min, max) {
|
|
4
|
+
return Math.min(Math.max(value, min), max)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getScrollTop() {
|
|
8
|
+
const scrollingElement =
|
|
9
|
+
document.scrollingElement || document.documentElement || document.body
|
|
10
|
+
|
|
11
|
+
return scrollingElement ? scrollingElement.scrollTop : 0
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getViewportHeight() {
|
|
15
|
+
return (
|
|
16
|
+
window.innerHeight ||
|
|
17
|
+
window.outerHeight ||
|
|
18
|
+
document.documentElement?.clientHeight ||
|
|
19
|
+
1
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function parseAbsoluteValue(value) {
|
|
24
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
25
|
+
return value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof value !== 'string') {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const parsedValue = Number.parseFloat(value)
|
|
33
|
+
|
|
34
|
+
return Number.isFinite(parsedValue) ? parsedValue : null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resolveKeywordValue(value, el, scrollTop, viewportHeight) {
|
|
38
|
+
if (!el || typeof value !== 'string') {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const match = value.match(/^(top|middle|bottom)-(top|middle|bottom)$/)
|
|
43
|
+
|
|
44
|
+
if (!match) {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const [, elementEdge, viewportEdge] = match
|
|
49
|
+
const rect = el.getBoundingClientRect()
|
|
50
|
+
let absoluteOffset = scrollTop + rect.top
|
|
51
|
+
|
|
52
|
+
if (elementEdge === 'middle') {
|
|
53
|
+
absoluteOffset += rect.height / 2
|
|
54
|
+
} else if (elementEdge === 'bottom') {
|
|
55
|
+
absoluteOffset += rect.height
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (viewportEdge === 'middle') {
|
|
59
|
+
absoluteOffset -= viewportHeight / 2
|
|
60
|
+
} else if (viewportEdge === 'bottom') {
|
|
61
|
+
absoluteOffset -= viewportHeight
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return absoluteOffset
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function resolveBoundary(value, el, scrollTop, viewportHeight) {
|
|
68
|
+
const absoluteValue = parseAbsoluteValue(value)
|
|
69
|
+
|
|
70
|
+
if (absoluteValue !== null) {
|
|
71
|
+
return absoluteValue
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return resolveKeywordValue(value, el, scrollTop, viewportHeight)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getBindingConfig(el, { modifiers = {}, expression } = {}) {
|
|
78
|
+
const viewportHeight = getViewportHeight()
|
|
79
|
+
const scrollTop = getScrollTop()
|
|
80
|
+
const from = modifiers.window
|
|
81
|
+
? 0
|
|
82
|
+
: resolveBoundary('middle-top', el, scrollTop, viewportHeight)
|
|
83
|
+
const to = modifiers.window
|
|
84
|
+
? window.outerHeight || viewportHeight
|
|
85
|
+
: resolveBoundary('middle-bottom', el, scrollTop, viewportHeight)
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
cssVariable: `--${expression || DEFAULT_VARIABLE_NAME}`,
|
|
89
|
+
from,
|
|
90
|
+
to,
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function setProgress(el, cssVariable, progress) {
|
|
95
|
+
const normalizedProgress = Number.isFinite(progress)
|
|
96
|
+
? Math.round(progress * 10000) / 10000
|
|
97
|
+
: 0
|
|
98
|
+
|
|
99
|
+
el.style.setProperty(cssVariable, String(normalizedProgress))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function updateScrollTrack(el) {
|
|
103
|
+
if (typeof window === 'undefined' || !el.__scrollTrackState) {
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const scrollTop = getScrollTop()
|
|
108
|
+
const { cssVariable, from, to } = getBindingConfig(
|
|
109
|
+
el,
|
|
110
|
+
el.__scrollTrackState.binding
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if (from === null || to === null) {
|
|
114
|
+
setProgress(el, cssVariable, 0)
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (from === to) {
|
|
119
|
+
setProgress(el, cssVariable, scrollTop >= to ? 1 : 0)
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const progress = clamp((scrollTop - from) / (to - from), 0, 1)
|
|
124
|
+
|
|
125
|
+
setProgress(el, cssVariable, progress)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function mountScrollTrack(el, binding = {}) {
|
|
4
129
|
if (typeof window === 'undefined') return
|
|
5
130
|
|
|
6
|
-
el
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
131
|
+
unmountScrollTrack(el)
|
|
132
|
+
|
|
133
|
+
const state = {
|
|
134
|
+
binding,
|
|
135
|
+
frameId: null,
|
|
136
|
+
handleUpdate() {
|
|
137
|
+
updateScrollTrack(el)
|
|
138
|
+
},
|
|
139
|
+
scheduleUpdate() {
|
|
140
|
+
if (state.frameId !== null) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
state.frameId = window.requestAnimationFrame(() => {
|
|
145
|
+
state.frameId = null
|
|
146
|
+
state.handleUpdate()
|
|
147
|
+
})
|
|
16
148
|
},
|
|
17
|
-
}
|
|
18
|
-
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
el.__scrollTrackState = state
|
|
152
|
+
updateScrollTrack(el)
|
|
153
|
+
|
|
154
|
+
window.addEventListener('scroll', state.scheduleUpdate, { passive: true })
|
|
155
|
+
window.addEventListener('resize', state.scheduleUpdate)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function updateBinding(el, binding = {}) {
|
|
159
|
+
if (!el.__scrollTrackState) {
|
|
160
|
+
mountScrollTrack(el, binding)
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
el.__scrollTrackState.binding = binding
|
|
165
|
+
updateScrollTrack(el)
|
|
19
166
|
}
|
|
20
167
|
|
|
21
168
|
function unmountScrollTrack(el) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
169
|
+
const state = el.__scrollTrackState
|
|
170
|
+
|
|
171
|
+
if (!state || typeof window === 'undefined') return
|
|
172
|
+
|
|
173
|
+
window.removeEventListener('scroll', state.scheduleUpdate)
|
|
174
|
+
window.removeEventListener('resize', state.scheduleUpdate)
|
|
175
|
+
|
|
176
|
+
if (state.frameId !== null) {
|
|
177
|
+
window.cancelAnimationFrame(state.frameId)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
delete el.__scrollTrackState
|
|
25
181
|
}
|
|
26
182
|
|
|
27
183
|
export default {
|
|
28
184
|
inserted: mountScrollTrack,
|
|
29
185
|
mounted: mountScrollTrack,
|
|
186
|
+
update: updateBinding,
|
|
187
|
+
updated: updateBinding,
|
|
30
188
|
unbind: unmountScrollTrack,
|
|
31
189
|
unmounted: unmountScrollTrack,
|
|
32
190
|
}
|