summaryrefslogtreecommitdiff
path: root/shared/components/src/stores/media-query.ts
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /shared/components/src/stores/media-query.ts
init commit
Diffstat (limited to 'shared/components/src/stores/media-query.ts')
-rw-r--r--shared/components/src/stores/media-query.ts63
1 files changed, 63 insertions, 0 deletions
diff --git a/shared/components/src/stores/media-query.ts b/shared/components/src/stores/media-query.ts
new file mode 100644
index 0000000..83cc055
--- /dev/null
+++ b/shared/components/src/stores/media-query.ts
@@ -0,0 +1,63 @@
+// Based on https://github.com/cibernox/svelte-media
+import { readable } from 'svelte/store';
+import { ArtworkConfig } from '@amp/web-app-components/config/components/artwork';
+import { getMediaConditions } from '@amp/web-app-components/src/utils/getMediaConditions';
+
+const { BREAKPOINTS } = ArtworkConfig.get();
+const mqConditions = getMediaConditions(BREAKPOINTS);
+
+const DEFAULT_SETTING = 'medium';
+
+/**
+ * Filters media query results and outputs the breakpoint name with a matching media query.
+ *
+ * @param {Object} mqls media query configurations (pulled from getMediaConditions())
+ * @returns {String|undefined} breakpoint string that matches current media query
+ */
+function calculateMediaQuery(mqls: Record<string, MediaQueryList>): string {
+ return Object.entries(mqls)
+ .filter(([_, query]) => query.matches)
+ .map(([name, _]) => name)[0];
+}
+
+/**
+ * This function allows to build a store that tracks which of the given media query conditions matches.
+ * @param initialValue The inital value for the store. It only bears importance in server side rendering
+ * as it will update immediately in the browser
+ * @param mediaQueryConditions The dictionary with the media query names and the MQ condition to match against.
+ * @returns Svelte.Store<string> The name of the matching media query
+ */
+export function buildMediaQueryStore(
+ initialValue: string,
+ mediaQueryConditions: Record<string, string> = mqConditions,
+) {
+ return readable(initialValue, (set) => {
+ if (
+ typeof window === 'undefined' ||
+ typeof matchMedia === 'undefined'
+ ) {
+ set(initialValue);
+ return;
+ }
+
+ let mqls = {};
+ let updateMediaQuery = () => set(calculateMediaQuery(mqls));
+
+ for (const key in mediaQueryConditions) {
+ mqls[key] = window.matchMedia(mediaQueryConditions[key]);
+ // `addListener` is deprecated but should still be used for compatibility with more browsers.
+ mqls[key].addListener(updateMediaQuery);
+ }
+
+ updateMediaQuery();
+
+ return function (): void {
+ for (let key in mqls) {
+ // `removeListener` is deprecated but should still be used for compatibility with more browsers.
+ mqls[key].removeListener(updateMediaQuery);
+ }
+ };
+ });
+}
+
+export const mediaQueries = buildMediaQueryStore(DEFAULT_SETTING, mqConditions);