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 export let initialPageIndex = 0
$: { $: {
data.initialPageIndexInit = initialPageIndex console.log('initialPageIndex', initialPageIndex)
data.initialPageIndex = initialPageIndex
} }
/** /**
@@ -217,7 +218,6 @@
// call after adding clones // call after adding clones
data.particlesCount = particlesContainer.children.length data.particlesCount = particlesContainer.children.length
data.initialPageIndex = initialPageIndex
pageWindowElementResizeObserver.observe(pageWindowElement); 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 { NEXT, PREV } from '../../direction'
import { import {
@@ -22,13 +22,13 @@ function createCarousel(onChange) {
const [data, methods, service] = simplyReactive( const [data, methods, service] = simplyReactive(
{ {
data: {
particlesCountWithoutClones: 0, particlesCountWithoutClones: 0,
particlesToShow: 1, // normalized particlesToShow: 1, // normalized
particlesToShowInit: 1, // initial value particlesToShowInit: 1, // initial value
particlesToScroll: 1, // normalized particlesToScroll: 1, // normalized
particlesToScrollInit: 1, // initial value particlesToScrollInit: 1, // initial value
initialPageIndex: 1, // normalized initialPageIndex: 0,
initialPageIndexInit: 1, // initial value
particlesCount: 1, particlesCount: 1,
currentParticleIndex: 1, currentParticleIndex: 1,
infinite: false, infinite: false,
@@ -50,84 +50,8 @@ function createCarousel(onChange) {
particleWidth: 0, particleWidth: 0,
loaded: [], loaded: [],
}, },
{ watch: {
setCurrentPageIndex: (data) => { setLoaded({ 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) {
data.loaded = getAdjacentIndexes({ data.loaded = getAdjacentIndexes({
infinite: data.infinite, infinite: data.infinite,
pageIndex: data.currentPageIndex, pageIndex: data.currentPageIndex,
@@ -137,9 +61,85 @@ function createCarousel(onChange) {
particlesToScroll: data.particlesToScroll, particlesToScroll: data.particlesToScroll,
}).particleIndexes }).particleIndexes
}, },
setCurrentPageIndex({ data }) {
data.currentPageIndex = getCurrentPageIndexByCurrentParticleIndex({
currentParticleIndex: data.currentParticleIndex,
particlesCount: data.particlesCount,
clonesCountHead: data.clonesCountHead,
clonesCountTotal: data.clonesCountTotal,
infinite: data.infinite,
particlesToScroll: data.particlesToScroll,
})
}, },
{ setPartialPageSize({ data }) {
_prev: (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({ const newCurrentParticleIndex = getParticleIndexByPageIndex({
infinite: data.infinite, infinite: data.infinite,
pageIndex: data.currentPageIndex - 1, pageIndex: data.currentPageIndex - 1,
@@ -151,7 +151,7 @@ function createCarousel(onChange) {
}) })
data.currentParticleIndex = newCurrentParticleIndex data.currentParticleIndex = newCurrentParticleIndex
}, },
_next: (data) => { _next({ data }) {
const newCurrentParticleIndex = getParticleIndexByPageIndex({ const newCurrentParticleIndex = getParticleIndexByPageIndex({
infinite: data.infinite, infinite: data.infinite,
pageIndex: data.currentPageIndex + 1, pageIndex: data.currentPageIndex + 1,
@@ -163,7 +163,7 @@ function createCarousel(onChange) {
}) })
data.currentParticleIndex = newCurrentParticleIndex data.currentParticleIndex = newCurrentParticleIndex
}, },
_moveToParticle: (data, _, particleIndex) => { _moveToParticle({ data }, particleIndex) {
const newCurrentParticleIndex = getValueInRange( const newCurrentParticleIndex = getValueInRange(
0, 0,
particleIndex, particleIndex,
@@ -171,64 +171,49 @@ function createCarousel(onChange) {
) )
data.currentParticleIndex = newCurrentParticleIndex data.currentParticleIndex = newCurrentParticleIndex
}, },
toggleFocused: (data) => { toggleFocused({ data }) {
data.focused = !data.focused data.focused = !data.focused
}, },
async _applyAutoplayIfNeeded( async _applyAutoplayIfNeeded({ data, methods }) {
{
infinite,
autoplayDirection,
currentParticleIndex,
particlesCount,
autoplay,
},
{ showNextPage, showPrevPage }
) {
// prevent progress change if not infinite for first and last page // prevent progress change if not infinite for first and last page
if ( if (
!infinite && !data.infinite &&
((autoplayDirection === NEXT && ((data.autoplayDirection === NEXT &&
currentParticleIndex === particlesCount - 1) || data.currentParticleIndex === data.particlesCount - 1) ||
(autoplayDirection === PREV && currentParticleIndex === 0)) (data.autoplayDirection === PREV &&
data.currentParticleIndex === 0))
) { ) {
progressManager.reset() progressManager.reset()
return return
} }
if (autoplay) { if (data.autoplay) {
const onFinish = () => const onFinish = () =>
switcher({ switcher({
[NEXT]: async () => showNextPage(), [NEXT]: async () => methods.showNextPage(),
[PREV]: async () => showPrevPage(), [PREV]: async () => methods.showPrevPage(),
})(autoplayDirection) })(data.autoplayDirection)
await progressManager.start(onFinish) await progressManager.start(onFinish)
} }
}, },
// makes delayed jump to 1st or last element // makes delayed jump to 1st or last element
_jumpIfNeeded: async ( async _jumpIfNeeded({ data, methods }) {
{
infinite,
currentParticleIndex,
particlesCount,
clonesCountTotal,
clonesCountTail,
clonesCountHead,
},
{ showParticle }
) => {
let jumped = false let jumped = false
if (infinite) { if (data.infinite) {
if (currentParticleIndex === 0) { if (data.currentParticleIndex === 0) {
await showParticle(particlesCount - clonesCountTotal, { await methods.showParticle(
data.particlesCount - data.clonesCountTotal,
{
animated: false, animated: false,
}) }
)
jumped = true jumped = true
} else if ( } else if (
currentParticleIndex === data.currentParticleIndex ===
particlesCount - clonesCountTail data.particlesCount - data.clonesCountTail
) { ) {
await showParticle(clonesCountHead, { await methods.showParticle(data.clonesCountHead, {
animated: false, animated: false,
}) })
jumped = true jumped = true
@@ -236,43 +221,34 @@ function createCarousel(onChange) {
} }
return jumped return jumped
}, },
async changePage({ data, methods }, updateStoreFn, options) {
changePage: async (
data,
{ offsetPage, _applyAutoplayIfNeeded, _jumpIfNeeded },
updateStoreFn,
options
) => {
progressManager.reset() progressManager.reset()
if (data.disabled) return if (data.disabled) return
data.disabled = true data.disabled = true
updateStoreFn() updateStoreFn()
await offsetPage({ animated: get(options, 'animated', true) }) await methods.offsetPage({ animated: get(options, 'animated', true) })
data.disabled = false data.disabled = false
const jumped = await _jumpIfNeeded() const jumped = await methods._jumpIfNeeded()
!jumped && _applyAutoplayIfNeeded() // no need to wait it finishes !jumped && methods._applyAutoplayIfNeeded() // no need to wait it finishes
}, },
showNextPage: async ({ disabled }, { changePage, _next }, options) => { async showNextPage({ data, methods }, options) {
if (disabled) return if (data.disabled) return
await changePage(_next, options) await methods.changePage(methods._next, options)
}, },
showPrevPage: async ({ disabled }, { changePage, _prev }, options) => { async showPrevPage({ data, methods }, options) {
if (disabled) return if (data.disabled) return
await changePage(_prev, options) await methods.changePage(methods._prev, options)
}, },
showParticle: async ( async showParticle({ methods }, particleIndex, options) {
_, await methods.changePage(
{ changePage, _moveToParticle }, () => methods._moveToParticle(particleIndex),
particleIndex,
options options
) => { )
await changePage(() => _moveToParticle(particleIndex), options)
}, },
showPage: async (data, { showParticle }, pageIndex, options) => { async showPage({ data, methods }, pageIndex, options) {
await showParticle( const ind = getParticleIndexByPageIndex({
getParticleIndexByPageIndex({
infinite: data.infinite, infinite: data.infinite,
pageIndex, pageIndex,
clonesCountHead: data.clonesCountHead, clonesCountHead: data.clonesCountHead,
@@ -280,11 +256,11 @@ function createCarousel(onChange) {
particlesToScroll: data.particlesToScroll, particlesToScroll: data.particlesToScroll,
particlesCount: data.particlesCount, particlesCount: data.particlesCount,
particlesToShow: data.particlesToShow, 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) const animated = get(options, 'animated', true)
return new Promise((resolve) => { return new Promise((resolve) => {
// durationMs is an offset animation time // durationMs is an offset animation time
@@ -296,7 +272,10 @@ function createCarousel(onChange) {
}) })
}, },
}, },
onChange },
{
onChange,
}
) )
return [{ data, progressManager }, methods, service] 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]
}