@wordpress/block-editor
Version:
137 lines (107 loc) • 4.05 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = useSimulatedMediaQuery;
var _lodash = require("lodash");
var _cssMediaquery = require("css-mediaquery");
var _element = require("@wordpress/element");
var _url = require("@wordpress/url");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
const ENABLED_MEDIA_QUERY = '(min-width:0px)';
const DISABLED_MEDIA_QUERY = '(min-width:999999px)';
const VALID_MEDIA_QUERY_REGEX = /\((min|max)-width:[^\(]*?\)/g;
function getStyleSheetsThatMatchHostname() {
var _window$document$styl, _window, _window$document;
if (typeof window === 'undefined') {
return [];
}
return (0, _lodash.filter)((_window$document$styl = (_window = window) === null || _window === void 0 ? void 0 : (_window$document = _window.document) === null || _window$document === void 0 ? void 0 : _window$document.styleSheets) !== null && _window$document$styl !== void 0 ? _window$document$styl : [], styleSheet => {
if (!styleSheet.href) {
return false;
}
return (0, _url.getProtocol)(styleSheet.href) === window.location.protocol && (0, _url.getAuthority)(styleSheet.href) === window.location.host;
});
}
function isReplaceableMediaRule(rule) {
if (!rule.media) {
return false;
} // Need to use "media.mediaText" instead of "conditionText" for IE support.
return !!rule.media.mediaText.match(VALID_MEDIA_QUERY_REGEX);
}
function replaceRule(styleSheet, newRuleText, index) {
styleSheet.deleteRule(index);
styleSheet.insertRule(newRuleText, index);
}
function replaceMediaQueryWithWidthEvaluation(ruleText, widthValue) {
return ruleText.replace(VALID_MEDIA_QUERY_REGEX, matchedSubstring => {
if ((0, _cssMediaquery.match)(matchedSubstring, {
type: 'screen',
width: widthValue
})) {
return ENABLED_MEDIA_QUERY;
}
return DISABLED_MEDIA_QUERY;
});
}
/**
* Function that manipulates media queries from stylesheets to simulate a given
* viewport width.
*
* @param {string} marker CSS selector string defining start and end of
* manipulable styles.
* @param {number?} width Viewport width to simulate. If provided null, the
* stylesheets will not be modified.
*/
function useSimulatedMediaQuery(marker, width) {
(0, _element.useEffect)(() => {
if (!width) {
return;
}
const styleSheets = getStyleSheetsThatMatchHostname();
const originalStyles = [];
styleSheets.forEach((styleSheet, styleSheetIndex) => {
let relevantSection = false;
for (let ruleIndex = 0; ruleIndex < styleSheet.cssRules.length; ++ruleIndex) {
const rule = styleSheet.cssRules[ruleIndex];
if (rule.type !== window.CSSRule.STYLE_RULE && rule.type !== window.CSSRule.MEDIA_RULE) {
continue;
}
if (!relevantSection && !!rule.cssText.match(new RegExp(`#start-${marker}`))) {
relevantSection = true;
}
if (relevantSection && !!rule.cssText.match(new RegExp(`#end-${marker}`))) {
relevantSection = false;
}
if (!relevantSection || !isReplaceableMediaRule(rule)) {
continue;
}
const ruleText = rule.cssText;
if (!originalStyles[styleSheetIndex]) {
originalStyles[styleSheetIndex] = [];
}
originalStyles[styleSheetIndex][ruleIndex] = ruleText;
replaceRule(styleSheet, replaceMediaQueryWithWidthEvaluation(ruleText, width), ruleIndex);
}
});
return () => {
originalStyles.forEach((rulesCollection, styleSheetIndex) => {
if (!rulesCollection) {
return;
}
for (let ruleIndex = 0; ruleIndex < rulesCollection.length; ++ruleIndex) {
const originalRuleText = rulesCollection[ruleIndex];
if (originalRuleText) {
replaceRule(styleSheets[styleSheetIndex], originalRuleText, ruleIndex);
}
}
});
};
}, [width]);
}
//# sourceMappingURL=index.js.map