82 lines
2.2 KiB
TypeScript
82 lines
2.2 KiB
TypeScript
import { useContext } from 'react';
|
|
import { BreakpointContext } from './BreakpointProvider'
|
|
import { uaParser } from '../../utils/uaParser'
|
|
|
|
export interface DeviceType {
|
|
mobile?: boolean;
|
|
tablet?: boolean;
|
|
desktop?: boolean;
|
|
}
|
|
|
|
export interface OrientationType {
|
|
landscape?: boolean
|
|
portrait?: boolean
|
|
}
|
|
|
|
export interface Breakpoints {
|
|
xs?: boolean
|
|
s?: boolean
|
|
m?: boolean
|
|
l?: boolean
|
|
xl?: boolean
|
|
// greater than the width
|
|
up?: boolean
|
|
// less than the width
|
|
down?: boolean
|
|
width?: {
|
|
min?: number
|
|
max?: number
|
|
}
|
|
}
|
|
|
|
export type BreakpointProps = DeviceType & Breakpoints & OrientationType
|
|
|
|
const deviceType = ['mobile', 'tablet', 'desktop']
|
|
|
|
const currentDeviceType = ['mobile', 'tablet'].includes(uaParser.device.model || '') ? uaParser.device.model : 'desktop'
|
|
|
|
function matchWidth(width: number, min?: number, max?: number): boolean {
|
|
if (typeof min === 'number' && typeof max === 'number') {
|
|
return width >= min && width <= max
|
|
}
|
|
if (typeof min === 'number') {
|
|
return width >= min
|
|
}
|
|
if (typeof max === 'number') {
|
|
return width <= max
|
|
}
|
|
return false
|
|
}
|
|
|
|
export const useBreakpoint = (props: BreakpointProps): boolean => {
|
|
const { breakpointList, size: { orientation, ...size } } = useContext(BreakpointContext)
|
|
let enabled: boolean
|
|
|
|
const allKeys = Object.keys(props)
|
|
|
|
const keysWithoutDeviceType = allKeys.filter(key => !deviceType.includes(key))
|
|
const keysWithDeviceType = allKeys.filter(key => deviceType.includes(key))
|
|
|
|
enabled = keysWithoutDeviceType.every(key => {
|
|
if (typeof breakpointList[key as keyof typeof breakpointList] === 'number' && !props.width) {
|
|
if (props.up) {
|
|
return size.width > breakpointList[key as keyof typeof breakpointList]
|
|
}
|
|
if (props.down) {
|
|
return size.width <= breakpointList[key as keyof typeof breakpointList]
|
|
}
|
|
return size.width === breakpointList[key as keyof typeof breakpointList]
|
|
}
|
|
if (key === 'width') {
|
|
return matchWidth(3000, props.width?.min, props.width?.max)
|
|
}
|
|
if (key === 'landscape' || key === 'portrait') {
|
|
return key === orientation
|
|
}
|
|
|
|
return true
|
|
}) && (keysWithDeviceType.length ? keysWithDeviceType.some(key => currentDeviceType === key) : true)
|
|
|
|
return enabled
|
|
}
|