diff --git a/packages/vue-final-modal/package.json b/packages/vue-final-modal/package.json index b2ab32fd..ea09e76e 100644 --- a/packages/vue-final-modal/package.json +++ b/packages/vue-final-modal/package.json @@ -35,19 +35,22 @@ "devDependencies": { "@cypress/vue": "^5.0.5", "@release-it/conventional-changelog": "^5.1.1", + "@types/scroll-lock": "^2.1.3", "@vueuse/core": "^10.7.1", "@vueuse/integrations": "^10.7.1", "cypress": "^13.6.0", "focus-trap": "^7.5.4", "release-it": "^16.1.3", + "scroll-lock": "^2.1.5", "vite-plugin-dts": "^3.6.3", "vue": "^3.4.7" }, "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", "@vueuse/core": ">=10.0.0", "@vueuse/integrations": ">=10.0.0", "focus-trap": ">=7.2.0", - "@vue/composition-api": "^1.0.0-rc.1", + "scroll-lock": ">=2.1.5", "vue": ">=2.7.0 || >=3.0.0" }, "homepage": "https://vue-final-modal.org/", diff --git a/packages/vue-final-modal/src/components/VueFinalModal/VueFinalModal.vue b/packages/vue-final-modal/src/components/VueFinalModal/VueFinalModal.vue index cc6d7ae5..7dc405f2 100644 --- a/packages/vue-final-modal/src/components/VueFinalModal/VueFinalModal.vue +++ b/packages/vue-final-modal/src/components/VueFinalModal/VueFinalModal.vue @@ -5,7 +5,7 @@ import { useTransition } from './useTransition' import { useToClose } from './useToClose' import { useModelValue } from './useModelValue' import { useFocusTrap } from './useFocusTrap' -import { useLockScroll } from './useBodyScrollLock' +import { useScrollLock } from './useScrollLock' import { useZIndex } from './useZIndex' import { vVisible } from './vVisible' import { arrayMoveItemToLast, arrayRemoveItem, noop, once } from '~/utils' @@ -50,7 +50,7 @@ const vfmContentEl = ref() const { focus, blur } = useFocusTrap(props, { focusEl: vfmRootEl }) const { zIndex, refreshZIndex, resetZIndex } = useZIndex(props) const { modelValueLocal } = useModelValue(props, emit, { open, close }) -const { enableBodyScroll, disableBodyScroll } = useLockScroll(props, { +const { disablePageScroll, enablePageScroll } = useScrollLock(props, { lockScrollEl: vfmRootEl, modelValueLocal, }) @@ -74,7 +74,7 @@ const { modelValueLocal, onEntering() { nextTick(() => { - disableBodyScroll() + disablePageScroll() focus() }) }, @@ -87,7 +87,7 @@ const { onLeave() { arrayRemoveItem(openedModals, instance) resetZIndex() - enableBodyScroll() + enablePageScroll() emit('closed') // eslint-disable-next-line vue/custom-event-name-casing emit('_closed') @@ -143,7 +143,7 @@ function close(): boolean { } onBeforeUnmount(() => { - enableBodyScroll() + enablePageScroll() arrayRemoveItem(modals, instance) arrayRemoveItem(openedModals, instance) blur() @@ -208,6 +208,7 @@ export default { :style="{ zIndex }" role="dialog" aria-modal="true" + data-scroll-lock-scrollable @keydown.esc="() => onEsc()" @mouseup.self="() => onMouseupRoot()" @mousedown.self="e => onMousedown(e)" diff --git a/packages/vue-final-modal/src/components/VueFinalModal/useBodyScrollLock.ts b/packages/vue-final-modal/src/components/VueFinalModal/useBodyScrollLock.ts deleted file mode 100644 index 4c40cacc..00000000 --- a/packages/vue-final-modal/src/components/VueFinalModal/useBodyScrollLock.ts +++ /dev/null @@ -1,282 +0,0 @@ -import type { Ref } from 'vue-demi' -import { onBeforeUnmount, watch } from 'vue-demi' -import type VueFinalModal from './VueFinalModal.vue' - -type BodyScrollOptions = { - reserveScrollBarGap?: boolean - allowTouchMove?: (el?: null | HTMLElement) => boolean -} - -type Lock = { - targetElement: HTMLElement - options?: BodyScrollOptions -} - -// stolen from body-scroll-lock - -// Older browsers don't support event options, feature detect it. -let hasPassiveEvents = false -if (typeof window !== 'undefined') { - const passiveTestOptions = { - get passive() { - hasPassiveEvents = true - return undefined - }, - } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - window.addEventListener('testPassive', null, passiveTestOptions) - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - window.removeEventListener('testPassive', null, passiveTestOptions) -} - -const isIosDevice - = typeof window !== 'undefined' - && window.navigator - && window.navigator.platform - && (/iP(ad|hone|od)/.test(window.navigator.platform) - || (window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1)) - -let locks: Lock[] = [] -let documentListenerAdded = false -let clientY = 0 -let initialClientY = -1 -let previousBodyOverflowSetting: undefined | string -let previousBodyPaddingRight: undefined | string - -const hasScrollbar = (el: HTMLElement) => { - if (!el || el.nodeType !== Node.ELEMENT_NODE) - return false - - const style = window.getComputedStyle(el) - return ['auto', 'scroll'].includes(style.overflowY) && el.scrollHeight > el.clientHeight -} - -const shouldScroll = (el: HTMLElement, delta: number) => { - if (el.scrollTop === 0 && delta < 0) - return false - if (el.scrollTop + el.clientHeight + delta >= el.scrollHeight && delta > 0) - return false - return true -} - -const composedPath = (el: null | HTMLElement) => { - const path = [] - while (el) { - path.push(el) - if (el.classList.contains('vfm')) - return path - el = el.parentElement - } - return path -} - -const hasAnyScrollableEl = (el: HTMLElement | null, delta: number) => { - let hasAnyScrollableEl = false - const path = composedPath(el) - path.forEach((el) => { - if (hasScrollbar(el) && shouldScroll(el, delta)) - hasAnyScrollableEl = true - }) - return hasAnyScrollableEl -} - -// returns true if `el` should be allowed to receive touchmove events. -const allowTouchMove = (el: HTMLElement | null) => locks.some(() => hasAnyScrollableEl(el, -clientY)) - -const preventDefault = (rawEvent: TouchEvent) => { - const e = rawEvent || window.event - - // For the case whereby consumers adds a touchmove event listener to document. - // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false }) - // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then - // the touchmove event on document will break. - if (allowTouchMove(e.target as HTMLElement | null)) - return true - - // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom). - if (e.touches.length > 1) - return true - - if (e.preventDefault) - e.preventDefault() - - return false -} - -const setOverflowHidden = (options?: BodyScrollOptions) => { - // If previousBodyPaddingRight is already set, don't set it again. - if (previousBodyPaddingRight === undefined) { - const reserveScrollBarGap = !!options && options.reserveScrollBarGap === true - const scrollBarGap = window.innerWidth - document.documentElement.clientWidth - - if (reserveScrollBarGap && scrollBarGap > 0) { - const computedBodyPaddingRight = parseInt(getComputedStyle(document.body).getPropertyValue('padding-right'), 10) - previousBodyPaddingRight = document.body.style.paddingRight - document.body.style.paddingRight = `${computedBodyPaddingRight + scrollBarGap}px` - } - } - // If previousBodyOverflowSetting is already set, don't set it again. - if (previousBodyOverflowSetting === undefined) { - previousBodyOverflowSetting = document.body.style.overflow - document.body.style.overflow = 'hidden' - } -} - -const restoreOverflowSetting = () => { - if (previousBodyPaddingRight !== undefined) { - document.body.style.paddingRight = previousBodyPaddingRight - - // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it - // can be set again. - previousBodyPaddingRight = undefined - } - - if (previousBodyOverflowSetting !== undefined) { - document.body.style.overflow = previousBodyOverflowSetting - - // Restore previousBodyOverflowSetting to undefined - // so setOverflowHidden knows it can be set again. - previousBodyOverflowSetting = undefined - } -} -// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions -const isTargetElementTotallyScrolled = (targetElement: HTMLElement) => - targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false - -const handleScroll = (event: TouchEvent, targetElement: HTMLElement) => { - clientY = event.targetTouches[0].clientY - initialClientY - - if (allowTouchMove(event.target as HTMLElement | null)) - return false - - if (targetElement && targetElement.scrollTop === 0 && clientY > 0) { - // element is at the top of its scroll. - return preventDefault(event) - } - - if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) { - // element is at the bottom of its scroll. - return preventDefault(event) - } - - event.stopPropagation() - return true -} - -export const disableBodyScroll = (targetElement?: HTMLElement, options?: BodyScrollOptions) => { - // targetElement must be provided - if (!targetElement) { - console.error( - 'disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.', - ) - return - } - - // disableBodyScroll must not have been called on this targetElement before - if (locks.some(lock => lock.targetElement === targetElement)) - return - - const lock = { - targetElement, - options: options || {}, - } - - locks = [...locks, lock] - - if (isIosDevice) { - targetElement.ontouchstart = (event: TouchEvent) => { - if (event.targetTouches.length === 1) { - // detect single touch. - initialClientY = event.targetTouches[0].clientY - } - } - targetElement.ontouchmove = (event: TouchEvent) => { - if (event.targetTouches.length === 1) { - // detect single touch. - handleScroll(event, targetElement) - } - } - - if (!documentListenerAdded) { - document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined) - documentListenerAdded = true - } - } - else { - setOverflowHidden(options) - } -} - -export const enableBodyScroll = (targetElement?: HTMLElement) => { - if (!targetElement) { - console.error( - 'enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.', - ) - return - } - - locks = locks.filter(lock => lock.targetElement !== targetElement) - - if (isIosDevice) { - targetElement.ontouchstart = null - targetElement.ontouchmove = null - - if (documentListenerAdded && locks.length === 0) { - document.removeEventListener('touchmove', preventDefault, (hasPassiveEvents ? { passive: false } : undefined) as any) - documentListenerAdded = false - } - } - else if (!locks.length) { - restoreOverflowSetting() - } -} - -export function useLockScroll(props: InstanceType['$props'], options: { - lockScrollEl: Ref - modelValueLocal: Ref -}) { - const { lockScrollEl, modelValueLocal } = options - - let _lockScrollEl: HTMLElement - watch(lockScrollEl, (val) => { - if (val) - _lockScrollEl = val - }, { immediate: true }) - - watch(() => props.lockScroll, (val) => { - val ? _disableBodyScroll() : _enableBodyScroll() - }) - - onBeforeUnmount(() => { - _enableBodyScroll() - }) - - function _enableBodyScroll() { - _lockScrollEl && enableBodyScroll(_lockScrollEl) - } - - function _disableBodyScroll() { - if (!modelValueLocal.value) - return - props.lockScroll && _lockScrollEl - && disableBodyScroll(_lockScrollEl, { - reserveScrollBarGap: props.reserveScrollBarGap, - allowTouchMove: (el) => { - while (el && el !== document.body) { - if (el.getAttribute('vfm-scroll-lock-ignore') !== null) - return true - - el = el.parentElement - } - return false - }, - }) - } - - return { - enableBodyScroll: _enableBodyScroll, - disableBodyScroll: _disableBodyScroll, - } -} diff --git a/packages/vue-final-modal/src/components/VueFinalModal/useScrollLock.ts b/packages/vue-final-modal/src/components/VueFinalModal/useScrollLock.ts new file mode 100644 index 00000000..9dd63409 --- /dev/null +++ b/packages/vue-final-modal/src/components/VueFinalModal/useScrollLock.ts @@ -0,0 +1,51 @@ +import { disablePageScroll, enablePageScroll, setFillGapMethod } from 'scroll-lock' +import type { Ref } from 'vue-demi' +import { onBeforeUnmount, watch } from 'vue-demi' +import type VueFinalModal from './VueFinalModal.vue' +import { noop, once } from '~/utils' + +export function useScrollLock(props: InstanceType['$props'], options: { + lockScrollEl: Ref + modelValueLocal: Ref +}) { + const { lockScrollEl, modelValueLocal } = options + + let _lockScrollEl: HTMLElement + watch(lockScrollEl, (val) => { + if (val) + _lockScrollEl = val + }, { immediate: true }) + + watch(() => props.lockScroll, (val) => { + val ? _disablePageScroll() : _enablePageScroll() + }) + + watch(() => props.reserveScrollBarGap, (val) => { + setFillGapMethod(val ? 'padding' : 'none') + }, { immediate: true }) + + onBeforeUnmount(() => { + _enablePageScroll() + }) + + let enablePageScrollOnce = noop + function _enablePageScroll() { + enablePageScrollOnce() + } + + function _disablePageScroll() { + if (!modelValueLocal.value) + return + if (props.lockScroll && _lockScrollEl) { + disablePageScroll(_lockScrollEl) + enablePageScrollOnce = once(() => { + _lockScrollEl && enablePageScroll(_lockScrollEl) + }) + } + } + + return { + enablePageScroll: _enablePageScroll, + disablePageScroll: _disablePageScroll, + } +} diff --git a/packages/vue-final-modal/vite.config.ts b/packages/vue-final-modal/vite.config.ts index 59203848..0196292f 100644 --- a/packages/vue-final-modal/vite.config.ts +++ b/packages/vue-final-modal/vite.config.ts @@ -30,6 +30,7 @@ export default defineConfig({ '@vueuse/core', '@vueuse/integrations/useFocusTrap', 'focus-trap', + 'scroll-lock', ], output: { globals: { @@ -37,6 +38,7 @@ export default defineConfig({ '@vueuse/core': 'VueUse', '@vueuse/integrations/useFocusTrap': 'VueUseFocusTrap', 'focus-trap': 'FocusTrap', + 'scroll-lock': 'ScrollLock', }, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75409667..96d9362a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -95,7 +95,7 @@ importers: version: 1.7.2(vue@3.4.7) vue-demi: specifier: ^0.14.6 - version: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + version: 0.14.6(vue@3.4.7) devDependencies: '@cypress/vue': specifier: ^5.0.5 @@ -103,12 +103,15 @@ importers: '@release-it/conventional-changelog': specifier: ^5.1.1 version: 5.1.1(release-it@16.2.1) + '@types/scroll-lock': + specifier: ^2.1.3 + version: 2.1.3 '@vueuse/core': specifier: ^10.7.1 - version: 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) + version: 10.7.1(vue@3.4.7) '@vueuse/integrations': specifier: ^10.7.1 - version: 10.7.1(@vue/composition-api@1.7.2)(focus-trap@7.5.4)(vue@3.4.7) + version: 10.7.1(focus-trap@7.5.4)(fuse.js@6.6.2)(vue@3.4.7) cypress: specifier: ^13.6.0 version: 13.6.0 @@ -118,6 +121,9 @@ importers: release-it: specifier: ^16.1.3 version: 16.2.1(typescript@5.3.3) + scroll-lock: + specifier: ^2.1.5 + version: 2.1.5 vite-plugin-dts: specifier: ^3.6.3 version: 3.6.3(@types/node@20.10.4)(typescript@5.3.3)(vite@5.0.6) @@ -2145,7 +2151,7 @@ packages: dependencies: '@nuxt/kit': 3.8.2(rollup@3.29.4) '@nuxtjs/mdc': 0.2.8(rollup@3.29.4) - '@vueuse/core': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) + '@vueuse/core': 10.7.1(vue@3.4.7) '@vueuse/head': 2.0.0(vue@3.4.7) '@vueuse/nuxt': 10.6.1(nuxt@3.8.2)(rollup@3.29.4)(vue@3.4.7) consola: 3.2.3 @@ -2547,7 +2553,7 @@ packages: '@typescript-eslint/parser': 6.13.1(eslint@8.56.0)(typescript@5.3.3) eslint: 8.56.0 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.13.1)(eslint-plugin-import@2.29.0)(eslint@8.56.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.13.1)(eslint@8.56.0) eslint-plugin-vue: 9.18.1(eslint@8.56.0) transitivePeerDependencies: - eslint-import-resolver-node @@ -3568,6 +3574,10 @@ packages: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true + /@types/scroll-lock@2.1.3: + resolution: {integrity: sha512-9Z9MIt9qF5DFEKlLI5MlNnk3SjjHEo0wjhzMEmZaJxCad981cs9Zerd8J1G2ELJVjXto1q/Cd+fNwmuscFHnpA==} + dev: true + /@types/semver@7.5.6: resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} dev: true @@ -4005,7 +4015,7 @@ packages: '@lezer/html': 1.3.7 '@pepicons/vue': 3.1.1(vue@3.4.7) '@viteplay/types': 0.2.9 - '@vueuse/core': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) + '@vueuse/core': 10.7.1(vue@3.4.7) codemirror: 6.0.1(@lezer/common@1.2.0) floating-vue: 2.0.0-beta.20(vue@3.4.7) fuzzysort: 2.0.4 @@ -4200,6 +4210,7 @@ packages: vue: '>= 2.5 < 2.7' dependencies: vue: 3.4.7(typescript@5.3.3) + dev: false /@vue/devtools-api@6.5.0: resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} @@ -4298,19 +4309,19 @@ packages: '@types/web-bluetooth': 0.0.20 '@vueuse/metadata': 10.6.1 '@vueuse/shared': 10.6.1(vue@3.4.7) - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue dev: true - /@vueuse/core@10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7): + /@vueuse/core@10.7.1(vue@3.4.7): resolution: {integrity: sha512-74mWHlaesJSWGp1ihg76vAnfVq9NTv1YT0SYhAQ6zwFNdBkkP+CKKJmVOEHcdSnLXCXYiL5e7MaewblfiYLP7g==} dependencies: '@types/web-bluetooth': 0.0.20 '@vueuse/metadata': 10.7.1 - '@vueuse/shared': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + '@vueuse/shared': 10.7.1(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -4322,7 +4333,7 @@ packages: '@types/web-bluetooth': 0.0.16 '@vueuse/metadata': 9.13.0 '@vueuse/shared': 9.13.0(vue@3.4.7) - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -4340,56 +4351,6 @@ packages: vue: 3.4.7(typescript@5.3.3) dev: true - /@vueuse/integrations@10.7.1(@vue/composition-api@1.7.2)(focus-trap@7.5.4)(vue@3.4.7): - resolution: {integrity: sha512-cKo5LEeKVHdBRBtMTOrDPdR0YNtrmN9IBfdcnY2P3m5LHVrsD0xiHUtAH1WKjHQRIErZG6rJUa6GA4tWZt89Og==} - peerDependencies: - async-validator: '*' - axios: '*' - change-case: '*' - drauu: '*' - focus-trap: '*' - fuse.js: '*' - idb-keyval: '*' - jwt-decode: '*' - nprogress: '*' - qrcode: '*' - sortablejs: '*' - universal-cookie: '*' - peerDependenciesMeta: - async-validator: - optional: true - axios: - optional: true - change-case: - optional: true - drauu: - optional: true - focus-trap: - optional: true - fuse.js: - optional: true - idb-keyval: - optional: true - jwt-decode: - optional: true - nprogress: - optional: true - qrcode: - optional: true - sortablejs: - optional: true - universal-cookie: - optional: true - dependencies: - '@vueuse/core': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) - '@vueuse/shared': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) - focus-trap: 7.5.4 - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true - /@vueuse/integrations@10.7.1(focus-trap@7.5.4)(fuse.js@6.6.2)(vue@3.4.7): resolution: {integrity: sha512-cKo5LEeKVHdBRBtMTOrDPdR0YNtrmN9IBfdcnY2P3m5LHVrsD0xiHUtAH1WKjHQRIErZG6rJUa6GA4tWZt89Og==} peerDependencies: @@ -4431,11 +4392,11 @@ packages: universal-cookie: optional: true dependencies: - '@vueuse/core': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) - '@vueuse/shared': 10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7) + '@vueuse/core': 10.7.1(vue@3.4.7) + '@vueuse/shared': 10.7.1(vue@3.4.7) focus-trap: 7.5.4 fuse.js: 6.6.2 - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -4463,7 +4424,7 @@ packages: '@vueuse/metadata': 10.6.1 local-pkg: 0.5.0 nuxt: 3.8.2(@types/node@20.10.4)(eslint@8.54.0)(rollup@3.29.4)(typescript@5.3.3)(vite@4.5.1)(vue-tsc@1.8.20) - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - rollup @@ -4474,16 +4435,16 @@ packages: /@vueuse/shared@10.6.1(vue@3.4.7): resolution: {integrity: sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==} dependencies: - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue dev: true - /@vueuse/shared@10.7.1(@vue/composition-api@1.7.2)(vue@3.4.7): + /@vueuse/shared@10.7.1(vue@3.4.7): resolution: {integrity: sha512-v0jbRR31LSgRY/C5i5X279A/WQjD6/JsMzGa+eqt658oJ75IvQXAeONmwvEMrvJQKnRElq/frzBR7fhmWY5uLw==} dependencies: - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -4492,7 +4453,7 @@ packages: /@vueuse/shared@9.13.0(vue@3.4.7): resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} dependencies: - vue-demi: 0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7) + vue-demi: 0.14.6(vue@3.4.7) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -7017,7 +6978,7 @@ packages: enhanced-resolve: 5.12.0 eslint: 8.56.0 eslint-module-utils: 2.7.4(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.13.1)(eslint@8.56.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.11.0 @@ -7247,6 +7208,41 @@ packages: - supports-color dev: true + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.13.1)(eslint@8.56.0): + resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.13.1(eslint@8.56.0)(typescript@5.3.3) + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7(supports-color@8.1.1) + doctrine: 2.1.0 + eslint: 8.56.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + hasown: 2.0.0 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + /eslint-plugin-jest@27.6.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -13971,6 +13967,10 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true + /scroll-lock@2.1.5: + resolution: {integrity: sha512-GN8Lp0AzXbkrPFUUNkMUruiiv019UvarNKE/SnXi+AxZRjMnDc2R22VB9RcUtL4P/uub04cKibmpHKIKTyWwYQ==} + dev: true + /scule@1.0.0: resolution: {integrity: sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==} dev: true @@ -16094,7 +16094,7 @@ packages: typescript: 5.3.3 dev: true - /vue-demi@0.14.6(@vue/composition-api@1.7.2)(vue@3.4.7): + /vue-demi@0.14.6(vue@3.4.7): resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} engines: {node: '>=12'} hasBin: true @@ -16106,7 +16106,6 @@ packages: '@vue/composition-api': optional: true dependencies: - '@vue/composition-api': 1.7.2(vue@3.4.7) vue: 3.4.7(typescript@5.3.3) /vue-devtools-stub@0.1.0: