Fix adding extra deps

This commit is contained in:
Vadim
2021-10-09 10:30:27 +03:00
parent 87a60678ba
commit de213cba88
3 changed files with 239 additions and 371 deletions

View File

@@ -79,7 +79,8 @@
*/
export let initialPageIndex = 0
$: {
data.initialPageIndexInit = initialPageIndex
console.log('initialPageIndex', initialPageIndex)
data.initialPageIndex = initialPageIndex
}
/**
@@ -217,7 +218,6 @@
// call after adding clones
data.particlesCount = particlesContainer.children.length
data.initialPageIndex = initialPageIndex
pageWindowElementResizeObserver.observe(pageWindowElement);
}

View File

@@ -1,4 +1,4 @@
import simplyReactive from 'simply-reactive'
import simplyReactive from '../../../../simply-reactive/main'
import { NEXT, PREV } from '../../direction'
import {
@@ -22,13 +22,13 @@ function createCarousel(onChange) {
const [data, methods, service] = simplyReactive(
{
data: {
particlesCountWithoutClones: 0,
particlesToShow: 1, // normalized
particlesToShowInit: 1, // initial value
particlesToScroll: 1, // normalized
particlesToScrollInit: 1, // initial value
initialPageIndex: 1, // normalized
initialPageIndexInit: 1, // initial value
initialPageIndex: 0,
particlesCount: 1,
currentParticleIndex: 1,
infinite: false,
@@ -50,84 +50,8 @@ function createCarousel(onChange) {
particleWidth: 0,
loaded: [],
},
{
setCurrentPageIndex: (data) => {
data.currentPageIndex = getCurrentPageIndexByCurrentParticleIndex({
currentParticleIndex: data.currentParticleIndex,
particlesCount: data.particlesCount,
clonesCountHead: data.clonesCountHead,
clonesCountTotal: data.clonesCountTotal,
infinite: data.initialPageIndex,
particlesToScroll: data.particlesToScroll,
})
},
setPartialPageSize: (data) => {
data.partialPageSize = getPartialPageSize({
particlesToScroll: data.particlesToScroll,
particlesToShow: data.particlesToShow,
particlesCountWithoutClones: data.particlesCountWithoutClones,
})
},
setClonesCount: (data) => {
const { head, tail } = getClonesCount({
infinite: data.infinite,
particlesToShow: data.particlesToShow,
partialPageSize: data.partialPageSize,
})
data.clonesCountHead = head
data.clonesCountTail = tail
data.clonesCountTotal = head + tail
},
setPagesCount: (data) => {
data.pagesCount = getPagesCountByParticlesCount({
infinite: data.infinite,
particlesCountWithoutClones: data.particlesCountWithoutClones,
particlesToScroll: data.particlesToScroll,
})
},
setProgressManagerAutoplayDuration: (data) => {
progressManager.setAutoplayDuration(data.autoplayDuration)
},
toggleProgressManager: ({ pauseOnFocus, focused }) => {
if (pauseOnFocus) {
if (focused) {
progressManager.pause()
} else {
progressManager.resume()
}
}
},
initDuration: (data) => {
data.durationMs = data.durationMsInit
},
applyAutoplay: (data, { _applyAutoplayIfNeeded }) => {
// prevent _applyAutoplayIfNeeded to be called with watcher
// to prevent its data added to deps
data.autoplay && _applyAutoplayIfNeeded(data.autoplay)
},
setParticlesToShow(data) {
data.particlesToShow = getValueInRange(
1,
data.particlesToShowInit,
data.particlesCountWithoutClones
)
},
setParticlesToScroll(data) {
data.particlesToScroll = getValueInRange(
1,
data.particlesToScrollInit,
data.particlesCountWithoutClones
)
},
setInitialPageIndex(data) {
data.initialPageIndex = getValueInRange(
1,
data.initialPageIndexInit,
data.pagesCount
)
},
setLoaded(data) {
watch: {
setLoaded({ data }) {
data.loaded = getAdjacentIndexes({
infinite: data.infinite,
pageIndex: data.currentPageIndex,
@@ -137,9 +61,85 @@ function createCarousel(onChange) {
particlesToScroll: data.particlesToScroll,
}).particleIndexes
},
setCurrentPageIndex({ data }) {
data.currentPageIndex = getCurrentPageIndexByCurrentParticleIndex({
currentParticleIndex: data.currentParticleIndex,
particlesCount: data.particlesCount,
clonesCountHead: data.clonesCountHead,
clonesCountTotal: data.clonesCountTotal,
infinite: data.infinite,
particlesToScroll: data.particlesToScroll,
})
},
{
_prev: (data) => {
setPartialPageSize({ data }) {
data.partialPageSize = getPartialPageSize({
particlesToScroll: data.particlesToScroll,
particlesToShow: data.particlesToShow,
particlesCountWithoutClones: data.particlesCountWithoutClones,
})
},
setClonesCount({ data }) {
const { head, tail } = getClonesCount({
infinite: data.infinite,
particlesToShow: data.particlesToShow,
partialPageSize: data.partialPageSize,
})
data.clonesCountHead = head
data.clonesCountTail = tail
data.clonesCountTotal = head + tail
},
setProgressManagerAutoplayDuration({ data }) {
progressManager.setAutoplayDuration(data.autoplayDuration)
},
toggleProgressManager({ data: { pauseOnFocus, focused } }) {
// as focused is in if block, it will not be put to deps, read them in data: {}
if (pauseOnFocus) {
if (focused) {
progressManager.pause()
} else {
progressManager.resume()
}
}
},
initDuration({ data }) {
data.durationMs = data.durationMsInit
},
applyAutoplay({ data, methods: { _applyAutoplayIfNeeded } }) {
// prevent _applyAutoplayIfNeeded to be called with watcher
// to prevent its data added to deps
data.autoplay && _applyAutoplayIfNeeded(data.autoplay)
},
setParticlesToShow({ data }) {
data.particlesToShow = getValueInRange(
1,
data.particlesToShowInit,
data.particlesCountWithoutClones
)
},
setPagesCount({ data }) {
data.pagesCount = getPagesCountByParticlesCount({
infinite: data.infinite,
particlesCountWithoutClones: data.particlesCountWithoutClones,
particlesToScroll: data.particlesToScroll,
})
},
setParticlesToScroll({ data }) {
data.particlesToScroll = getValueInRange(
1,
data.particlesToScrollInit,
data.particlesCountWithoutClones
)
},
setInitialPageIndex({ data, methods: { showPage } }) {
const ind = getValueInRange(0, data.initialPageIndex, data.pagesCount)
console.log('ind', data.initialPageIndex, ind)
showPage(5, {
animated: false,
})
},
},
methods: {
_prev({ data }) {
const newCurrentParticleIndex = getParticleIndexByPageIndex({
infinite: data.infinite,
pageIndex: data.currentPageIndex - 1,
@@ -151,7 +151,7 @@ function createCarousel(onChange) {
})
data.currentParticleIndex = newCurrentParticleIndex
},
_next: (data) => {
_next({ data }) {
const newCurrentParticleIndex = getParticleIndexByPageIndex({
infinite: data.infinite,
pageIndex: data.currentPageIndex + 1,
@@ -163,7 +163,7 @@ function createCarousel(onChange) {
})
data.currentParticleIndex = newCurrentParticleIndex
},
_moveToParticle: (data, _, particleIndex) => {
_moveToParticle({ data }, particleIndex) {
const newCurrentParticleIndex = getValueInRange(
0,
particleIndex,
@@ -171,64 +171,49 @@ function createCarousel(onChange) {
)
data.currentParticleIndex = newCurrentParticleIndex
},
toggleFocused: (data) => {
toggleFocused({ data }) {
data.focused = !data.focused
},
async _applyAutoplayIfNeeded(
{
infinite,
autoplayDirection,
currentParticleIndex,
particlesCount,
autoplay,
},
{ showNextPage, showPrevPage }
) {
async _applyAutoplayIfNeeded({ data, methods }) {
// prevent progress change if not infinite for first and last page
if (
!infinite &&
((autoplayDirection === NEXT &&
currentParticleIndex === particlesCount - 1) ||
(autoplayDirection === PREV && currentParticleIndex === 0))
!data.infinite &&
((data.autoplayDirection === NEXT &&
data.currentParticleIndex === data.particlesCount - 1) ||
(data.autoplayDirection === PREV &&
data.currentParticleIndex === 0))
) {
progressManager.reset()
return
}
if (autoplay) {
if (data.autoplay) {
const onFinish = () =>
switcher({
[NEXT]: async () => showNextPage(),
[PREV]: async () => showPrevPage(),
})(autoplayDirection)
[NEXT]: async () => methods.showNextPage(),
[PREV]: async () => methods.showPrevPage(),
})(data.autoplayDirection)
await progressManager.start(onFinish)
}
},
// makes delayed jump to 1st or last element
_jumpIfNeeded: async (
{
infinite,
currentParticleIndex,
particlesCount,
clonesCountTotal,
clonesCountTail,
clonesCountHead,
},
{ showParticle }
) => {
async _jumpIfNeeded({ data, methods }) {
let jumped = false
if (infinite) {
if (currentParticleIndex === 0) {
await showParticle(particlesCount - clonesCountTotal, {
if (data.infinite) {
if (data.currentParticleIndex === 0) {
await methods.showParticle(
data.particlesCount - data.clonesCountTotal,
{
animated: false,
})
}
)
jumped = true
} else if (
currentParticleIndex ===
particlesCount - clonesCountTail
data.currentParticleIndex ===
data.particlesCount - data.clonesCountTail
) {
await showParticle(clonesCountHead, {
await methods.showParticle(data.clonesCountHead, {
animated: false,
})
jumped = true
@@ -236,43 +221,34 @@ function createCarousel(onChange) {
}
return jumped
},
changePage: async (
data,
{ offsetPage, _applyAutoplayIfNeeded, _jumpIfNeeded },
updateStoreFn,
options
) => {
async changePage({ data, methods }, updateStoreFn, options) {
progressManager.reset()
if (data.disabled) return
data.disabled = true
updateStoreFn()
await offsetPage({ animated: get(options, 'animated', true) })
await methods.offsetPage({ animated: get(options, 'animated', true) })
data.disabled = false
const jumped = await _jumpIfNeeded()
!jumped && _applyAutoplayIfNeeded() // no need to wait it finishes
const jumped = await methods._jumpIfNeeded()
!jumped && methods._applyAutoplayIfNeeded() // no need to wait it finishes
},
showNextPage: async ({ disabled }, { changePage, _next }, options) => {
if (disabled) return
await changePage(_next, options)
async showNextPage({ data, methods }, options) {
if (data.disabled) return
await methods.changePage(methods._next, options)
},
showPrevPage: async ({ disabled }, { changePage, _prev }, options) => {
if (disabled) return
await changePage(_prev, options)
async showPrevPage({ data, methods }, options) {
if (data.disabled) return
await methods.changePage(methods._prev, options)
},
showParticle: async (
_,
{ changePage, _moveToParticle },
particleIndex,
async showParticle({ methods }, particleIndex, options) {
await methods.changePage(
() => methods._moveToParticle(particleIndex),
options
) => {
await changePage(() => _moveToParticle(particleIndex), options)
)
},
showPage: async (data, { showParticle }, pageIndex, options) => {
await showParticle(
getParticleIndexByPageIndex({
async showPage({ data, methods }, pageIndex, options) {
const ind = getParticleIndexByPageIndex({
infinite: data.infinite,
pageIndex,
clonesCountHead: data.clonesCountHead,
@@ -280,11 +256,11 @@ function createCarousel(onChange) {
particlesToScroll: data.particlesToScroll,
particlesCount: data.particlesCount,
particlesToShow: data.particlesToShow,
}),
options
)
})
console.log('ParticleIndex', ind)
await methods.showParticle(ind, options)
},
offsetPage(data, _, options) {
offsetPage({ data }, options) {
const animated = get(options, 'animated', true)
return new Promise((resolve) => {
// durationMs is an offset animation time
@@ -296,7 +272,10 @@ function createCarousel(onChange) {
})
},
},
onChange
},
{
onChange,
}
)
return [{ data, progressManager }, methods, service]

View File

@@ -1,111 +0,0 @@
// Code that has to run when a
// reactive property changes it's value.
const objectsAreSame = (x, y) => {
// return false
let _objectsAreSame = true
for (let propertyName in x) {
if (Number.isNaN(x[propertyName]) || Number.isNaN(y[propertyName])) {
continue
}
if (x[propertyName] !== y[propertyName]) {
_objectsAreSame = false
break
}
}
return _objectsAreSame
}
const getObject = (oldData, newData) => {
const newDeps = {}
Object.entries(oldData).forEach(([key, value]) => {
// console.log('oldData', key, value)
newDeps[key] = newData[key]
})
// console.log('isDiff', oldData, newDeps)
return newDeps
}
const useSubscription = () => {
const subscribers = {}
const memoDependency = (target, dep) => {
const { watcherName, fn } = target
const { key, value } = dep
if (!subscribers[watcherName]) {
subscribers[watcherName] = {
deps: {},
fn,
}
}
subscribers[watcherName].deps[key] = value
}
return {
subscribe: (target, dep) => {
if (target) {
memoDependency(target, dep)
}
},
notify: (data) => {
Object.entries(subscribers).forEach(([watcherName, { deps }]) => {
const newDeps = getObject(deps, data)
if (!objectsAreSame(deps, newDeps)) {
subscribers[watcherName].deps = newDeps
subscribers[watcherName].fn()
}
})
},
}
}
const useWatcher = () => {
let target = null
return {
watch: (watcherName, fn) => {
target = {
watcherName,
fn,
}
target.fn()
target = null
},
getTarget: () => {
return target
},
}
}
export const reactive = (data, watchers, methods, onChange) => {
const { subscribe, notify } = useSubscription()
const { watch, getTarget } = useWatcher()
const _data = new Proxy(data, {
get(target, key) {
subscribe(getTarget(), { key, value: target[key] })
return Reflect.get(...arguments)
},
set(_, key, value) {
Reflect.set(...arguments)
onChange && onChange(key, value)
notify(_data)
return true
},
})
Object.entries(watchers).forEach(([watcherName, watcher]) => {
watch(watcherName, () => watcher(_data))
})
const _methods = {}
Object.entries(methods).forEach(([methodName, method]) => {
_methods[methodName] = (...args) => method(_data, _methods, ...args)
})
return [_data, _methods]
}