@enact/ui
Version:
A collection of simplified unstyled cross-platform UI components for Enact
243 lines (231 loc) • 9.03 kB
JavaScript
;
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
var fontMap = {};
var currentLocale = null;
// Generate a single font-face rule
var buildFont = function buildFont(config) {
if (!config && !config.name) {
return '';
}
var strOut = '@font-face { \n' + " font-family: \"".concat(config.name, "\";\n");
if (config.weight) {
strOut += " font-weight: ".concat(config.weight, ";\n");
}
if (config.localName) {
// Accept a string or an array. If it's a string convert it into an array
if (typeof config.localName === 'string') {
config.localName = [config.localName];
}
// Take our array and update each of its elements to be CSS "local()" strings
config.localName = config.localName.map(function (f) {
return "local(\"".concat(f, "\")");
});
// Join all our strings together with a comma, so it's a valid CSS `src` rule
strOut += " src: ".concat(config.localName.join(', '), ";\n");
}
if (config.unicodeRange) {
strOut += " unicode-range: ".concat(config.unicodeRange, ";\n");
}
strOut += '} \n';
return strOut;
};
// Generate a collection of font-face rules, in multiple font-variants
var buildFontSet = function buildFontSet(fontName, fonts, strLang, bitDefault) {
var strOut = '',
name = bitDefault ? fontName : fontName + ' ' + strLang;
if (fonts[strLang].regular) {
// Build Regular
strOut += buildFont({
name: name,
localName: fonts[strLang].regular,
unicodeRange: fonts[strLang].unicodeRange
});
// Build Light
strOut += buildFont({
name: name,
localName: fonts[strLang].light || fonts[strLang].regular,
weight: 300,
unicodeRange: fonts[strLang].unicodeRange
});
// Build SemiBold
strOut += buildFont({
name: name,
localName: fonts[strLang].semibold || fonts[strLang].bold || fonts[strLang].regular,
weight: 600,
unicodeRange: fonts[strLang].unicodeRange
});
// Build Bold
strOut += buildFont({
name: name,
localName: fonts[strLang].bold || fonts[strLang].regular,
weight: 700,
unicodeRange: fonts[strLang].unicodeRange
});
}
return strOut;
};
var buildFontDefinitionCss = function buildFontDefinitionCss(locale, buildOverrides) {
var matchLang = locale.match(/\b([a-z]{2})\b/),
language = matchLang && matchLang[1],
matchScript = locale.match(/\b([a-z]{4})\b/i),
script = matchScript && matchScript[1],
matchReg = locale.match(/\b([A-Z]{2}|[0-9]{3})\b/),
region = matchReg && matchReg[1];
var fontDefinitionCss = '';
// Build all the fonts so they could be explicitly called
for (var fontName in fontMap) {
var fonts = fontMap[fontName];
for (var lang in fonts) {
if (!buildOverrides) {
fontDefinitionCss += buildFontSet(fontName, fonts, lang);
} else {
// Set up the override for locale-specific font.
// la = language, sc = script, re = region; `la-RE` or `zh-Hans-HK`
var _lang$split = lang.split('-'),
_lang$split2 = _slicedToArray(_lang$split, 3),
la = _lang$split2[0],
sc = _lang$split2[1],
re = _lang$split2[2];
// if script is not specified, fall back to second part representing region
if (!re && sc && sc.length === 2) {
re = sc;
sc = null;
}
var matchesRegion = re ? re === region : true;
var matchesScript = sc ? sc === script : true;
if (la === language && matchesRegion && matchesScript) {
fontDefinitionCss += buildFontSet(fontName, fonts, lang, true);
}
}
}
}
return fontDefinitionCss;
};
var insertFontDefinitionCss = function insertFontDefinitionCss(styleId, fontDefinitionCss) {
if (typeof document !== 'undefined') {
// Normal execution in a browser window
var styleElem = document.getElementById(styleId);
if (!styleElem) {
styleElem = document.createElement('style');
styleElem.setAttribute('id', styleId);
styleElem.setAttribute('type', 'text/css');
document.head.appendChild(styleElem);
}
styleElem.innerHTML = fontDefinitionCss;
} else {
var tag = "<style type=\"text/css\" id=\"".concat(styleId, "\">").concat(fontDefinitionCss, "</style>");
// We're rendering without the DOM; return the font definition stylesheet element string.
return tag;
}
};
function fontGenerator(locale) {
var styleId = 'localized-fonts';
if (typeof document !== 'undefined' && document.getElementById(styleId)) {
return;
}
return insertFontDefinitionCss(styleId, buildFontDefinitionCss(locale));
}
function fontOverrideGenerator(locale) {
return insertFontDefinitionCss('localized-fonts-override', buildFontDefinitionCss(locale, true));
}
/**
* Generates locale-specific font rules allowing any locale to have its own custom font. Each
* locale-font from the configuration block (defined in this file) is generated at run-time. If the
* locale you're currently in is in the locale-font list an additional `@font-face` rule will be
* generated that will override the standard font.
*
* In addition to the standard override-font being generated, named region-specific fonts are also
* generated. This lets you incorporate language specific fonts when you're outside of one of those
* regions; useful in a language list context where you want the name of each language to be
* represented by that language's designated font.
*
* Below is example genarated-output of the Urdu ("ur") locale-font.
*
* ```css
* @font-face {
* font-family: 'Custom Font ur';
* font-weight: 500;
* src: local('CustomFont_Urdu');
* unicode-range: U+0600-U+06FF, U+FE70-U+FEFE, U+FB50-U+FDFF;
* }
* @font-face {
* font-family: 'Custom Font ur Bold';
* font-weight: 700;
* src: local('CustomFont_Urdu');
* unicode-range: U+0600-U+06FF, U+FE70-U+FEFE, U+FB50-U+FDFF;
* }
* @font-face {
* font-family: 'Custom Font ur Light';
* font-weight: 300;
* src: local('CustomFont_Urdu');
* unicode-range: U+0600-U+06FF, U+FE70-U+FEFE, U+FB50-U+FDFF;
* }
* ```
*
* @param {String} locale Locale string in the format
* @returns {String} An HTML fragment of the `<style>` when prerendering
*
* @public
*/
function generateFontRules(locale) {
if (!locale || locale === currentLocale) {
return;
}
currentLocale = locale;
return fontGenerator(locale);
}
function generateFontOverrideRules(locale) {
if (!locale) {
return;
}
return fontOverrideGenerator(locale);
}
/**
* Adds a localed font to the font map
*
* ```
* addLocalizedFont('My Theme Font', {
* 'ur': {
* regular: 'My Theme Urdu',
* unicodeRange:
* 'U+600-6FF,' +
* 'U+FE70-FEFE,' +
* 'U+FB50-FDFF'
* }
* })
* ```
*
* @param {String} name Name of the font
* @param {Object} fonts Object mapping font names and unicode ranges to locales
*
* @public
*/
function addLocalizedFont(name, fonts) {
fontMap[name] = fonts;
if (currentLocale) {
fontGenerator(currentLocale);
}
}
/**
* Removes a localized font from the font map
*
* @param {String} name Name of the font
*
* @public
*/
function removeLocalizedFont(name) {
delete fontMap[name];
if (currentLocale) {
fontGenerator(currentLocale);
}
}
module.exports = generateFontRules;
module.exports.generateFontRules = generateFontRules;
module.exports.generateFontOverrideRules = generateFontOverrideRules;
module.exports.addLocalizedFont = addLocalizedFont;
module.exports.removeLocalizedFont = removeLocalizedFont;