Skip to content

Commit

Permalink
feat: new updates
Browse files Browse the repository at this point in the history
  • Loading branch information
sadeghbarati committed Oct 15, 2024
1 parent 4df119c commit d811614
Show file tree
Hide file tree
Showing 14 changed files with 4,967 additions and 4,418 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "module",
"version": "0.0.0",
"private": true,
"packageManager": "pnpm@8.15.4",
"packageManager": "pnpm@9.12.1",
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
Expand All @@ -12,11 +12,11 @@
"build:playground": "pnpm build:package && pnpm --filter playground build"
},
"devDependencies": {
"@antfu/eslint-config": "^2.6.4",
"@changesets/cli": "^2.27.1",
"@playwright/test": "^1.41.2",
"@rushstack/eslint-patch": "^1.3.3",
"@vue/eslint-config-typescript": "^12.0.0",
"eslint": "^8.56.0"
"@antfu/eslint-config": "^3.7.3",
"@changesets/cli": "^2.27.9",
"@playwright/test": "^1.48.0",
"@rushstack/eslint-patch": "^1.10.4",
"@vue/eslint-config-typescript": "^14.1.1",
"eslint": "^9.12.0"
}
}
42 changes: 21 additions & 21 deletions packages/vaul-vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,28 @@
"vue": "^3.3.0"
},
"dependencies": {
"@vueuse/core": "^10.8.0",
"radix-vue": "^1.4.9",
"vue": "^3.4.5"
"@vueuse/core": "^11.1.0",
"radix-vue": "^1.9.7"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/jsdom": "^21.1.6",
"@types/node": "^18.19.3",
"@vitejs/plugin-vue": "^4.5.2",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "^2.4.3",
"@vue/tsconfig": "^0.5.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"jsdom": "^23.0.1",
"npm-run-all2": "^6.1.1",
"typescript": "~5.3.0",
"vite": "^5.0.10",
"vite-plugin-css-injected-by-js": "^3.3.1",
"vite-plugin-dts": "^3.7.0",
"vitest": "^1.0.4",
"vue-tsc": "^1.8.25"
"@rushstack/eslint-patch": "^1.10.4",
"@tsconfig/node18": "^18.2.4",
"@types/jsdom": "^21.1.7",
"@types/node": "^18.19.55",
"@vitejs/plugin-vue": "^5.1.4",
"@vue/eslint-config-typescript": "^14.1.1",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.5.1",
"eslint": "^9.12.0",
"eslint-plugin-vue": "^9.29.0",
"jsdom": "^25.0.1",
"npm-run-all2": "^6.2.3",
"typescript": "~5.6.3",
"vite": "^5.4.9",
"vite-plugin-css-injected-by-js": "^3.5.2",
"vite-plugin-dts": "^4.2.4",
"vitest": "^2.1.3",
"vue": "^3.5.12",
"vue-tsc": "^2.1.6"
}
}
4 changes: 2 additions & 2 deletions packages/vaul-vue/src/DrawerRoot.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { DialogRoot } from 'radix-vue'
import { useVModel } from '@vueuse/core'
import { type WritableComputedRef, computed, toRefs } from 'vue'
import { DialogRoot } from 'radix-vue'
import { computed, toRefs, type WritableComputedRef } from 'vue'
import { provideDrawerRootContext } from './context'
import {
CLOSE_THRESHOLD,
Expand Down
36 changes: 36 additions & 0 deletions packages/vaul-vue/src/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export function isMobileFirefox(): boolean | undefined {
const userAgent = navigator.userAgent
return (
typeof window !== 'undefined'
&& ((/Firefox/.test(userAgent) && /Mobile/.test(userAgent)) // Android Firefox
|| /FxiOS/.test(userAgent)) // iOS Firefox
)
}

export function isMac(): boolean | undefined {
return testPlatform(/^Mac/)
}

export function isIPhone(): boolean | undefined {
return testPlatform(/^iPhone/)
}

export function isSafari(): boolean | undefined {
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
}

export function isIPad(): boolean | undefined {
return (
testPlatform(/^iPad/)
// iPadOS 13 lies and says it's a Mac, but we can distinguish by detecting touch support.
|| (isMac() && navigator.maxTouchPoints > 1)
)
}

export function isIOS(): boolean | undefined {
return isIPhone() || isIPad()
}

export function testPlatform(re: RegExp): boolean | undefined {
return typeof window !== 'undefined' && window.navigator != null ? re.test(window.navigator.platform) : undefined
}
12 changes: 12 additions & 0 deletions packages/vaul-vue/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,15 @@ export const TRANSITIONS = {
}

export const VELOCITY_THRESHOLD = 0.4

export const CLOSE_THRESHOLD = 0.25

export const SCROLL_LOCK_TIMEOUT = 100

export const BORDER_RADIUS = 8

export const NESTED_DISPLACEMENT = 16

export const WINDOW_TOP_OFFSET = 26

export const DRAG_CLASS = 'vaul-dragging'
52 changes: 31 additions & 21 deletions packages/vaul-vue/src/context.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
import type { ComponentPublicInstance, Ref } from 'vue'
import { createContext } from 'radix-vue'
import type { DialogRootProps } from 'radix-vue'
import type { DrawerDirection } from './types'

export interface DrawerRootContext {
open: Ref<boolean>
isOpen: Ref<boolean>
modal: Ref<boolean>
drawerRef: Ref<ComponentPublicInstance | null> //
overlayRef: Ref<ComponentPublicInstance | null> //
onPress: (event: PointerEvent) => void //
onRelease: (event: PointerEvent) => void //
onDrag: (event: PointerEvent) => void //
onNestedDrag: (percentageDragged: number) => void //
onNestedOpenChange: (o: boolean) => void //
onNestedRelease: (o: boolean) => void //
dismissible: Ref<boolean>
isOpen: Ref<boolean> //
isDragging: Ref<boolean> //
keyboardIsOpen: Ref<boolean> //
snapPointsOffset: Ref<number[]> //
snapPoints: Ref<(number | string)[] | undefined> //
activeSnapPointIndex?: number | null // **
modal: Ref<boolean> //
shouldFade: Ref<boolean>
activeSnapPoint: Ref<number | string | null | undefined>
closeDrawer: () => void
open: Ref<boolean> //
direction: Ref<DrawerDirection>
shouldScaleBackground: Ref<boolean | undefined>
setBackgroundColorOnScale: boolean // **
noBodyStyles: boolean // **
handleOnly?: boolean
container?: HTMLElement | null
autoFocus?: boolean
shouldAnimate?: Ref<boolean | undefined>

/** vaul-vue */
hasBeenOpened: Ref<boolean>
isVisible: Ref<boolean>
drawerRef: Ref<ComponentPublicInstance | null>
overlayRef: Ref<ComponentPublicInstance | null>
isDragging: Ref<boolean>
dragStartTime: Ref<Date | null>
isAllowedToDrag: Ref<boolean>
snapPoints: Ref<(number | string)[] | undefined>
keyboardIsOpen: Ref<boolean>
activeSnapPoint: Ref<number | string | null | undefined>
pointerStart: Ref<number>
dismissible: Ref<boolean>
drawerHeightRef: Ref<number>
snapPointsOffset: Ref<number[]>
direction: Ref<DrawerDirection>
onPress: (event: PointerEvent) => void
onDrag: (event: PointerEvent) => void
onRelease: (event: PointerEvent) => void
closeDrawer: () => void
shouldFade: Ref<boolean>
fadeFromIndex: Ref<number | undefined>
shouldScaleBackground: Ref<boolean | undefined>
onNestedDrag: (percentageDragged: number) => void
onNestedRelease: (o: boolean) => void
onNestedOpenChange: (o: boolean) => void
emitClose: () => void
emitDrag: (percentageDragged: number) => void
emitRelease: (open: boolean) => void
Expand Down
10 changes: 5 additions & 5 deletions packages/vaul-vue/src/controls.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { computed, onUnmounted, ref, watch, watchEffect } from 'vue'
import type { ComponentPublicInstance, Ref } from 'vue'
import type { DrawerRootContext } from './context'
import type { DrawerDirection } from './types'
import { isClient } from '@vueuse/core'
import { dampenValue, getTranslate, isVertical, reset, set } from './helpers'
import { computed, onUnmounted, ref, watch, watchEffect } from 'vue'
import { TRANSITIONS, VELOCITY_THRESHOLD } from './constants'
import { useSnapPoints } from './useSnapPoints'
import { dampenValue, getTranslate, isVertical, reset, set } from './helpers'
import { usePositionFixed } from './usePositionFixed'
import type { DrawerRootContext } from './context'
import type { DrawerDirection } from './types'
import { useSnapPoints } from './useSnapPoints'

export const CLOSE_THRESHOLD = 0.25

Expand Down
49 changes: 38 additions & 11 deletions packages/vaul-vue/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DrawerDirection } from './types'
import type { AnyFunction, DrawerDirection } from './types'

interface Style {
[key: string]: string
Expand Down Expand Up @@ -60,7 +60,23 @@ export function reset(el: Element | HTMLElement | null, prop?: string) {
}
}

export function isVertical(direction: DrawerDirection) {
switch (direction) {
case 'top':
case 'bottom':
return true
case 'left':
case 'right':
return false
default:
return direction satisfies never
}
}

export function getTranslate(element: HTMLElement, direction: DrawerDirection): number | null {
if (!element)
return null

const style = window.getComputedStyle(element)
const transform
// @ts-expect-error some custom style only exist in certain browser
Expand All @@ -79,15 +95,26 @@ export function dampenValue(v: number) {
return 8 * (Math.log(v + 1) - 2)
}

export function isVertical(direction: DrawerDirection) {
switch (direction) {
case 'top':
case 'bottom':
return true
case 'left':
case 'right':
return false
default:
return direction satisfies never
export function assignStyle(element: HTMLElement | null | undefined, style: Partial<CSSStyleDeclaration>) {
if (!element)
return () => {}

const prevStyle = element.style.cssText
Object.assign(element.style, style)

return () => {
element.style.cssText = prevStyle
}
}

/**
* Receives functions as arguments and returns a new function that calls all.
*/
export function chain<T>(...fns: T[]) {
return (...args: T extends AnyFunction ? Parameters<T> : never) => {
for (const fn of fns) {
if (typeof fn === 'function')
fn(...args)
}
}
}
2 changes: 2 additions & 0 deletions packages/vaul-vue/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export interface SnapPoint {
}

export type DrawerDirection = 'top' | 'bottom' | 'left' | 'right'

export type AnyFunction = (...args: any) => any
37 changes: 26 additions & 11 deletions packages/vaul-vue/src/usePositionFixed.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,53 @@
import { type Ref, onMounted, onUnmounted, ref, watch } from 'vue'
import { onMounted, onUnmounted, type Ref, ref, watch } from 'vue'
import { isSafari } from './browser'

interface BodyPosition {
position: string
top: string
left: string
height: string
right: string
}

interface PositionFixedOptions {
isOpen: Ref<boolean>
modal: Ref<boolean>
nested: Ref<boolean>
hasBeenOpened: Ref<boolean>
preventScrollRestoration: Ref<boolean>
noBodyStyles: Ref<boolean>
}

let previousBodyPosition: BodyPosition | null = null

export function usePositionFixed(options: PositionFixedOptions) {
const { isOpen, modal, nested, hasBeenOpened } = options
const { isOpen, modal, nested, hasBeenOpened, preventScrollRestoration, noBodyStyles } = options
const activeUrl = ref(typeof window !== 'undefined' ? window.location.href : '')
const scrollPos = ref(0)

function setPositionFixed(): void {
if (previousBodyPosition === null && isOpen.value) {
if (!isSafari())
return

// If previousBodyPosition is already set, don't set it again.
if (previousBodyPosition === null && isOpen.value && !noBodyStyles.value) {
previousBodyPosition = {
position: document.body.style.position,
top: document.body.style.top,
left: document.body.style.left,
height: document.body.style.height,
right: 'unset',
}

const { scrollX, innerHeight } = window

document.body.style.position = 'fixed'
document.body.style.top = `-${scrollPos.value}px`
document.body.style.left = `-${scrollX}px`
document.body.style.right = '0px'
document.body.style.height = 'auto'
document.body.style.setProperty('position', 'fixed', 'important')
Object.assign(document.body.style, {
top: `${-scrollPos.value}px`,
left: `${-scrollX}px`,
right: '0px',
height: 'auto',
})

setTimeout(() => {
requestAnimationFrame(() => {
Expand All @@ -52,7 +63,11 @@ export function usePositionFixed(options: PositionFixedOptions) {
}

function restorePositionSetting(): void {
if (previousBodyPosition !== null) {
// All browsers on iOS will return true here.
if (!isSafari())
return

if (previousBodyPosition !== null && !noBodyStyles.value) {
// Convert the position from "px" to Int
const y = -Number.parseInt(document.body.style.top, 10)
const x = -Number.parseInt(document.body.style.left, 10)
Expand All @@ -61,7 +76,7 @@ export function usePositionFixed(options: PositionFixedOptions) {
Object.assign(document.body.style, previousBodyPosition)

requestAnimationFrame(() => {
if (activeUrl.value !== window.location.href) {
if (preventScrollRestoration && activeUrl.value !== window.location.href) {
activeUrl.value = window.location.href
return
}
Expand All @@ -86,7 +101,7 @@ export function usePositionFixed(options: PositionFixedOptions) {
})
})

watch([isOpen, hasBeenOpened, activeUrl], () => {
watch([isOpen, hasBeenOpened, activeUrl, modal, nested, setPositionFixed, restorePositionSetting], () => {
if (nested.value || !hasBeenOpened.value)
return

Expand Down
Loading

0 comments on commit d811614

Please sign in to comment.