breakpoint-changes-rx
Advanced tools
Comparing version 3.1.0 to 3.2.0
@@ -1,16 +0,7 @@ | ||
import { Observable, BehaviorSubject } from 'rxjs'; | ||
export interface BreakpointDefinition { | ||
min?: string | number; | ||
max?: string | number; | ||
} | ||
export type BreakpointDefinitions = Record<string, BreakpointDefinition>; | ||
export interface BreakpointParseConfig { | ||
regex?: RegExp; | ||
groupName?: number; | ||
groupMinMax?: number; | ||
isMin: (val: string) => boolean; | ||
} | ||
export declare const parseBreakpoints: (object: Record<string, unknown>, config?: Partial<BreakpointParseConfig>) => BreakpointDefinitions; | ||
import { BehaviorSubject } from 'rxjs'; | ||
import parseBreakpoints from './parseBreakpoints'; | ||
import type { BreakpointDefinitions, BreakpointParseConfig as BreakpointParseConfigType } from './types'; | ||
export type BreakpointParseConfig = BreakpointParseConfigType; | ||
declare const breakpoints: <T extends BreakpointDefinitions, K extends keyof T>(breakpointDefinitions: T) => { | ||
breakpointsChanges$: Observable<{ | ||
breakpointsChanges$: import("rxjs").Observable<{ | ||
curr: K[]; | ||
@@ -49,3 +40,3 @@ prev: K[]; | ||
*/ | ||
breakpointsChange: (bp: K) => Observable<boolean>; | ||
breakpointsChange: (bp: K) => import("rxjs").Observable<boolean>; | ||
/** | ||
@@ -58,4 +49,5 @@ * Create an observable emitting values for entering or leaving a breakpoint range | ||
*/ | ||
breakpointsInRange(range: K[]): Observable<boolean>; | ||
breakpointsInRange(range: K[]): import("rxjs").Observable<boolean>; | ||
}; | ||
export default breakpoints; | ||
export { parseBreakpoints }; |
@@ -1,73 +0,16 @@ | ||
import { Observable, merge, BehaviorSubject, } from 'rxjs'; | ||
import { scan, filter, map, bufferTime, share, } from 'rxjs/operators'; | ||
const nameMin = 'min'; | ||
const nameMax = 'max'; | ||
const defaultParseConfig = { | ||
regex: /^breakpoint-(\w*)-((max)|(min))$/, | ||
groupName: 1, | ||
groupMinMax: 2, | ||
isMin: (val) => val === nameMin, | ||
}; | ||
export const parseBreakpoints = (object, config) => { | ||
const parseConfig = Object.assign(Object.assign({}, defaultParseConfig), config); | ||
return Object.entries(object).reduce((obj, [key, value]) => { | ||
const breakpointMatch = key.match(parseConfig.regex); | ||
if (breakpointMatch && typeof value === 'string') { | ||
const name = breakpointMatch[parseConfig.groupName]; | ||
let breakpoint = obj[name]; | ||
if (!breakpoint) { | ||
breakpoint = {}; | ||
obj[name] = breakpoint; | ||
} | ||
breakpoint[parseConfig.isMin(breakpointMatch[parseConfig.groupMinMax]) | ||
? nameMin | ||
: nameMax] = value; | ||
} | ||
return obj; | ||
}, {}); | ||
}; | ||
import { BehaviorSubject } from 'rxjs'; | ||
import { filter, map, bufferTime, share, } from 'rxjs/operators'; | ||
import parseBreakpoints from './parseBreakpoints'; | ||
import fromBreakpointDefinitions from './fromBreakpointDefinitions'; | ||
import breakpointHits from './breakpointHits'; | ||
const breakpoints = (breakpointDefinitions) => { | ||
const initialBreakpoints = []; | ||
const breakpointsChanges$ = merge(...Object.entries(breakpointDefinitions) | ||
.map(([name, breakpoint]) => { | ||
const { min, max } = breakpoint; | ||
// matchMedia, build media query | ||
const mediaQueryList = matchMedia([['min', min], ['max', max]] | ||
.filter(([, val]) => val) | ||
.map(([str, val]) => `(${str}-width: ${typeof val === 'string' | ||
? val | ||
: `${String(val)}px`})`) | ||
.join(' and ')); | ||
// set the current breakpoints | ||
if (mediaQueryList.matches) { | ||
initialBreakpoints.push(name); | ||
} | ||
return new Observable((subscriber) => { | ||
mediaQueryList.addEventListener('change', ({ matches }) => { | ||
subscriber.next({ name: name, matches }); | ||
}); | ||
}); | ||
})).pipe(bufferTime(250), // collect and combine multiple matchMedia() matches at the same time | ||
filter(({ length }) => !!length), // and filter empty | ||
// convert it to the final breakpoint change object | ||
scan(({ curr: prev }, actual) => { | ||
const curr = [...prev]; // add previous breakpoint but without the removed ones | ||
actual.forEach(({ matches, name }) => { | ||
if (!matches) { | ||
const idx = curr.indexOf(name); | ||
/* istanbul ignore else */ | ||
if (idx !== -1) { | ||
curr.splice(idx, 1); | ||
} | ||
} | ||
else /* istanbul ignore else */ if (!curr.includes(name)) { | ||
curr.push(name); | ||
} | ||
}); | ||
return { curr, prev }; | ||
}, { curr: initialBreakpoints, prev: [] }), // initial value | ||
const breakpointsChanges$ = fromBreakpointDefinitions(breakpointDefinitions, initialBreakpoints).pipe(bufferTime(250), // collect and combine multiple matchMedia() matches at the same time | ||
breakpointHits(initialBreakpoints), // convert it to the final breakpoint change object | ||
share()); | ||
const breakpointsChangesBehavior$ = new BehaviorSubject({ curr: initialBreakpoints, prev: [] }); | ||
const breakpointsChangesBehavior$ = new BehaviorSubject({ | ||
curr: initialBreakpoints, | ||
prev: [], | ||
}); | ||
breakpointsChanges$.subscribe(breakpointsChangesBehavior$); | ||
// TODO: check array.includes(getCurrentBreakpoints()[0])) | ||
const getCurrentBreakpoints = () => { | ||
@@ -114,3 +57,3 @@ let bps = []; | ||
*/ | ||
breakpointsChange: (bp) => breakpointsChanges$.pipe(filter(({ curr, prev }) => [curr, prev].some((b) => breakpointListContainsBreakpoint(b, bp))), filter(({ curr, prev }) => curr.includes(bp) !== prev.includes(bp)), map(({ curr }) => curr.includes(bp))), | ||
breakpointsChange: (bp) => breakpointsChanges$.pipe(filter(({ curr, prev, }) => [curr, prev].some((b) => breakpointListContainsBreakpoint(b, bp))), filter(({ curr, prev, }) => curr.includes(bp) !== prev.includes(bp)), map(({ curr }) => curr.includes(bp))), | ||
/** | ||
@@ -125,3 +68,6 @@ * Create an observable emitting values for entering or leaving a breakpoint range | ||
const isInRange = (bpl) => breakpointListContainsBreakpoints(bpl, range); | ||
return breakpointsChanges$.pipe(map(({ curr, prev }) => ({ curr: isInRange(curr), prev: isInRange(prev) })), filter(({ curr, prev }) => curr !== prev), map(({ curr }) => curr)); | ||
return breakpointsChanges$.pipe(map(({ curr, prev, }) => ({ | ||
curr: isInRange(curr), | ||
prev: isInRange(prev), | ||
})), filter(({ curr, prev, }) => curr !== prev), map(({ curr, }) => curr)); | ||
}, | ||
@@ -131,1 +77,2 @@ }; | ||
export default breakpoints; | ||
export { parseBreakpoints }; |
{ | ||
"name": "breakpoint-changes-rx", | ||
"version": "3.1.0", | ||
"version": "3.2.0", | ||
"repository": { | ||
@@ -28,3 +28,3 @@ "type": "git", | ||
"scripts": { | ||
"lint": "eslint --fix --ext .tsx,.ts,.jsx,.js ./ && tsc --noEmit", | ||
"lint": "eslint --fix --ext .tsx,.ts,.mts,.cts,.jsx,.js,.mjs,.cjs ./ && tsc --noEmit", | ||
"build": "tsc", | ||
@@ -34,3 +34,3 @@ "prepublishOnly": "tsc", | ||
"ci-test": "run-s \"ci-test:*\"", | ||
"ci-test:lint": "eslint --ext .tsx,.ts,.jsx,.js ./", | ||
"ci-test:lint": "eslint --ext .tsx,.ts,.mts,.cts,.jsx,.js,.mjs,.cjs ./", | ||
"ci-test:tsc": "tsc --noEmit", | ||
@@ -45,21 +45,21 @@ "ci-test:test": "jest --coverage", | ||
"devDependencies": { | ||
"@commitlint/cli": "17.4.4", | ||
"@commitlint/config-conventional": "17.4.4", | ||
"@jenssimon/eslint-config-base": "6.6.12", | ||
"@jenssimon/eslint-config-typescript": "3.6.28", | ||
"@types/jest": "29.4.0", | ||
"@commitlint/cli": "17.6.6", | ||
"@commitlint/config-conventional": "17.6.6", | ||
"@jenssimon/eslint-config-base": "7.0.1", | ||
"@jenssimon/eslint-config-typescript": "4.0.1", | ||
"@types/jest": "29.5.2", | ||
"commitizen": "4.3.0", | ||
"cz-conventional-changelog": "3.3.0", | ||
"eslint": "8.35.0", | ||
"eslint": "8.44.0", | ||
"husky": "8.0.3", | ||
"jest": "29.5.0", | ||
"jest-environment-jsdom": "29.5.0", | ||
"lint-staged": "13.1.2", | ||
"lint-staged": "13.2.3", | ||
"npm-run-all": "4.1.5", | ||
"pinst": "3.0.0", | ||
"rxjs": "7.8.0", | ||
"semantic-release": "20.1.1", | ||
"ts-jest": "29.0.5", | ||
"rxjs": "7.8.1", | ||
"semantic-release": "21.0.6", | ||
"ts-jest": "29.1.1", | ||
"ts-node": "10.9.1", | ||
"typescript": "4.9.5" | ||
"typescript": "5.1.6" | ||
}, | ||
@@ -94,3 +94,3 @@ "peerDependencies": { | ||
}, | ||
"packageManager": "yarn@3.4.1", | ||
"packageManager": "yarn@3.6.1", | ||
"config": { | ||
@@ -97,0 +97,0 @@ "commitizen": { |
@@ -1,2 +0,2 @@ | ||
[![NPM version][npm-image]][npm-url] [![Downloads][npm-downloads-image]][npm-url] [![star this repo][gh-stars-image]][gh-url] [![fork this repo][gh-forks-image]][gh-url] [![Build Status][gh-status-image]][gh-url] [![Coverage Status][coveralls-image]][coveralls-url] | ||
[![NPM version][npm-image]][npm-url] [![Downloads][npm-downloads-image]][npm-url] [![star this repo][gh-stars-image]][gh-url] [![fork this repo][gh-forks-image]][gh-url] [![CI][gh-status-image]][gh-status-url] [![Coverage Status][coveralls-image]][coveralls-url] | ||
@@ -12,10 +12,10 @@ # breakpoint-changes-rx | ||
```typescript | ||
import breakpoints, { parseBreakpoints } from 'breakpoint-changes-rx'; | ||
import style from './style.scss'; | ||
import breakpoints, { parseBreakpoints } from 'breakpoint-changes-rx' | ||
import style from './style.scss' | ||
const breakpointDefinitions = parseBreakpoints(style); | ||
const breakpointDefinitions = parseBreakpoints(style) | ||
const bps = breakpoints(breakpointDefinitions); | ||
const bps = breakpoints(breakpointDefinitions) | ||
console.log('current breakpoints: %o', bps.getCurrentBreakpoints()); | ||
console.log('current breakpoints: %o', bps.getCurrentBreakpoints()) | ||
``` | ||
@@ -28,3 +28,3 @@ | ||
breakpoints.getCurrentBreakpoints(), // [ "md", "lg" } ] | ||
); | ||
) | ||
``` | ||
@@ -60,11 +60,11 @@ | ||
```javascript | ||
import breakpoints, { parseBreakpoints } from 'breakpoint-changes-rx'; | ||
import style from './style.scss'; | ||
```typescript | ||
import breakpoints, { parseBreakpoints } from 'breakpoint-changes-rx' | ||
import style from './style.scss' | ||
const breakpointDefinitions = parseBreakpoints(style); | ||
const breakpointDefinitions = parseBreakpoints(style) | ||
const bps = breakpoints(breakpointDefinitions); | ||
const bps = breakpoints(breakpointDefinitions) | ||
console.log('current breakpoints: %o', bps.getCurrentBreakpoints()); | ||
console.log('current breakpoints: %o', bps.getCurrentBreakpoints()) | ||
``` | ||
@@ -76,3 +76,3 @@ | ||
```javascript | ||
```typescript | ||
{ | ||
@@ -86,6 +86,9 @@ curr: ['md'], | ||
```javascript | ||
bps.breakpointChanges$.subscribe(({ curr, prev }) => { | ||
console.log('previous breakpoint is %o, actual breakpoint is %o', prev, curr); | ||
}); | ||
```typescript | ||
bps.breakpointChanges$.subscribe(({ | ||
curr, | ||
prev, | ||
}) => { | ||
console.log('previous breakpoint is %o, actual breakpoint is %o', prev, curr) | ||
}) | ||
``` | ||
@@ -103,6 +106,6 @@ | ||
```javascript | ||
const current = bp.getCurrentBreakpoints(); | ||
```typescript | ||
const current = bp.getCurrentBreakpoints() | ||
console.log('current breakpoints are %o', current); // e.g. ['lg'] | ||
console.log('current breakpoints are %o', current) // e.g. ['lg'] | ||
``` | ||
@@ -114,6 +117,6 @@ | ||
```javascript | ||
```typescript | ||
bp.breakpointsChange('md').subscribe((active) => { | ||
console.log('breakpoint md %s', active ? 'entered' : 'left'); | ||
}); | ||
console.log('breakpoint md %s', active ? 'entered' : 'left') | ||
}) | ||
``` | ||
@@ -125,6 +128,6 @@ | ||
```javascript | ||
```typescript | ||
bp.breakpointsInRange(['sm', 'md']).subscribe((active) => { | ||
console.log('range gets %s', active ? 'entered' : 'left'); | ||
}); | ||
console.log('range gets %s', active ? 'entered' : 'left') | ||
}) | ||
``` | ||
@@ -136,4 +139,4 @@ | ||
```javascript | ||
console.log('this might be a mobile device %o', bp.includesBreakpoints(['sm', 'md'])); | ||
```typescript | ||
console.log('this might be a mobile device %o', bp.includesBreakpoints(['sm', 'md'])) | ||
``` | ||
@@ -145,4 +148,4 @@ | ||
```javascript | ||
console.log('breakpoint "md" is active %o', bp.includesBreakpoint('md')); | ||
```typescript | ||
console.log('breakpoint "md" is active %o', bp.includesBreakpoint('md')) | ||
``` | ||
@@ -167,3 +170,3 @@ | ||
{ | ||
"sm": { "max": "767px", }, | ||
"sm": { "max": "767px" }, | ||
"md": { "min": "768px", "max": "991px" }, | ||
@@ -192,7 +195,7 @@ "lg": { "min": "992px", "max": "1199px" }, | ||
```javascript | ||
import { parseBreakpoints } from 'breakpoint-changes-rx'; | ||
import style from './style.scss'; | ||
```typescript | ||
import { parseBreakpoints } from 'breakpoint-changes-rx' | ||
import style from './style.scss' | ||
const breakpointDefinitions = parseBreakpoints(style); | ||
const breakpointDefinitions = parseBreakpoints(style) | ||
``` | ||
@@ -222,5 +225,6 @@ | ||
[gh-forks-image]: https://badgen.net/github/forks/jenssimon/breakpoint-changes-rx | ||
[gh-status-image]: https://badgen.net/github/status/jenssimon/breakpoint-changes-rx | ||
[gh-status-image]: https://github.com/jenssimon/breakpoint-changes-rx/actions/workflows/ci.yml/badge.svg | ||
[gh-status-url]: https://github.com/jenssimon/breakpoint-changes-rx/actions/workflows/ci.yml | ||
[coveralls-url]: https://coveralls.io/github/jenssimon/breakpoint-changes-rx?branch=main | ||
[coveralls-image]: https://coveralls.io/repos/github/jenssimon/breakpoint-changes-rx/badge.svg?branch=main |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
218
16292
126