react-native-web-internals
Version:
React Native for Web
293 lines (292 loc) • 11.4 kB
JavaScript
import { simpleHash } from "@tamagui/simple-hash";
import createReactDOMStyle from "./createReactDOMStyle.mjs";
import hyphenateStyleName from "./hyphenateStyleName.mjs";
import normalizeValueWithProperty from "./normalizeValueWithProperty.mjs";
const cache = /* @__PURE__ */new Map(),
emptyObject = {},
classicGroup = 1,
atomicGroup = 2.2,
customGroup = {
borderColor: 2,
borderRadius: 2,
borderStyle: 2,
borderWidth: 2,
display: 2,
flex: 2,
margin: 2,
overflow: 2,
overscrollBehavior: 2,
padding: 2,
marginHorizontal: 2.1,
marginVertical: 2.1,
paddingHorizontal: 2.1,
paddingVertical: 2.1
},
borderTopLeftRadius = "borderTopLeftRadius",
borderTopRightRadius = "borderTopRightRadius",
borderBottomLeftRadius = "borderBottomLeftRadius",
borderBottomRightRadius = "borderBottomRightRadius",
borderLeftColor = "borderLeftColor",
borderLeftStyle = "borderLeftStyle",
borderLeftWidth = "borderLeftWidth",
borderRightColor = "borderRightColor",
borderRightStyle = "borderRightStyle",
borderRightWidth = "borderRightWidth",
right = "right",
marginLeft = "marginLeft",
marginRight = "marginRight",
paddingLeft = "paddingLeft",
paddingRight = "paddingRight",
left = "left",
PROPERTIES_FLIP = {
[borderTopLeftRadius]: borderTopRightRadius,
[borderTopRightRadius]: borderTopLeftRadius,
[borderBottomLeftRadius]: borderBottomRightRadius,
[borderBottomRightRadius]: borderBottomLeftRadius,
[borderLeftColor]: borderRightColor,
[borderLeftStyle]: borderRightStyle,
[borderLeftWidth]: borderRightWidth,
[borderRightColor]: borderLeftColor,
[borderRightStyle]: borderLeftStyle,
[borderRightWidth]: borderLeftWidth,
[left]: right,
[marginLeft]: marginRight,
[marginRight]: marginLeft,
[paddingLeft]: paddingRight,
[paddingRight]: paddingLeft,
[right]: left
},
PROPERTIES_I18N = {
borderTopStartRadius: borderTopLeftRadius,
borderTopEndRadius: borderTopRightRadius,
borderBottomStartRadius: borderBottomLeftRadius,
borderBottomEndRadius: borderBottomRightRadius,
borderStartColor: borderLeftColor,
borderStartStyle: borderLeftStyle,
borderStartWidth: borderLeftWidth,
borderEndColor: borderRightColor,
borderEndStyle: borderRightStyle,
borderEndWidth: borderRightWidth,
end: right,
marginStart: marginLeft,
marginEnd: marginRight,
paddingStart: paddingLeft,
paddingEnd: paddingRight,
start: left
},
PROPERTIES_VALUE = ["clear", "float", "textAlign"];
function atomic(style) {
const compiledStyle = {
$$css: !0
},
compiledRules = [];
function atomicCompile(prop, value) {
const valueString = stringifyValueWithProperty(value, prop),
cacheKey = prop + valueString,
cachedResult = cache.get(cacheKey);
let identifier;
if (cachedResult != null) identifier = cachedResult[0], compiledRules.push(cachedResult[1]);else {
identifier = createIdentifier("r", prop, value);
const order = customGroup[prop] || atomicGroup,
orderedRules = [createAtomicRules(identifier, prop, value), order];
compiledRules.push(orderedRules), cache.set(cacheKey, [identifier, orderedRules]);
}
return identifier;
}
return Object.keys(style).sort().forEach(prop => {
const value = style[prop];
if (value != null) {
let localizeableValue;
if (PROPERTIES_VALUE.indexOf(prop) > -1) {
const left2 = atomicCompile(prop, "left"),
right2 = atomicCompile(prop, "right");
value === "start" ? localizeableValue = [left2, right2] : value === "end" && (localizeableValue = [right2, left2]);
}
const propPolyfill = PROPERTIES_I18N[prop];
if (propPolyfill != null) {
const ltr = atomicCompile(propPolyfill, value),
rtl = atomicCompile(PROPERTIES_FLIP[propPolyfill], value);
localizeableValue = [ltr, rtl];
}
if (prop === "transitionProperty") {
const values = Array.isArray(value) ? value : [value],
polyfillIndices = [];
for (let i = 0; i < values.length; i++) {
const val = values[i];
typeof val == "string" && PROPERTIES_I18N[val] != null && polyfillIndices.push(i);
}
if (polyfillIndices.length > 0) {
const ltrPolyfillValues = [...values],
rtlPolyfillValues = [...values];
polyfillIndices.forEach(i => {
const ltrVal = ltrPolyfillValues[i];
if (typeof ltrVal == "string") {
const ltrPolyfill = PROPERTIES_I18N[ltrVal],
rtlPolyfill = PROPERTIES_FLIP[ltrPolyfill];
ltrPolyfillValues[i] = ltrPolyfill, rtlPolyfillValues[i] = rtlPolyfill;
const ltr = atomicCompile(prop, ltrPolyfillValues),
rtl = atomicCompile(prop, rtlPolyfillValues);
localizeableValue = [ltr, rtl];
}
});
}
}
localizeableValue == null ? localizeableValue = atomicCompile(prop, value) : compiledStyle.$$css$localize = !0, compiledStyle[prop] = localizeableValue;
}
}), [compiledStyle, compiledRules];
}
function classic(style, name) {
const compiledStyle = {
$$css: !0
},
compiledRules = [],
{
animationKeyframes,
...rest
} = style,
identifier = createIdentifier("css", name, style),
selector = `.${identifier}`;
let animationName;
if (animationKeyframes != null) {
const [animationNames, keyframesRules] = processKeyframesValue(animationKeyframes);
animationName = animationNames.join(","), compiledRules.push(...keyframesRules);
}
const block = createDeclarationBlock({
...rest,
animationName
});
return compiledRules.push(`${selector}${block}`), compiledStyle[identifier] = identifier, [compiledStyle, [[compiledRules, classicGroup]]];
}
function inline(originalStyle, isRTL) {
const style = originalStyle || emptyObject,
frozenProps = {},
nextStyle = {};
for (const originalProp in style) {
const originalValue = style[originalProp];
let prop = originalProp,
value = originalValue;
if (!Object.prototype.hasOwnProperty.call(style, originalProp) || originalValue == null) continue;
PROPERTIES_VALUE.indexOf(originalProp) > -1 && (originalValue === "start" ? value = isRTL ? "right" : "left" : originalValue === "end" && (value = isRTL ? "left" : "right"));
const propPolyfill = PROPERTIES_I18N[originalProp];
if (propPolyfill != null && (prop = isRTL ? PROPERTIES_FLIP[propPolyfill] : propPolyfill), originalProp === "transitionProperty") {
const originalValues = Array.isArray(originalValue) ? originalValue : [originalValue];
originalValues.forEach((val, i) => {
if (typeof val == "string") {
const valuePolyfill = PROPERTIES_I18N[val];
valuePolyfill != null && (originalValues[i] = isRTL ? PROPERTIES_FLIP[valuePolyfill] : valuePolyfill);
}
});
}
frozenProps[prop] || (nextStyle[prop] = value), PROPERTIES_I18N.hasOwnProperty(originalProp) && (frozenProps[prop] = !0);
}
return createReactDOMStyle(nextStyle, !0);
}
function stringifyValueWithProperty(value, property) {
const normalizedValue = normalizeValueWithProperty(value, property);
return typeof normalizedValue != "string" ? JSON.stringify(normalizedValue || "") : normalizedValue;
}
function createAtomicRules(identifier, property, value) {
const rules = [],
selector = `.${identifier}`;
switch (property) {
case "animationKeyframes":
{
const [animationNames, keyframesRules] = processKeyframesValue(value),
block = createDeclarationBlock({
animationName: animationNames.join(",")
});
rules.push(`${selector}${block}`, ...keyframesRules);
break;
}
// Equivalent to using '::placeholder'
case "placeholderTextColor":
{
const block = createDeclarationBlock({
color: value,
opacity: 1
});
rules.push(`${selector}::-webkit-input-placeholder${block}`, `${selector}::-moz-placeholder${block}`, `${selector}:-ms-input-placeholder${block}`, `${selector}::placeholder${block}`);
break;
}
// Polyfill for additional 'pointer-events' values
// See d13f78622b233a0afc0c7a200c0a0792c8ca9e58
case "pointerEvents":
{
let finalValue = value;
if (value === "auto" || value === "box-only") {
if (finalValue = "auto!important", value === "box-only") {
const block2 = createDeclarationBlock({
pointerEvents: "none"
});
rules.push(`${selector}>*${block2}`);
}
} else if ((value === "none" || value === "box-none") && (finalValue = "none!important", value === "box-none")) {
const block2 = createDeclarationBlock({
pointerEvents: "auto"
});
rules.push(`${selector}>*${block2}`);
}
const block = createDeclarationBlock({
pointerEvents: finalValue
});
rules.push(`${selector}${block}`);
break;
}
// Polyfill for draft spec
// https://drafts.csswg.org/css-scrollbars-1/
case "scrollbarWidth":
{
value === "none" && rules.push(`${selector}::-webkit-scrollbar{display:none}`);
const block = createDeclarationBlock({
scrollbarWidth: value
});
rules.push(`${selector}${block}`);
break;
}
default:
{
const block = createDeclarationBlock({
[property]: value
});
rules.push(`${selector}${block}`);
break;
}
}
return rules;
}
function createDeclarationBlock(style) {
const domStyle = createReactDOMStyle(style);
return `{${Object.keys(domStyle).map(property => {
const value = domStyle[property],
prop = hyphenateStyleName(property);
return Array.isArray(value) ? value.map(v => `${prop}:${v}`).join(";") : `${prop}:${value}`;
}).sort().join(";")};}`;
}
function createIdentifier(prefix, name, value) {
const hashedString = simpleHash(name + stringifyValueWithProperty(value, name));
return process.env.NODE_ENV !== "production" ? `${prefix}-${name}-${hashedString}` : `${prefix}-${hashedString}`;
}
function createKeyframes(keyframes) {
const prefixes = ["-webkit-", ""],
identifier = createIdentifier("r", "animation", keyframes),
steps = "{" + Object.keys(keyframes).map(stepName => {
const rule = keyframes[stepName],
block = createDeclarationBlock(rule);
return `${stepName}${block}`;
}).join("") + "}",
rules = prefixes.map(prefix => `@${prefix}keyframes ${identifier}${steps}`);
return [identifier, rules];
}
function processKeyframesValue(keyframesValue) {
if (typeof keyframesValue == "number") throw new Error(`Invalid CSS keyframes type: ${typeof keyframesValue}`);
const animationNames = [],
rules = [];
return (Array.isArray(keyframesValue) ? keyframesValue : [keyframesValue]).forEach(keyframes => {
if (typeof keyframes == "string") animationNames.push(keyframes);else {
const [identifier, keyframesRules] = createKeyframes(keyframes);
animationNames.push(identifier), rules.push(...keyframesRules);
}
}), [animationNames, rules];
}
export { atomic, classic, inline, stringifyValueWithProperty };
//# sourceMappingURL=index.mjs.map