Skip to content

Commit

Permalink
feat(useBreakpoints): add strategy option to allow desktop-first co…
Browse files Browse the repository at this point in the history
…nvention (#3783)

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
jack-allocate and antfu committed Feb 20, 2024
1 parent 66d09b5 commit 15fc0fa
Showing 1 changed file with 36 additions and 17 deletions.
53 changes: 36 additions & 17 deletions packages/core/useBreakpoints/index.ts
Expand Up @@ -10,12 +10,27 @@ export * from './breakpoints'

export type Breakpoints<K extends string = string> = Record<K, MaybeRefOrGetter<number | string>>

export interface UseBreakpointsOptions extends ConfigurableWindow {
/**
* The query strategy to use for the generated shortcut methods like `.lg`
*
* 'min-width' - .lg will be true when the viewport is greater than or equal to the lg breakpoint (mobile-first)
* 'max-width' - .lg will be true when the viewport is smaller than the xl breakpoint (desktop-first)
*
* @default "min-width"
*/
strategy?: 'min-width' | 'max-width'
}

/**
* Reactively viewport breakpoints
*
* @see https://vueuse.org/useBreakpoints
*/
export function useBreakpoints<K extends string>(breakpoints: Breakpoints<K>, options: ConfigurableWindow = {}) {
export function useBreakpoints<K extends string>(
breakpoints: Breakpoints<K>,
options: UseBreakpointsOptions = {},
) {
function getValue(k: MaybeRefOrGetter<K>, delta?: number) {
let v = toValue(breakpoints[toValue(k)])

Expand All @@ -28,7 +43,7 @@ export function useBreakpoints<K extends string>(breakpoints: Breakpoints<K>, op
return v
}

const { window = defaultWindow } = options
const { window = defaultWindow, strategy = 'min-width' } = options

function match(query: string): boolean {
if (!window)
Expand All @@ -40,27 +55,31 @@ export function useBreakpoints<K extends string>(breakpoints: Breakpoints<K>, op
return useMediaQuery(() => `(min-width: ${getValue(k)})`, options)
}

const smallerOrEqual = (k: MaybeRefOrGetter<K>) => {
return useMediaQuery(() => `(max-width: ${getValue(k)})`, options)
}

const shortcutMethods = Object.keys(breakpoints)
.reduce((shortcuts, k) => {
Object.defineProperty(shortcuts, k, {
get: () => greaterOrEqual(k as K),
get: () => strategy === 'min-width'
? greaterOrEqual(k as K)
: smallerOrEqual(k as K),
enumerable: true,
configurable: true,
})
return shortcuts
}, {} as Record<K, Ref<boolean>>)

return Object.assign(shortcutMethods, {
greaterOrEqual,
smallerOrEqual,
greater(k: MaybeRefOrGetter<K>) {
return useMediaQuery(() => `(min-width: ${getValue(k, 0.1)})`, options)
},
greaterOrEqual,
smaller(k: MaybeRefOrGetter<K>) {
return useMediaQuery(() => `(max-width: ${getValue(k, -0.1)})`, options)
},
smallerOrEqual(k: MaybeRefOrGetter<K>) {
return useMediaQuery(() => `(max-width: ${getValue(k)})`, options)
},
between(a: MaybeRefOrGetter<K>, b: MaybeRefOrGetter<K>) {
return useMediaQuery(() => `(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`, options)
},
Expand All @@ -87,15 +106,15 @@ export function useBreakpoints<K extends string>(breakpoints: Breakpoints<K>, op
}

export type UseBreakpointsReturn<K extends string = string> = {
greater: (k: K) => ComputedRef<boolean>
greaterOrEqual: (k: K) => ComputedRef<boolean>
smaller: (k: K) => ComputedRef<boolean>
smallerOrEqual: (k: K) => ComputedRef<boolean>
between: (a: K, b: K) => ComputedRef<boolean>
isGreater: (k: K) => boolean
isGreaterOrEqual: (k: K) => boolean
isSmaller: (k: K) => boolean
isSmallerOrEqual: (k: K) => boolean
isInBetween: (a: K, b: K) => boolean
greater: (k: MaybeRefOrGetter<K>) => ComputedRef<boolean>
greaterOrEqual: (k: MaybeRefOrGetter<K>) => ComputedRef<boolean>
smaller: (k: MaybeRefOrGetter<K>) => ComputedRef<boolean>
smallerOrEqual: (k: MaybeRefOrGetter<K>) => ComputedRef<boolean>
between: (a: MaybeRefOrGetter<K>, b: MaybeRefOrGetter<K>) => ComputedRef<boolean>
isGreater: (k: MaybeRefOrGetter<K>) => boolean
isGreaterOrEqual: (k: MaybeRefOrGetter<K>) => boolean
isSmaller: (k: MaybeRefOrGetter<K>) => boolean
isSmallerOrEqual: (k: MaybeRefOrGetter<K>) => boolean
isInBetween: (a: MaybeRefOrGetter<K>, b: MaybeRefOrGetter<K>) => boolean
current: () => ComputedRef<string[]>
} & Record<K, ComputedRef<boolean>>

0 comments on commit 15fc0fa

Please sign in to comment.