import { __assign } from "tslib"; import { GLOBAL_STYLESHEET_KEY, SHADOW_DOM_STYLESHEET_SETTING } from './shadowConfig'; export var InjectionMode = { /** * Avoids style injection, use getRules() to read the styles. */ none: 0, /** * Inserts rules using the insertRule api. */ insertNode: 1, /** * Appends rules using appendChild. */ appendChild: 2, }; export var STYLESHEET_SETTING = '__stylesheet__'; /** * MSIE 11 doesn't cascade styles based on DOM ordering, but rather on the order that each style node * is created. As such, to maintain consistent priority, IE11 should reuse a single style node. */ var REUSE_STYLE_NODE = typeof navigator !== 'undefined' && /rv:11.0/.test(navigator.userAgent); var _global = {}; // Grab window. try { // Why the cast? // if compiled/type checked in same program with `@fluentui/font-icons-mdl2` which extends `Window` on global // ( check packages/font-icons-mdl2/src/index.ts ) the definitions don't match! Thus the need of this extra assertion _global = (window || {}); } catch (_a) { /* leave as blank object */ } var _stylesheet; /** * Represents the state of styles registered in the page. Abstracts * the surface for adding styles to the stylesheet, exposes helpers * for reading the styles registered in server rendered scenarios. * * @public */ var Stylesheet = /** @class */ (function () { function Stylesheet(config, serializedStylesheet) { var _a, _b, _c, _d, _e, _f; this._rules = []; this._preservedRules = []; this._counter = 0; this._keyToClassName = {}; this._onInsertRuleCallbacks = []; this._onResetCallbacks = []; this._classNameToArgs = {}; // If there is no document we won't have an element to inject into. this._config = __assign({ injectionMode: typeof document === 'undefined' ? InjectionMode.none : InjectionMode.insertNode, defaultPrefix: 'css', namespace: undefined, cspSettings: undefined }, config); this._classNameToArgs = (_a = serializedStylesheet === null || serializedStylesheet === void 0 ? void 0 : serializedStylesheet.classNameToArgs) !== null && _a !== void 0 ? _a : this._classNameToArgs; this._counter = (_b = serializedStylesheet === null || serializedStylesheet === void 0 ? void 0 : serializedStylesheet.counter) !== null && _b !== void 0 ? _b : this._counter; this._keyToClassName = (_d = (_c = this._config.classNameCache) !== null && _c !== void 0 ? _c : serializedStylesheet === null || serializedStylesheet === void 0 ? void 0 : serializedStylesheet.keyToClassName) !== null && _d !== void 0 ? _d : this._keyToClassName; this._preservedRules = (_e = serializedStylesheet === null || serializedStylesheet === void 0 ? void 0 : serializedStylesheet.preservedRules) !== null && _e !== void 0 ? _e : this._preservedRules; this._rules = (_f = serializedStylesheet === null || serializedStylesheet === void 0 ? void 0 : serializedStylesheet.rules) !== null && _f !== void 0 ? _f : this._rules; } /** * Gets the singleton instance. */ Stylesheet.getInstance = function (shadowConfig) { _stylesheet = _global[STYLESHEET_SETTING]; if (_global[SHADOW_DOM_STYLESHEET_SETTING]) { return _global[SHADOW_DOM_STYLESHEET_SETTING].getInstance(shadowConfig); } if (!_stylesheet || (_stylesheet._lastStyleElement && _stylesheet._lastStyleElement.ownerDocument !== document)) { var fabricConfig = (_global === null || _global === void 0 ? void 0 : _global.FabricConfig) || {}; var stylesheet = new Stylesheet(fabricConfig.mergeStyles, fabricConfig.serializedStylesheet); _stylesheet = stylesheet; _global[STYLESHEET_SETTING] = stylesheet; } return _stylesheet; }; /** * Serializes the Stylesheet instance into a format which allows rehydration on creation. * @returns string representation of `ISerializedStylesheet` interface. */ Stylesheet.prototype.serialize = function () { return JSON.stringify({ classNameToArgs: this._classNameToArgs, counter: this._counter, keyToClassName: this._keyToClassName, preservedRules: this._preservedRules, rules: this._rules, }); }; /** * Configures the stylesheet. */ Stylesheet.prototype.setConfig = function (config) { this._config = __assign(__assign({}, this._config), config); }; /** * Configures a reset callback. * * @param callback - A callback which will be called when the Stylesheet is reset. * @returns function which when called un-registers provided callback. */ Stylesheet.prototype.onReset = function (callback) { var _this = this; this._onResetCallbacks.push(callback); return function () { _this._onResetCallbacks = _this._onResetCallbacks.filter(function (cb) { return cb !== callback; }); }; }; /** * Configures an insert rule callback. * * @param callback - A callback which will be called when a rule is inserted. * @returns function which when called un-registers provided callback. */ Stylesheet.prototype.onInsertRule = function (callback) { var _this = this; this._onInsertRuleCallbacks.push(callback); return function () { _this._onInsertRuleCallbacks = _this._onInsertRuleCallbacks.filter(function (cb) { return cb !== callback; }); }; }; /** * Generates a unique classname. * * @param displayName - Optional value to use as a prefix. */ Stylesheet.prototype.getClassName = function (displayName) { var namespace = this._config.namespace; var prefix = displayName || this._config.defaultPrefix; return "".concat(namespace ? namespace + '-' : '').concat(prefix, "-").concat(this._counter++); }; /** * Used internally to cache information about a class which was * registered with the stylesheet. */ Stylesheet.prototype.cacheClassName = function (className, key, args, rules) { this._keyToClassName[this._getCacheKey(key)] = className; this._classNameToArgs[className] = { args: args, rules: rules, }; }; /** * Gets the appropriate classname given a key which was previously * registered using cacheClassName. */ Stylesheet.prototype.classNameFromKey = function (key) { return this._keyToClassName[this._getCacheKey(key)]; }; /** * Gets all classnames cache with the stylesheet. */ Stylesheet.prototype.getClassNameCache = function () { return this._keyToClassName; }; /** * Gets the arguments associated with a given classname which was * previously registered using cacheClassName. */ Stylesheet.prototype.argsFromClassName = function (className) { var entry = this._classNameToArgs[className]; return entry && entry.args; }; /** * Gets the rules associated with a given classname which was * previously registered using cacheClassName. */ Stylesheet.prototype.insertedRulesFromClassName = function (className) { var entry = this._classNameToArgs[className]; return entry && entry.rules; }; /** * Inserts a css rule into the stylesheet. * @param preserve - Preserves the rule beyond a reset boundary. */ Stylesheet.prototype.insertRule = function (rule, preserve, stylesheetKey) { if (stylesheetKey === void 0) { stylesheetKey = GLOBAL_STYLESHEET_KEY; } var injectionMode = this._config.injectionMode; var element = injectionMode !== InjectionMode.none ? this._getStyleElement() : undefined; if (preserve) { this._preservedRules.push(rule); } if (element) { switch (injectionMode) { case InjectionMode.insertNode: this._insertRuleIntoSheet(element.sheet, rule); break; case InjectionMode.appendChild: element.appendChild(document.createTextNode(rule)); break; } } else { this._rules.push(rule); } // eslint-disable-next-line deprecation/deprecation if (this._config.onInsertRule) { // eslint-disable-next-line deprecation/deprecation this._config.onInsertRule(rule); } this._onInsertRuleCallbacks.forEach(function (callback) { return callback({ key: stylesheetKey, sheet: (element ? element.sheet : undefined), rule: rule }); }); }; /** * Gets all rules registered with the stylesheet; only valid when * using InsertionMode.none. */ Stylesheet.prototype.getRules = function (includePreservedRules) { return (includePreservedRules ? this._preservedRules.join('') : '') + this._rules.join(''); }; /** * Resets the internal state of the stylesheet. Only used in server * rendered scenarios where we're using InsertionMode.none. */ Stylesheet.prototype.reset = function () { this._rules = []; this._counter = 0; this._classNameToArgs = {}; this._keyToClassName = {}; this._onResetCallbacks.forEach(function (callback) { return callback(); }); }; // Forces the regeneration of incoming styles without totally resetting the stylesheet. Stylesheet.prototype.resetKeys = function () { this._keyToClassName = {}; }; Stylesheet.prototype._createStyleElement = function () { var _a; var doc = ((_a = this._config.window) === null || _a === void 0 ? void 0 : _a.document) || document; var head = doc.head; var styleElement = doc.createElement('style'); var nodeToInsertBefore = null; styleElement.setAttribute('data-merge-styles', 'true'); var cspSettings = this._config.cspSettings; if (cspSettings) { if (cspSettings.nonce) { styleElement.setAttribute('nonce', cspSettings.nonce); } } if (this._lastStyleElement) { // If the `nextElementSibling` is null, then the insertBefore will act as a regular append. // https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore#Syntax nodeToInsertBefore = this._lastStyleElement.nextElementSibling; } else { var placeholderStyleTag = this._findPlaceholderStyleTag(); if (placeholderStyleTag) { nodeToInsertBefore = placeholderStyleTag.nextElementSibling; } else { nodeToInsertBefore = head.childNodes[0]; } } head.insertBefore(styleElement, head.contains(nodeToInsertBefore) ? nodeToInsertBefore : null); this._lastStyleElement = styleElement; return styleElement; }; Stylesheet.prototype._insertRuleIntoSheet = function (sheet, rule) { if (!sheet) { return false; } try { sheet.insertRule(rule, sheet.cssRules.length); return true; } catch (e) { // The browser will throw exceptions on unsupported rules (such as a moz prefix in webkit.) // We need to swallow the exceptions for this scenario, otherwise we'd need to filter // which could be slower and bulkier. } return false; }; Stylesheet.prototype._getCacheKey = function (key) { return key; }; Stylesheet.prototype._getStyleElement = function () { var _this = this; if (!this._styleElement) { this._styleElement = this._createStyleElement(); if (!REUSE_STYLE_NODE) { // Reset the style element on the next frame. var win = this._config.window || window; win.requestAnimationFrame(function () { _this._styleElement = undefined; }); } } return this._styleElement; }; Stylesheet.prototype._findPlaceholderStyleTag = function () { var head = document.head; if (head) { return head.querySelector('style[data-merge-styles]'); } return null; }; return Stylesheet; }()); export { Stylesheet }; //# sourceMappingURL=Stylesheet.js.map