Утилиты и пресеты
Утилиты
syncCSSVars(options?) → stop
Синхронизирует все ключи брейкпоинтов с CSS custom properties (1 / 0) на document.documentElement (или на кастомном элементе). Автоматически удаляет свойства для ключей, убранных при изменении конфига.
const stop = state.syncCSSVars({ element: document.body, prefix: '--bp-' })
// → --bp-mobile: 1; --bp-desktop: 0; …
stop() // очистка| Опция | По умолчанию | Описание |
|---|---|---|
element | document.documentElement | Целевой HTML-элемент |
prefix | '--responsive-' | Префикс имени CSS custom property |
emitDOMEvents(target?, options?) → stop
Диспатчит DOM CustomEvent на target при каждом изменении брейкпоинтов:
responsive:change— срабатывает при любом изменении состояния;event.detail— полный снапшот состоянияresponsive:mobile:enter— срабатывает, когдаmobileстановитсяtrueresponsive:mobile:leave— срабатывает, когдаmobileстановитсяfalse
const stop = state.emitDOMEvents(document, { prefix: 'bp:' })
document.addEventListener('bp:change', (e) => console.log(e.detail))
document.addEventListener('bp:mobile:enter', () => initDrawer())
document.addEventListener('bp:desktop:leave', () => destroyDesktopChart())
stop()| Опция | По умолчанию | Описание |
|---|---|---|
prefix | 'responsive:' | Префикс имени кастомного события |
toSignal(key, factory) → Signal
Привязывает ключ брейкпоинта к записываемому сигналу из любой библиотеки сигналов. Сигнал синхронизируется через on().
// @preact/signals-core
import { signal } from '@preact/signals-core'
const isMobile = state.toSignal('mobile', signal)
isMobile.value // реактивный boolean
// Angular signal
import { signal } from '@angular/core'
const isMobile = state.toSignal('mobile', signal)
// Vue ref
import { ref } from 'vue'
const isMobile = state.toSignal('mobile', ref)getMediaQueries() → Record<string, string>
Возвращает сгенерированные строки CSS media query для каждого ключа брейкпоинта.
const mq = state.getMediaQueries()
// { mobile: '(max-width: 600px)', desktop: '(min-width: 961px)' }getState<T>() → T
Возвращает стабильный снапшот текущего состояния. Одна и та же ссылка между изменениями — безопасно для React useSyncExternalStore.
getOrder() → string[]
Возвращает настроенный массив порядка брейкпоинтов (либо пустой массив, если не задан).
hydrate(initialState): гидратация SSR
Устанавливает начальное состояние из серверного снапшота, чтобы предотвратить сдвиг разметки. Обновляет только те ключи, что есть в текущем конфиге.
state.hydrate({ mobile: false, tablet: false, desktop: true })destroy()
Удаляет все слушатели matchMedia / ResizeObserver, очищает всех подписчиков и отменяет любой ожидающий таймер debounce.
toMediaQueryString(conditions): автономная утилита
Конвертирует MediaQueryConfig в строку CSS media query. Полезно для CSS-in-JS или отладки.
import { toMediaQueryString } from 'responsive-media'
toMediaQueryString([
{ type: 'min-width', value: 768 },
{ type: 'max-width', value: 1024 },
])
// → "(min-width: 768px) and (max-width: 1024px)"
toMediaQueryString([
[{ type: 'max-width', value: 600 }],
[{ type: 'orientation', value: 'portrait' }],
])
// → "(max-width: 600px), (orientation: portrait)"match(state, map, fallback?): автономная утилита
Возвращает первое значение в map, чей ключ равен true в state. Приоритет соответствует порядку вставки в map.
import { match } from 'responsive-media'
import { responsiveState } from 'responsive-media'
const cols = match(responsiveState.proxy, { mobile: 1, tablet: 2, desktop: 4 })
const View = match(responsiveState.proxy, { mobile: MobileMenu, desktop: DesktopNav })
const label = match(responsiveState.proxy, { sm: 'Compact', lg: 'Full' }, 'Default')subscribeMediaQuery(query, callback): автономная утилита
Низкоуровневая реактивная обёртка вокруг одной сырой строки CSS media query. Фреймворк-агностична — адаптеры Vue и React используют её внутри себя.
import { subscribeMediaQuery } from 'responsive-media'
const off = subscribeMediaQuery('(prefers-color-scheme: dark)', (matches) => {
document.body.classList.toggle('dark', matches)
})
off() // очисткаПресеты
Импортируйте из responsive-media/presets либо из основной точки входа.
ResponsiveConfig (по умолчанию)
| Ключ | Диапазон |
|---|---|
mobile | ≤ 600px |
tablet | 601 – 960px |
desktop | ≥ 961px |
TailwindPreset + TailwindOrder
Взаимоисключающие брейкпоинты Tailwind CSS v3/v4:
| Ключ | Диапазон |
|---|---|
xs | ≤ 639px |
sm | 640 – 767px |
md | 768 – 1023px |
lg | 1024 – 1279px |
xl | 1280 – 1535px |
2xl | ≥ 1536px |
import { createResponsiveState, TailwindPreset, TailwindOrder } from 'responsive-media'
const state = createResponsiveState(TailwindPreset, { order: [...TailwindOrder] })BootstrapPreset + BootstrapOrder
Взаимоисключающие брейкпоинты Bootstrap 5:
| Ключ | Диапазон |
|---|---|
xs | ≤ 575px |
sm | 576 – 767px |
md | 768 – 991px |
lg | 992 – 1199px |
xl | 1200 – 1399px |
xxl | ≥ 1400px |
import { createResponsiveState, BootstrapPreset, BootstrapOrder } from 'responsive-media'
const state = createResponsiveState(BootstrapPreset, { order: [...BootstrapOrder] })AccessibilityPreset
Медиа-запросы пользовательских предпочтений. Несколько ключей могут быть true одновременно.
| Ключ | Совпадает, когда … |
|---|---|
dark | prefers-color-scheme: dark |
light | prefers-color-scheme: light |
reducedMotion | prefers-reduced-motion: reduce |
highContrast | prefers-contrast: more |
lowContrast | prefers-contrast: less |
noHover | hover: none (сенсорные устройства / стилус) |
coarsePointer | pointer: coarse (ввод пальцем) |
forcedColors | forced-colors: active (Windows HCM) |
print | тип медиа print |
import { createResponsiveState, AccessibilityPreset } from 'responsive-media'
const a11y = createResponsiveState(AccessibilityPreset)
a11y.onEnter('dark', () => applyDarkTheme())
a11y.onEnter('reducedMotion', () => disableAnimations())
a11y.onEnter('print', () => hideNonPrintable())