@cwist/vue-match-media
Version:
React to media query changes in your Vue 3 application (useful for adaptive design).
100 lines (99 loc) • 4.2 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVueMatchMediaPlugin = void 0;
var vue_1 = require("vue");
var useApi_1 = require("./useApi");
function isNumberWithUnit(v) {
return typeof v === 'string' && !!v.match(/^\d+(?:r?em|px)$/);
}
function valueWithUnit(v) {
if ((typeof v === 'number' && !isNaN(v)) ||
(typeof v === 'string' && v.match(/^\d+(?:\.\d+)?$/))) {
return v + "px";
}
else if (typeof v === 'string') {
return v;
}
throw new TypeError('Unknown unit value.');
}
function pascalToKebab(str) {
return str.replace(/[\w]([A-Z])/g, function (m) { return m[0] + '-' + m[1]; }).toLowerCase();
}
function populateRules(breakpoint) {
var rules = {};
if (typeof breakpoint === 'number' || isNumberWithUnit(breakpoint)) {
rules.minWidth = breakpoint;
}
else if (breakpoint instanceof Array &&
breakpoint.length === 2) {
var _a = breakpoint, minWidth = _a[0], maxWidth = _a[1];
if (typeof minWidth === 'number' || isNumberWithUnit(minWidth)) {
rules.minWidth = minWidth;
}
if (typeof maxWidth === 'number' || isNumberWithUnit(maxWidth)) {
rules.maxWidth = maxWidth;
}
}
else if (typeof breakpoint === 'object') {
rules = __assign(__assign({}, rules), breakpoint);
}
return rules;
}
function createVueMatchMediaPlugin(options) {
return {
options: options,
install: function (app) {
if (options && options.breakpoints) {
var breakpoints_1 = options.breakpoints;
var keys = Object.keys(breakpoints_1);
var computedBreakpoints_1 = keys.reduce(function (acc, k) {
var rules = populateRules((typeof breakpoints_1[k] === 'object' &&
breakpoints_1[k].breakpoint) ||
breakpoints_1[k]);
acc[k] = Object.keys(rules)
.map(function (r) { return "(" + pascalToKebab(r) + ": " + valueWithUnit(rules[r]) + ")"; })
.join(' and ');
return acc;
}, {});
var matchMediaObservable_1 = vue_1.reactive(keys.reduce(function (acc, k) {
// SSR
if (typeof window === 'undefined') {
if (typeof breakpoints_1[k]
.defaultValue === 'undefined') {
throw new Error("In order to use this plugin with SSR, you must provide a default value for every breakpoint (defaultValue is missing for breakpoint '" + k + "')");
}
acc[k] =
breakpoints_1[k].defaultValue || false;
}
// Client
else {
var mq = window.matchMedia(computedBreakpoints_1[k]);
// Using the deprecated addListener instead of addEventListener
// due to the lack of support in Safari
mq.addListener(function (e) {
matchMediaObservable_1[k] = e.matches;
});
acc[k] = mq.matches;
}
return acc;
}, {}));
app.config.globalProperties.$matchMedia = matchMediaObservable_1;
app.provide(useApi_1.matchMediaKey, matchMediaObservable_1);
}
},
};
}
exports.createVueMatchMediaPlugin = createVueMatchMediaPlugin;
var useApi_2 = require("./useApi");
Object.defineProperty(exports, "useMatchMedia", { enumerable: true, get: function () { return useApi_2.useMatchMedia; } });