|
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; |
|
} |
|
}; |
|
} |
|
|