mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-17 11:11:25 +00:00
breaking(breakpoint): add breakpointObserver store (#1092)
* breaking: re-name event "on:match" to "on:change" in `Breakpoint.svelte` * feat: add `breakpointObserver` read-only store * refactor: export breakpoint constants from `breakpoints.js`
This commit is contained in:
parent
bbd2cbe62c
commit
5de0d9a357
14 changed files with 180 additions and 101 deletions
80
src/Breakpoint/breakpointObserver.js
Normal file
80
src/Breakpoint/breakpointObserver.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
import { onMount } from "svelte";
|
||||
import { derived, writable } from "svelte/store";
|
||||
import { breakpoints } from "./breakpoints";
|
||||
|
||||
/**
|
||||
* Creates a readable store that returns the current breakpoint size.
|
||||
* It also provides functions for creating derived stores used to do comparisons.
|
||||
*/
|
||||
export function breakpointObserver() {
|
||||
const store = writable(undefined);
|
||||
|
||||
onMount(() => {
|
||||
/** @type {Record<import("./breakpoints").BreakpointSize, MediaQueryList>} */
|
||||
const match = {
|
||||
sm: window.matchMedia(`(max-width: ${breakpoints.md}px)`),
|
||||
md: window.matchMedia(
|
||||
`(min-width: ${breakpoints.md}px) and (max-width: ${breakpoints.lg}px)`
|
||||
),
|
||||
lg: window.matchMedia(
|
||||
`(min-width: ${breakpoints.lg}px) and (max-width: ${breakpoints.xlg}px)`
|
||||
),
|
||||
xlg: window.matchMedia(
|
||||
`(min-width: ${breakpoints.xlg}px) and (max-width: ${breakpoints.max}px)`
|
||||
),
|
||||
max: window.matchMedia(`(min-width: ${breakpoints.max}px)`),
|
||||
};
|
||||
const matchers = Object.entries(match);
|
||||
const sizeByMedia = Object.fromEntries(
|
||||
matchers.map(([size, queryList]) => [queryList.media, size])
|
||||
);
|
||||
|
||||
const size = matchers.find(([size, queryList]) => queryList.matches)[0];
|
||||
store.set(size);
|
||||
|
||||
/** @type {(e: MediaQueryListEvent) => void} */
|
||||
function handleChange({ matches, media }) {
|
||||
const size = sizeByMedia[media];
|
||||
if (matches) store.set(size);
|
||||
}
|
||||
|
||||
matchers.forEach(([size, queryList]) =>
|
||||
queryList.addEventListener("change", handleChange)
|
||||
);
|
||||
|
||||
return () => {
|
||||
matchers.forEach(([size, queryList]) =>
|
||||
queryList.removeEventListener("change", handleChange)
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
subscribe: store.subscribe,
|
||||
|
||||
/**
|
||||
* Returns a store readable store that returns whether the current
|
||||
* breakpoint is smaller than {@link size}.
|
||||
* @param {import("./breakpoints").BreakpointSize} size Size to compare against.
|
||||
*/
|
||||
smallerThan: (size) => {
|
||||
checkSizeValid(size);
|
||||
return derived(store, ($size) => breakpoints[$size] < breakpoints[size]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a store readable store that returns whether the current
|
||||
* breakpoint is larger than {@link size}.
|
||||
* @param {import("./breakpoints").BreakpointSize} size Size to compare against.
|
||||
*/
|
||||
largerThan: (size) => {
|
||||
checkSizeValid(size);
|
||||
return derived(store, ($size) => breakpoints[$size] > breakpoints[size]);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function checkSizeValid(size) {
|
||||
if (size in breakpoints == false)
|
||||
throw new Error(`"${size}" is not a valid breakpoint size.`);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue