@amaui/style
Version:
CSS in JS styling solution
252 lines (191 loc) • 10.6 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import Try from '@amaui/utils/try';
import isEnvironment from '@amaui/utils/isEnvironment';
import AmauiStyleSheet from './AmauiStyleSheet';
import { cammelCaseToKebabCase, getID, getRefs, is, valueResolve } from './utils';
const optionsDefault = {
value_version: 'value',
pure: false,
parents: [],
sort: true,
prefix: true,
rtl: true
};
class AmauiStyleRuleProperty {
constructor(value, property) {
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : optionsDefault;
_defineProperty(this, "value_version", 'value');
_defineProperty(this, "pure", false);
_defineProperty(this, "parents", []);
_defineProperty(this, "values", {
property: '',
value: '',
css: ''
});
this.value = value;
this.property = property;
this.options = options;
this.init();
}
get parent() {
return this.parents[this.parents.length - 1];
}
get response() {
return {
css: this.values.css
};
}
get css() {
return this.response.css;
}
updateValues() {
// Response
this.values.css = "".concat(this.values.property, ": ").concat(this.values.value, ";"); // For undefined animation name value
if (this.values.css.indexOf('undefined') > -1) this.values.css = '';
}
init(value) {
var _this$amauiStyleSheet, _this$parent, _this$amauiStyleSheet2, _this$parent2;
// Update values
this.values.property = cammelCaseToKebabCase(this.property);
this.values.value = value !== undefined ? value : this.value; // Options
this.value_version = this.options.value_version || 'value';
this.pure = this.options.pure !== undefined ? this.options.pure : false;
this.owner = this.options.owner;
this.parents = this.options.parents || [];
this.amauiStyle = this.options.amauiStyle;
this.amauiStyleSheet = this.options.amauiStyleSheet;
this.amauiStyleRule = this.options.amauiStyleRule;
if (this.id === undefined) this.id = getID();
if (this.level === undefined) this.level = this.parents.length - 1; // Add to rules_owned to all parents
this.parents.filter(parent => !(parent instanceof AmauiStyleSheet)).forEach(parent => parent.rules_owned.push(this)); // method or AmauiSubscription
if (value === undefined && ['method', 'amaui_subscription'].indexOf(this.value_version) > -1) {
if (this.value_version === 'method') this.values.value = Try(() => this.value(this.amauiStyleSheet.props));else if (this.value_version === 'amaui_subscription') {
this.values.value = this.value.value;
if (!this.value.subscribed) this.value.subscribed = [];
if (this.value.subscribed.indexOf(this) === -1) {
this.value.subscribe(this.update.bind(this));
this.value.subscribed.push(this);
}
} // Value
this.values.value = is('function', this.values.value) ? Try(() => this.values.value(this.amauiStyleSheet.props)) : this.values.value;
} // Value
this.values.value = valueResolve(this.values.property, this.values.value, this.amauiStyle).value[0]; // Move through plugins
// rtl
const useRtl = this.amauiStyle.options.rule.rtl && (this.amauiStyleSheet === undefined || this.amauiStyleSheet.options.rule.rtl !== false) && (((_this$amauiStyleSheet = this.amauiStyleSheet) === null || _this$amauiStyleSheet === void 0 ? void 0 : _this$amauiStyleSheet.amauiTheme) === undefined || this.amauiStyleSheet.amauiTheme.options.rule.rtl) && // by default is true
((_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.options.rtl) !== false;
if (useRtl) {
const rtl = this.amauiStyle.subscriptions.rule.rtl.map(this.values);
if (rtl !== null && rtl !== void 0 && rtl.value) {
var _rtl$value, _rtl$value2;
if (rtl !== null && rtl !== void 0 && (_rtl$value = rtl.value) !== null && _rtl$value !== void 0 && _rtl$value.property) this.values.property = rtl.value.property;
if (rtl !== null && rtl !== void 0 && (_rtl$value2 = rtl.value) !== null && _rtl$value2 !== void 0 && _rtl$value2.value) this.values.value = rtl.value.value;
}
} // prefix
const usePrefix = this.amauiStyle.options.rule.prefix && (this.amauiStyleSheet === undefined || this.amauiStyleSheet.options.rule.prefix !== false) && (((_this$amauiStyleSheet2 = this.amauiStyleSheet) === null || _this$amauiStyleSheet2 === void 0 ? void 0 : _this$amauiStyleSheet2.amauiTheme) === undefined || this.amauiStyleSheet.amauiTheme.options.rule.prefix !== false) && // by default is true
((_this$parent2 = this.parent) === null || _this$parent2 === void 0 ? void 0 : _this$parent2.options.prefix) !== false;
if (usePrefix && this.values.property.indexOf('-') !== 0 && Try(() => this.values.value.indexOf('-') !== 0)) {
var _this$amauiStyle$subs;
const prefixes = ((_this$amauiStyle$subs = this.amauiStyle.subscriptions.rule.prefix.map({
value: this.values.value,
property: this.values.property
})) === null || _this$amauiStyle$subs === void 0 ? void 0 : _this$amauiStyle$subs.value) || [];
if (!!prefixes.length) {
prefixes.forEach(item => {
var _this$parent3;
const exists = (((_this$parent3 = this.parent) === null || _this$parent3 === void 0 ? void 0 : _this$parent3.rules) || []).find(rule_ => rule_ instanceof AmauiStyleRuleProperty && rule_.values.property === item.property && rule_.values.value === item.value);
if (!exists && this.parent) {
AmauiStyleRuleProperty.make(item.value, item.property, {
value_version: 'value',
pure: this.pure,
owner: this.parent,
parents: this.parents,
amauiStyleRule: this.amauiStyleRule,
amauiStyleSheet: this.parent.amauiStyleSheet,
amauiStyle: this.parent.amauiStyle
});
}
});
}
} // Add itself to owner rules
if (this.owner) {
const exists = this.owner.rules.find(rule => rule.value.id === this.id);
if (!exists) this.owner.rules.push({
property: this.property,
value: this
});
this.level_actual = this.owner.level_actual + 1;
} // Update values
this.updateValues();
} // Update only if amauiStyleSheet is version 'dynamic'
update(value) {
var _domElement$style;
// Init with value
if (value !== undefined) this.init(value); // Make selector
// ie. for animation, and animation-name
this.makeSelector(); // Update the rule
// method or AmauiSubscription
if (value === undefined && ['method', 'amaui_subscription'].indexOf(this.value_version) > -1) {
if (this.value_version === 'method') this.values.value = Try(() => this.value(this.amauiStyleSheet.props));else if (this.value_version === 'amaui_subscription') this.values.value = this.value.value; // Value
this.values.value = is('function', this.values.value) ? Try(() => this.values.value(this.amauiStyleSheet.props)) : this.values.value;
this.values.value = valueResolve(this.values.property, this.values.value, this.amauiStyle).value[0];
} // Update values
this.updateValues();
const domElement = this.amauiStyleSheet.domElementForTesting || isEnvironment('browser') && window.document.createElement('div');
if (domElement) domElement.style[this.values.property] = this.values.value;
const valueNew = (domElement === null || domElement === void 0 ? void 0 : (_domElement$style = domElement.style) === null || _domElement$style === void 0 ? void 0 : _domElement$style[this.values.property]) || this.values.value; // Only if rule reference exists
if (this.owner.rule) {
// Only update if value is diff from previous update
if (this.owner.rule.style[this.values.property] !== valueNew) {
var _this$values$value;
const rule = this.owner.owner.rule || this.owner.owner.sheet; // For some reason important will not update the style property
// updating it through rule.style[property]
// only way is to fully remove the CSSStyleRule
// and insert a new one with new value
if (is('string', this.values.value) && (_this$values$value = this.values.value) !== null && _this$values$value !== void 0 && _this$values$value.includes('!important')) {
let index = Array.from((rule === null || rule === void 0 ? void 0 : rule.cssRules) || []).findIndex(item => item === this.owner.rule);
if (index > -1) {
Try(() => rule.deleteRule(index)); // Update owner values so it includes
// new update for this property value
this.owner.updateValues();
index = Try(() => rule.insertRule(this.owner.values.css));
if (index > -1) this.owner.rule = rule.cssRules[index];
}
} else Try(() => this.owner.rule.style[this.values.property] = this.values.value); // Update the values css string value
this.values.css = "".concat(this.values.property, ": ").concat(this.values.value, ";");
}
}
}
remove() {
this.clear();
}
makeSelector() {
if (['animation', 'animation-name'].some(item => this.values.property.indexOf(item) > -1)) {
const refs = getRefs(this.values.value);
const refValues = refs.map(item => this.amauiStyleSheet.amauiStyleSheetManager.names.keyframes[item]).filter(Boolean);
refs.forEach((ref, i) => this.values.value = this.values.value.replace("$".concat(ref), refValues[i])); // Update values
this.updateValues();
}
}
clear() {
var _this$owner;
// rule
if ((_this$owner = this.owner) !== null && _this$owner !== void 0 && _this$owner.rule) this.owner.rule.style[this.values.property] = ''; // rules
if (this.owner) {
const index = this.owner.rules.findIndex(item => item.value === this);
if (index > -1) this.owner.rules.splice(index, 1);
} // rules owned
this.parents.filter(parent => !(parent instanceof AmauiStyleSheet)).forEach(parent => {
const index = parent.rules_owned.findIndex(item => item.value === this);
if (index > -1) parent.rules_owned.splice(index, 1);
});
}
static make(value, property) {
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
value_version: 'value',
pure: false,
parents: [this]
};
return new AmauiStyleRuleProperty(value, property, options);
}
}
export default AmauiStyleRuleProperty;