Socket
Socket
Sign inDemoInstall

styled-breakpoints

Package Overview
Dependencies
Maintainers
1
Versions
183
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

styled-breakpoints - npm Package Compare versions

Comparing version 12.1.10 to 13.0.0

9

package.json
{
"name": "styled-breakpoints",
"version": "12.1.10",
"version": "13.0.0",
"description": "Simple and powerful css breakpoints for styled-components and emotion",
"main": "index.js",
"types": "index.d.ts",
"main": "./styled-breakpoints/create-styled-breakpoints-theme/create-styled-breakpoints-theme.js",
"types": "./styled-breakpoints/create-styled-breakpoints-theme/create-styled-breakpoints-theme.d.ts",
"sideEffects": false,

@@ -89,3 +89,3 @@ "scripts": {

"husky": "^8.0.3",
"jsdom": "^23.0.0",
"jsdom": "^24.0.0",
"lint-staged": "^15.1.0",

@@ -95,2 +95,3 @@ "prettier": "^3.1.0",

"react-dom": "^18.2.0",
"semantic-release-githubsquash": "^0.2.12",
"size-limit": "^11.0.2",

@@ -97,0 +98,0 @@ "vitest": "^1.0.1"

@@ -1,10 +0,1 @@

<div align="right">
<a href="https:///pr.new/mg901/styled-breakpoints">
<img
alt="Open in Codeflow"
src="https://developer.stackblitz.com/img/open_in_codeflow_small.svg"
/>
</a>
</div>
<div align="center">

@@ -48,5 +39,5 @@ <h1>

</div>
<br >
<br >
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua)
# Breakpoints

@@ -125,3 +116,2 @@

- [quick start](#quick-start)
- migration from v11
- [media queries](#media-queries)

@@ -134,4 +124,2 @@ - [min-width](#min-width)

- [customization](#customization)
- strict typed breakpoints
- merge with another theme

@@ -183,18 +171,45 @@ <br>

`styled.d.ts`
<br >
#### Configuration
`theme/index.tsx`
```tsx
import { createStyledBreakpointsTheme } from 'styled-breakpoints';
import styled { ThemeProvider as Provider } from 'styled-components';
export const theme = createStyledBreakpointsTheme();
type Props = {
children: React.ReactNode;
}
export const ThemeProvider = ({children}: Props) => {
return <Provider theme={theme}>{children}</Provider>
}
```
<br >
`theme/styled.d.ts`
```ts
import 'styled-components';
import { StyledBreakpointsTheme } from 'styled-breakpoints';
import { theme } from './theme';
type CustomTheme = typeof theme;
declare module 'styled-components' {
export interface DefaultTheme extends StyledBreakpointsTheme {}
export interface DefaultTheme extends CustomTheme {}
}
```
<br >
`app.tsx`
```tsx
import styled { DefaultTheme, ThemeProvider } from 'styled-components';
import { createStyledBreakpointsTheme } from 'styled-breakpoints';
import styled from 'styled-components';
import { ThemeProvider } from './theme';

@@ -207,10 +222,9 @@ const Box = styled.div`

}
`
const theme: DefaultTheme = createStyledBreakpointsTheme();
`;
const App = () => (
<ThemeProvider theme={theme}>
<Box/>
<ThemeProvider>
<Box />
</ThemeProvider>
)
);
```

@@ -234,19 +248,45 @@

`emotion.d.ts`
<br >
#### Configuration
`theme/index.tsx`
```tsx
import { createStyledBreakpointsTheme } from 'styled-breakpoints';
import { ThemeProvider as Provider } from '@emotion/react';
export const theme = createStyledBreakpointsTheme();
type Props = {
children: React.ReactNode;
};
export const ThemeProvider = ({ children }: Props) => {
return <Provider theme={theme}>{children}</Provider>;
};
```
<br >
`theme/emotion.d.ts`
```ts
import '@emotion/react';
import { StyledBreakpointsTheme } from 'styled-breakpoints';
import { theme } from './theme';
type CustomTheme = typeof theme;
declare module '@emotion/react' {
export interface Theme extends StyledBreakpointsTheme {}
export interface Theme extends CustomTheme {}
}
```
<br >
`app.tsx`
```tsx
import styled, from '@emotion/styled';
import { Theme, ThemeProvider } from '@emotion/react';
import { createStyledBreakpointsTheme } from 'styled-breakpoints';
import styled from '@emotion/styled';
import { ThemeProvider } from './theme';

@@ -261,6 +301,4 @@ const Box = styled.div`

const theme: Theme = createStyledBreakpointsTheme();
const App = () => (
<ThemeProvider theme={theme}>
<ThemeProvider>
<Box />

@@ -275,68 +313,2 @@ </ThemeProvider>

<details><summary><h2>🏎️&nbsp; Migration from <a href="https://github.com/mg901/styled-breakpoints/tree/v11.2.3" target="_blank">v11.2.3</a></h2></summary>
### Theme
The `createTheme` function has been replaced with `createStyledBreakpointsTheme`.
```diff
- import { createTheme } from "styled-breakpoints";
- const theme = createTheme();
+ import { createStyledBreakpointsTheme } from "styled-breakpoints";
+ const theme = createStyledBreakpointsTheme();
```
### Breakpoint Functions
Additionally, the functions `up`, `down`, `between`, and `only` have been moved to the theme object. This means that you no longer need to import them individually each time you want to use them.
```diff
- import { up } from "styled-breakpoints";
- const Box = styled.div`
- ${up('md')} {
- background-color: red;
- }
+ const Box = styled.div`
+ ${({ theme }) => theme.breakpoints.up('md')} {
+ background-color: red;
+ }
`
```
### Hooks
```diff
- import { up } from 'styled-breakpoints';
- import { useBreakpoint } from 'styled-breakpoints/react-styled';
or
- import { up } from 'styled-breakpoints';
- import { useBreakpoint } from 'styled-breakpoints/react-emotion';
- const Example = () => {
- const isMd = useBreakpoint(only('md'));
-
- return <Layout>{isMd && </Box>}</Layout>
- }
+ import { useMediaQuery } from 'styled-breakpoints/use-media-query';
+ const Example = () => {
+ const isMd = useMediaQuery(useTheme()?.breakpoints.only('md'));
+
+ return <Layout>{isMd && </Box>}</Layout>
+ }
```
</details>
## Media queries

@@ -507,3 +479,3 @@

```ts
declare function useMediaQuery(query?: string) => boolean
declare function useMediaQuery(query: string) => boolean
```

@@ -519,3 +491,3 @@

const SomeComponent = () => {
const isMd = useMediaQuery(useTheme()?.breakpoints.only('md'));
const isMd = useMediaQuery(useTheme().breakpoints.only('md'));

@@ -530,84 +502,9 @@ return <AnotherComponent>{isMd && <Box />}</AnotherComponent>;

<details><summary><h3> ⚙️ Strict Typed Breakpoints</h3></summary>
<h3>🎨 Merge with another theme</h3>
`app.tsx`
`theme/index.tsx`
```tsx
import styled, { DefaultTheme } from 'styled-components'; // or from '@emotion/react'
import { createStyledBreakpointsTheme } from 'styled-breakpoints';
export const breakpoints = {
small: '0px',
medium: '640px',
large: '1024px',
xLarge: '1200px',
xxLarge: '1440px',
} as const;
const theme: DefaultTheme = createStyledBreakpointsTheme({
breakpoints,
});
const App = () => (
<ThemeProvider theme={theme}>
<Box />
</ThemeProvider>
);
```
<details open><summary><h4>💅 Styled Components</h4></summary>
`styled.d.ts`
```ts
import 'styled-components';
import { MediaQueries } from 'styled-breakpoints';
import { breakpoints } from './app';
type Min = keyof typeof breakpoints;
// For max values remove the first key.
type Max = Exclude<keyof typeof breakpoints, 'small'>;
declare module 'styled-components' {
export interface DefaultTheme {
breakpoints: MediaQueries<Min, Max>;
}
}
```
</details>
<details><summary><h4><g-emoji class="g-emoji" alias="woman_singer" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f469-1f3a4.png">👩&zwj;🎤</g-emoji> Emotion</h4></summary>
`emotion.d.ts`
```ts
import '@emotion/react';
import { MediaQueries } from 'styled-breakpoints';
import { breakpoints } from './app';
type Min = keyof typeof breakpoints;
// For max values remove the first key.
type Max = Exclude<keyof typeof breakpoints, 'small'>;
declare module '@emotion/react' {
export interface Theme extends {
breakpoints: MediaQueries<Min, Max>;
}
}
```
</details>
</details>
<details><summary><h3>🎨 Merge with another theme</h3></summary>
`app.tsx`
```tsx
import { DefaultTheme, ThemeProvider } from 'styled-components'; // or from '@emotion/react';
import { createStyledBreakpointsTheme } from 'styled-breakpoints';
export const primaryTheme = {

@@ -622,52 +519,10 @@ fonts: ['sans-serif', 'Roboto'],

const const theme: DefaultTheme = {
export const theme = {
...primaryTheme,
...createStyledBreakpointsTheme(),
}
const App = () => (
<ThemeProvider theme={theme}>
<Box />
</ThemeProvider>
);
} as const;
```
<details open><summary><h4>💅 Styled Components</h4></summary>
<br>
`styled.d.ts`
```ts
import 'styled-components';
import { StyledBreakpointsTheme } from 'styled-breakpoints';
import { primaryTheme } from './app';
type PrimaryTheme = typeof primaryTheme;
declare module 'styled-components' {
export interface DefaultTheme extends StyledBreakpointsTheme, PrimaryTheme {}
}
```
</details>
<details><summary><h4><g-emoji class="g-emoji" alias="woman_singer" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f469-1f3a4.png">👩&zwj;🎤</g-emoji> Emotion</h4></summary>
`emotion.d.ts`
```ts
import '@emotion/react';
import { StyledBreakpointsTheme } from 'styled-breakpoints';
import { primaryTheme } from './app';
type PrimaryTheme = typeof primaryTheme;
declare module '@emotion/react' {
export interface Theme extends PrimaryTheme, StyledBreakpointsTheme {}
}
```
</details>
</details>
## License

@@ -674,0 +529,0 @@

const { createBreakpointsApi } = require('./create-breakpoints-api.prod');
const { createInvariant } = require('../create-invariant');
/**
* Creates an object with breakpoints.
* @param {Object} options - The options for creating the theme.
* @param {Object} options.breakpoints - An object defining breakpoints.
* @param {String} options.errorPrefix - The error prefix for validation.
* @returns {Object} - An object with breakpoint functions.
*/
exports.createBreakpointsApi = ({ breakpoints, errorPrefix }) => {
// Create an object for input validation
const invariant = createInvariant(errorPrefix);
const DEFAULT_ERROR_PREFIX = '[breakpoints]: ';
exports.DEFAULT_ERROR_PREFIX = DEFAULT_ERROR_PREFIX;
exports.createBreakpointsApi = ({ breakpoints, errorPrefix } = {}) => {
const invariant = createInvariant(errorPrefix || DEFAULT_ERROR_PREFIX);
const validation = createValidation({

@@ -21,3 +16,2 @@ invariant,

// Create a breakpoints API
const api = createBreakpointsApi({

@@ -27,7 +21,2 @@ breakpoints,

/**
* Get the minimum breakpoint value.
* @param {string} min - The breakpoint key.
* @returns {string} - The minimum breakpoint value.
*/
const up = (min) => {

@@ -39,7 +28,2 @@ validation.validateKey(min);

/**
* Get the maximum breakpoint value using calcMaxWidth.
* @param {string} max - The breakpoint key.
* @returns {string} - The maximum breakpoint value.
*/
const down = (max) => {

@@ -52,8 +36,2 @@ validation.validateKey(max);

/**
* Get a range between two breakpoints.
* @param {string} min - The minimum breakpoint key.
* @param {string} max - The maximum breakpoint key.
* @returns {Object} - An object with 'min' and 'max' properties containing the corresponding breakpoint values.
*/
const between = (min, max) => {

@@ -67,7 +45,2 @@ validation.validateKey(min);

/**
* Get a range based on a single breakpoint key.
* @param {string} key - The breakpoint key.
* @returns {string|Object} - The minimum or a range object based on the provided key.
*/
const only = (key) => {

@@ -102,2 +75,3 @@ validation.validateKey(key);

const VALID_PATTERN = /^\d+px$/;
const invalidBreakpoints = keys.reduce((acc, key) => {

@@ -122,13 +96,12 @@ // Check the validity of breakpoint values

function validateKey(key) {
// Check if the specified breakpoint exists
invariant(
breakpoints[key],
`breakpoint \`${key}\` not found in ${keys.join(', ')}.`
`Breakpoint \`${key}\` not found in ${keys.join(', ')}.`
);
}
// Check that a breakpoint is not equal to 0.
function validateNonZeroValue(key) {
const value = breakpoints[key];
// Check that the breakpoint is not 0
invariant(

@@ -143,3 +116,2 @@ removeUnits(value) !== 0,

// Check that `max` is greater than or equal to `min`
invariant(diff >= 0, 'The `max` value cannot be less than the `min`.');

@@ -150,3 +122,3 @@ }

function removeUnits(value) {
return parseInt(value, 10);
return parseInt(value, 10) || 0;
}

@@ -36,7 +36,3 @@ const { calcMaxWidth } = require('../calc-max-width');

const getNextKey = (key) => {
const currentIndex = indexMap[key];
const nextIndex = currentIndex + 1;
const isNotLastIndex = currentIndex < keys.length - 1;
return isNotLastIndex ? keys[nextIndex] : undefined;
return keys[indexMap[key] + 1];
};

@@ -55,10 +51,2 @@

/**
* Get a range based on a single breakpoint key.
* @param {string} key - The breakpoint key.
* @returns {string|Object} - The minimum or a range object based on the provided key.
*/
const only = (key) =>
key !== keys.at(-1) ? between(key, getNextKey(key)) : up(key);
return {

@@ -70,4 +58,3 @@ keys,

between,
only,
};
};

@@ -0,24 +1,65 @@

type UnionToIntersection<U> = (
U extends unknown ? (arg: U) => 0 : never
) extends (arg: infer I) => 0
? I
: never;
/**
* LastInUnion<1 | 2> = 2.
*/
type LastInUnion<U> =
UnionToIntersection<U extends unknown ? (x: U) => 0 : never> extends (
x: infer L
) => 0
? L
: never;
/**
* UnionToTuple<1 | 2> = [1, 2].
*/
export type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never]
? []
: [...UnionToTuple<Exclude<U, Last>>, Last];
type HeadlessTuple<T extends any[]> = T extends [infer _, ...infer Tail]
? Tail
: never;
export type OmitFirst<T> = HeadlessTuple<UnionToTuple<T>>[number];
export type Breakpoints = Record<string, `${string}px`>;
export type ErrorPrefix = `[${string}]: `;
export type Orientation = 'portrait' | 'landscape';
type BreakpointKeys = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
type Min = BreakpointKeys;
declare const DEFAULT_BREAKPOINTS: {
readonly xs: '0px';
readonly sm: '576px';
readonly md: '768px';
readonly lg: '992px';
readonly xl: '1200px';
readonly xxl: '1400px';
};
type Max = Exclude<BreakpointKeys, 'xs'>;
type DefaultBreakpoints = typeof DEFAULT_BREAKPOINTS;
type DefaultBreakpointKeys = keyof DefaultBreakpoints;
interface Options {
breakpoints?: Record<string, `${number}px`>;
errorPrefix?: string;
}
export type Options<T extends Breakpoints> = {
breakpoints?: T;
errorPrefix?: ErrorPrefix;
};
export interface MediaQueries<T = Min, U = Max> {
up: (min: T, orientation?: Orientation) => string;
down: (max: U, orientation?: Orientation) => string;
between: (min: T, max: U, orientation?: Orientation) => string;
only: (key: T, orientation?: Orientation) => string;
interface StyledBreakpointsTheme<Min, Max> {
breakpoints: {
up(min: Min, orientation?: Orientation): string;
down(max: Max, orientation?: Orientation): string;
between(min: Min, max: Max, orientation?: Orientation): string;
only(key: Min, orientation?: Orientation): string;
};
}
export interface StyledBreakpointsTheme<T = MediaQueries> {
breakpoints: T;
}
export function createStyledBreakpointsTheme(options?: Options): any;
export function createStyledBreakpointsTheme<
T extends Breakpoints = DefaultBreakpoints,
Keys extends keyof T = DefaultBreakpointKeys,
KeysWithoutFirst extends OmitFirst<Keys> = OmitFirst<DefaultBreakpointKeys>,
>(options?: Options<T>): StyledBreakpointsTheme<Keys, KeysWithoutFirst>;

@@ -43,69 +43,39 @@ const { createBreakpointsApi } = require('../../shared/create-breakpoints-api');

/**
* Creates a media query for a minimum width breakpoint.
*
* @param {String} min - The minimum breakpoint value.
* @param {String} orientation - Optional orientation value.
* @returns {String} - The media query string.
*/
// Creates a media query for a minimum width breakpoint.
function up(min, orientation) {
return withOrientationOrNot(
orientation,
withMedia(withMinWidth(api.up(min)))
withMedia(withMinWidth(api.up(min))),
orientation
);
}
/**
* Creates a media query for a maximum width breakpoint.
*
* @param {String} max - The maximum breakpoint value.
* @param {String} orientation - Optional orientation value.
* @returns {String} - The media query string.
*/
// Creates a media query for a maximum width breakpoint.
function down(max, orientation) {
return withOrientationOrNot(
orientation,
withMedia(withMaxWidth(api.down(max)))
withMedia(withMaxWidth(api.down(max))),
orientation
);
}
/**
* Creates a media query for a range between two breakpoints.
*
* @param {String} min - The minimum breakpoint value.
* @param {String} max - The maximum breakpoint value.
* @param {String} orientation - Optional orientation value.
* @returns {String} - The media query string.
*/
// Creates a media query for a range between two breakpoints.
function between(min, max, orientation) {
return withOrientationOrNot(
orientation,
withMinAndMaxMedia(api.between(min, max))
withRangeMedia(api.between(min, max)),
orientation
);
}
/**
* Creates a media query for a specific breakpoint or range.
*
* @param {String} key - The breakpoint key.
* @param {String} orientation - Optional orientation value.
* @returns {String} - The media query string.
*/
// Creates a media query for a specific breakpoint or range.
function only(key, orientation) {
return withOrientationOrNot(
orientation,
typeof api.only(key) === 'object'
? withMinAndMaxMedia(api.only(key))
: withMedia(withMinWidth(api.up(key)))
);
const isLastKey = key === api.keys.at(-1);
const mediaQuery = isLastKey
? withMedia(withMinWidth(api.up(key)))
: withRangeMedia(api.between(key, api.getNextKey(key)));
return withOrientationOrNot(mediaQuery, orientation);
}
/**
* Applies orientation if provided or returns the media query.
*
* @param {String} orientation - Optional orientation value.
* @param {String} mediaQuery - The media query string.
* @returns {String} - The media query with or without orientation.
*/
function withOrientationOrNot(orientation, mediaQuery) {
// Applies orientation if provided or returns the media query.
function withOrientationOrNot(mediaQuery, orientation) {
return orientation

@@ -119,38 +89,18 @@ ? withOrientation({

}
};
/**
* @param {String} value - The minimum width value.
* @returns {String} - The media query string.
*/
function withMinWidth(value) {
return `(min-width: ${value})`;
}
function withMinWidth(value) {
return `(min-width: ${value})`;
}
/**
* @param {String} value - The media query string.
* @returns {String} - The media query wrapped with '@media'.
*/
function withMedia(value) {
return `@media ${value}`;
}
function withMedia(value) {
return `@media ${value}`;
}
/**
* @param {String} value - The maximum width value.
* @returns {String} - The media query string.
*/
function withMaxWidth(value) {
return `(max-width: ${value})`;
}
function withMaxWidth(value) {
return `(max-width: ${value})`;
}
/**
* Creates a media query string for a range between minimum and maximum widths.
*
* @param {Object} options - The range options with minimum and maximum values.
* @param {String} options.min - The minimum width value.
* @param {String} options.max - The maximum width value.
* @returns {String} - The media query string for the range.
*/
function withMinAndMaxMedia({ min, max }) {
return `${withMedia(withMinWidth(min))} and ${withMaxWidth(max)}`;
}
};
function withRangeMedia({ min, max }) {
return `${withMedia(withMinWidth(min))} and ${withMaxWidth(max)}`;
}

@@ -6,4 +6,6 @@ const {

exports.withOrientation = ({ mediaQuery, orientation, invariant }) => {
const isValid = orientation === 'portrait' || orientation === 'landscape';
invariant(
orientation === 'portrait' || orientation === 'landscape',
isValid,
`\`${orientation}\` is invalid orientation. Please use \`landscape\` or \`portrait\`.`

@@ -10,0 +12,0 @@ );

@@ -1,3 +0,1 @@

declare module 'styled-breakpoints/use-media-query' {
export function useMediaQuery(query?: string): boolean;
}
export function useMediaQuery(query: string): boolean;

@@ -6,12 +6,16 @@ const { useState, useLayoutEffect, useEffect } = require('react');

exports.useMediaQuery = useMediaQuery;
/**
* Custom hook for handling media queries.
*
* @param {string} [query=''] - The media query to match.
* @param {string} query - The media query to match.
* @returns {boolean} - `true` if the media query matches, otherwise `false`.
*/
const useMediaQuery = (query = '') => {
const [isMatch, setIsMatch] = useState(getMatches(query));
function useMediaQuery(query) {
const [isMatch, setIsMatch] = useState(isBrowser && getMatches(query));
useEnhancedEffect(() => {
if (!isBrowser) return;
let mounted = true;

@@ -28,10 +32,10 @@ const mediaQueryList = window.matchMedia(query.replace(/^@media\s*/, ''));

// https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList#Browser_compatibility
if (mediaQueryList.addListener) {
mediaQueryList.addListener(handleChange);
} else {
mediaQueryList.addEventListener('change', handleChange);
}
const listenerMethod = mediaQueryList.addListener
? 'addListener'
: 'addEventListener';
mediaQueryList[listenerMethod]('change', handleChange);
setIsMatch(mediaQueryList.matches);
// eslint-disable-next-line consistent-return
return () => {

@@ -49,13 +53,6 @@ mounted = false;

return isMatch;
};
}
exports.useMediaQuery = useMediaQuery;
function getMatches(query) {
// Prevents SSR issues
if (typeof window !== 'undefined') {
return window.matchMedia(query).matches;
}
return false;
return window.matchMedia(query).matches;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc