@mixd-id/web-scaffold 0.1.240411077 → 0.1.240411079
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/package.json
CHANGED
|
@@ -101,6 +101,11 @@ export default{
|
|
|
101
101
|
timeoutId: null,
|
|
102
102
|
scrollPosition: null,
|
|
103
103
|
swiping: false,
|
|
104
|
+
|
|
105
|
+
// physics state
|
|
106
|
+
_rafId: null,
|
|
107
|
+
_anim: null,
|
|
108
|
+
_currentX: 0,
|
|
104
109
|
}
|
|
105
110
|
},
|
|
106
111
|
|
|
@@ -108,10 +113,17 @@ export default{
|
|
|
108
113
|
window.addEventListener('touchmove', this.onTouchMove, { passive: false });
|
|
109
114
|
if(this.autoPlay > 0)
|
|
110
115
|
this.play()
|
|
116
|
+
|
|
117
|
+
// initialize transform position
|
|
118
|
+
window.requestAnimationFrame(() => {
|
|
119
|
+
this._currentX = this._getCurrentX()
|
|
120
|
+
this._applyX(this._currentX)
|
|
121
|
+
})
|
|
111
122
|
},
|
|
112
123
|
|
|
113
124
|
unmounted() {
|
|
114
125
|
window.removeEventListener('touchmove', this.onTouchMove, { passive: false });
|
|
126
|
+
this._stopRaf()
|
|
115
127
|
},
|
|
116
128
|
|
|
117
129
|
watch:{
|
|
@@ -136,30 +148,99 @@ export default{
|
|
|
136
148
|
}
|
|
137
149
|
},
|
|
138
150
|
|
|
139
|
-
|
|
140
|
-
|
|
151
|
+
_stopRaf(){
|
|
152
|
+
if(this._rafId){
|
|
153
|
+
cancelAnimationFrame(this._rafId)
|
|
154
|
+
this._rafId = null
|
|
155
|
+
}
|
|
156
|
+
this._anim = null
|
|
157
|
+
},
|
|
141
158
|
|
|
142
|
-
|
|
143
|
-
|
|
159
|
+
_applyX(x){
|
|
160
|
+
this._currentX = x
|
|
161
|
+
if(this.$el?.firstElementChild)
|
|
162
|
+
this.$el.firstElementChild.style.transform = `translate3d(${x}px, 0, 0)`
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
_getCurrentX(){
|
|
166
|
+
const t = this.$el?.firstElementChild?.style?.transform || ''
|
|
167
|
+
const matches = t.match(/translate3d\((.*?)(?=\,)/)
|
|
168
|
+
return matches != null && typeof matches[1] !== 'undefined'
|
|
169
|
+
? parseFloat(matches[1].replace('px', ''))
|
|
170
|
+
: 0
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
_getTargetXForIndex(index){
|
|
174
|
+
if(!this.$refs.inner) return 0
|
|
175
|
+
|
|
176
|
+
let left = 0
|
|
144
177
|
const gapPx = parseInt(window.getComputedStyle(this.$refs.inner).getPropertyValue('column-gap'))
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
178
|
+
for(let curIndex = 0 ; curIndex < this.items.length ; curIndex++){
|
|
179
|
+
const item = this.$refs.inner.children[curIndex]
|
|
180
|
+
if(curIndex < index)
|
|
181
|
+
left += (item.clientWidth + (!isNaN(gapPx) ? gapPx : 0))
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return left * -1
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
_rubberBand(distance, dimension, constant = 0.55){
|
|
188
|
+
// similar to iOS rubber-banding
|
|
189
|
+
const abs = Math.abs(distance)
|
|
190
|
+
const result = (dimension * constant * abs) / (dimension + constant * abs)
|
|
191
|
+
return Math.sign(distance) * result
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
_springTo(targetX, { stiffness = 0.09, damping = 0.78, maxDuration = 900 } = {}){
|
|
195
|
+
this._stopRaf()
|
|
150
196
|
|
|
151
|
-
|
|
197
|
+
const startTime = performance.now()
|
|
198
|
+
let x = this._getCurrentX()
|
|
199
|
+
let v = 0
|
|
152
200
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
201
|
+
const step = (now) => {
|
|
202
|
+
const dtMs = now - (this._anim?.t || now)
|
|
203
|
+
const dt = Math.min(0.032, Math.max(0.008, dtMs / 1000))
|
|
204
|
+
this._anim = { t: now }
|
|
205
|
+
|
|
206
|
+
// spring force
|
|
207
|
+
const F = (targetX - x) * stiffness
|
|
208
|
+
v = (v + F) * damping
|
|
209
|
+
x = x + v / dt
|
|
210
|
+
|
|
211
|
+
// numerical safety
|
|
212
|
+
if(!isFinite(x)) x = targetX
|
|
213
|
+
|
|
214
|
+
this._applyX(x)
|
|
215
|
+
|
|
216
|
+
const elapsed = now - startTime
|
|
217
|
+
const done = (Math.abs(targetX - x) < 0.5 && Math.abs(v) < 0.1) || elapsed > maxDuration
|
|
218
|
+
|
|
219
|
+
if(done){
|
|
220
|
+
this._applyX(targetX)
|
|
221
|
+
this._stopRaf()
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
this._rafId = requestAnimationFrame(step)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
this._rafId = requestAnimationFrame(step)
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
setPosition(noAnimation) {
|
|
232
|
+
if(!this.$refs.inner) return
|
|
233
|
+
|
|
234
|
+
const left = this._getTargetXForIndex(this.index)
|
|
235
|
+
|
|
236
|
+
if(noAnimation){
|
|
237
|
+
this._stopRaf()
|
|
238
|
+
window.requestAnimationFrame(() => this._applyX(left))
|
|
239
|
+
return
|
|
158
240
|
}
|
|
159
241
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
})
|
|
242
|
+
// spring settle
|
|
243
|
+
this._springTo(left)
|
|
163
244
|
},
|
|
164
245
|
|
|
165
246
|
setIndex(index){
|
|
@@ -176,18 +257,13 @@ export default{
|
|
|
176
257
|
index = useBack === true ? 0 : this.items.length - 1
|
|
177
258
|
|
|
178
259
|
this.index = index
|
|
179
|
-
|
|
180
260
|
this.setPosition()
|
|
181
261
|
},
|
|
182
262
|
|
|
183
263
|
prev(){
|
|
184
|
-
|
|
185
264
|
let index = this.index - 1;
|
|
186
|
-
|
|
187
265
|
if(index < 0) index = 0
|
|
188
|
-
|
|
189
266
|
this.index = index
|
|
190
|
-
|
|
191
267
|
this.setPosition()
|
|
192
268
|
},
|
|
193
269
|
|
|
@@ -217,16 +293,20 @@ export default{
|
|
|
217
293
|
}
|
|
218
294
|
}
|
|
219
295
|
else if(this._props['direction'] === 'horizontal'){
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
296
|
+
const baseX = this._props['ix']
|
|
297
|
+
let nextX = baseX + dx
|
|
298
|
+
|
|
299
|
+
const atFirst = this.index === 0
|
|
300
|
+
const atLast = this.index === this.items.length - 1
|
|
301
|
+
const overscrolling = (atFirst && dx > 0) || (atLast && dx < 0)
|
|
302
|
+
|
|
303
|
+
if(overscrolling){
|
|
304
|
+
const dim = this.$el?.clientWidth || 1
|
|
305
|
+
nextX = baseX + this._rubberBand(dx, dim)
|
|
227
306
|
}
|
|
228
307
|
|
|
229
|
-
this
|
|
308
|
+
this._stopRaf() // user is directly controlling
|
|
309
|
+
this._applyX(nextX)
|
|
230
310
|
}
|
|
231
311
|
|
|
232
312
|
},
|
|
@@ -268,8 +348,9 @@ export default{
|
|
|
268
348
|
|
|
269
349
|
this.stop()
|
|
270
350
|
|
|
271
|
-
|
|
272
|
-
|
|
351
|
+
// stop any running spring and capture current position
|
|
352
|
+
this._stopRaf()
|
|
353
|
+
const ix = this._getCurrentX()
|
|
273
354
|
|
|
274
355
|
this._props = {
|
|
275
356
|
sx:typeof e.touches !== 'undefined' ? e.touches[0].clientX : e.clientX,
|
|
@@ -292,21 +373,9 @@ export default{
|
|
|
292
373
|
|
|
293
374
|
<style>
|
|
294
375
|
|
|
295
|
-
|
|
296
|
-
.carousel-prev{
|
|
297
|
-
position: absolute;
|
|
298
|
-
top: 50%;
|
|
299
|
-
transform: translate3d(0, -50%, 0);
|
|
300
|
-
}
|
|
301
|
-
.carousel-next{
|
|
302
|
-
right: 10px;
|
|
303
|
-
}
|
|
304
|
-
.carousel-prev{
|
|
305
|
-
left: 10px;
|
|
306
|
-
}
|
|
307
|
-
|
|
376
|
+
/* keep class for backwards compat but disable the old easing; spring animation is done in JS */
|
|
308
377
|
.transition-carousel{
|
|
309
|
-
transition:
|
|
378
|
+
transition: none;
|
|
310
379
|
}
|
|
311
380
|
</style>
|
|
312
381
|
|
|
@@ -198,6 +198,28 @@
|
|
|
198
198
|
</div>
|
|
199
199
|
</div>
|
|
200
200
|
|
|
201
|
+
<div>
|
|
202
|
+
<label :class="$style.label">Base Color</label>
|
|
203
|
+
<div class="mt-1 flex flex-row items-center gap-4">
|
|
204
|
+
<ColorPicker v-model="mediaOf(viewType, 'html, .html')['--base']" item-class="w-[48px] h-[48px]"
|
|
205
|
+
mode="hex" :custom-color="true" value-type="rgb"
|
|
206
|
+
@change="generateShade('--text', mediaOf(viewType, 'html, .html')['--text'])" />
|
|
207
|
+
|
|
208
|
+
<div class="grid grid-cols-5 gap-2 text-center">
|
|
209
|
+
<div>
|
|
210
|
+
<small class="text-xs text-text-400">400</small>
|
|
211
|
+
<ColorPicker v-model="mediaOf(viewType, 'html, .html')['--base-400']"
|
|
212
|
+
mode="hex" :custom-color="true" value-type="rgb" />
|
|
213
|
+
</div>
|
|
214
|
+
<div>
|
|
215
|
+
<small class="text-xs text-text-400">300</small>
|
|
216
|
+
<ColorPicker v-model="mediaOf(viewType, 'html, .html')['--base-300']"
|
|
217
|
+
mode="hex" :custom-color="true" value-type="rgb" />
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
|
|
201
223
|
</div>
|
|
202
224
|
|
|
203
225
|
<div class="p-6">
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
@click="$refs.ogModal.open({ ...this.page.og }, og => page.og = og)"
|
|
127
127
|
v-if="page.og && Object.keys(page.og).length > 0">
|
|
128
128
|
<div>
|
|
129
|
-
<Image :src="page.og.image" class="
|
|
129
|
+
<Image :src="page.og.image" class="wpack-[40px] aspect-square bg-text-50" />
|
|
130
130
|
</div>
|
|
131
131
|
<div class="flex-1 flex flex-col">
|
|
132
132
|
<label class="text-sm text-ellipsis-nowrap">
|
|
@@ -176,6 +176,8 @@
|
|
|
176
176
|
</Dropdown>
|
|
177
177
|
</div>
|
|
178
178
|
|
|
179
|
+
<slot name="info" :page="page"></slot>
|
|
180
|
+
|
|
179
181
|
</div>
|
|
180
182
|
|
|
181
183
|
<div v-else-if="store.tabIndex === 2" class="flex-1 overflow-y-auto p-6 flex flex-col gap-6">
|