|
import { onDestroy } from "svelte";
|
|
import { writable } from "svelte/store";
|
|
|
|
const sizes = {
|
|
sm: "(min-width: 640px)",
|
|
md: "(min-width: 768px)",
|
|
lg: "(min-width: 1024px)",
|
|
xl: "(min-width: 1280px)",
|
|
"2xl": "(min-width: 1536px)"
|
|
} as const;
|
|
|
|
const _default = {
|
|
sm: false,
|
|
md: false,
|
|
lg: false,
|
|
xl: false,
|
|
"2xl": false
|
|
};
|
|
|
|
export const media_query = () => {
|
|
const { subscribe, update } = writable(_default);
|
|
|
|
const listeners: {
|
|
[key: string]: [MediaQueryList, (ev: MediaQueryListEvent) => any];
|
|
} = {};
|
|
const onChange = (key: string) => () =>
|
|
update((s) => ({ ...s, [key]: !!listeners[key][0].matches }));
|
|
|
|
if (typeof window !== "undefined") {
|
|
for (const key in sizes) {
|
|
const mql = window.matchMedia(sizes[key as keyof typeof sizes]);
|
|
const listener = onChange(key);
|
|
|
|
mql.addEventListener("change", listener);
|
|
|
|
listeners[key] = [mql, listener];
|
|
}
|
|
|
|
onDestroy(() => {
|
|
for (const key in listeners) {
|
|
const [_mql, _listener] = listeners[key];
|
|
_mql.removeEventListener("change", _listener);
|
|
}
|
|
});
|
|
}
|
|
|
|
return { subscribe };
|
|
};
|
|
|
|
import slugify from "@sindresorhus/slugify";
|
|
|
|
export function make_slug_processor() {
|
|
const seen_slugs = new Map();
|
|
|
|
return function (name: string) {
|
|
const slug = slugify(name, { separator: "-", lowercase: true });
|
|
let count = seen_slugs.get(slug);
|
|
if (count) {
|
|
seen_slugs.set(slug, count + 1);
|
|
return `${slug}-${count + 1}`;
|
|
} else {
|
|
seen_slugs.set(slug, 1);
|
|
return slug;
|
|
}
|
|
};
|
|
}
|
|
|