@visactor/vrender-core
Version:
```typescript import { xxx } from '@visactor/vrender-core'; ```
172 lines (165 loc) • 8.96 kB
JavaScript
"use strict";
function isPlainObject(value) {
return null != value && "object" == typeof value && !Array.isArray(value);
}
function cloneValue(value) {
if (!isPlainObject(value)) return value;
const clone = {};
return Object.keys(value).forEach((key => {
clone[key] = cloneValue(value[key]);
})), clone;
}
function deepMerge(base, value) {
var _a;
const result = null !== (_a = cloneValue(base)) && void 0 !== _a ? _a : {};
return Object.keys(value).forEach((key => {
const nextValue = value[key], previousValue = result[key];
isPlainObject(previousValue) && isPlainObject(nextValue) ? result[key] = deepMerge(previousValue, nextValue) : result[key] = cloneValue(nextValue);
})), result;
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.StateEngine = void 0;
class StateEngine {
constructor(options) {
var _a;
this._activeStates = [], this._effectiveStates = [], this._suppressed = [], this._resolvedPatch = {},
this.resolverPatchCache = new Map, this.resolverCacheKey = "", this.resolverCacheValid = !1,
this.baseAttributes = {}, this.compiledDefinitions = options.compiledDefinitions,
this.stateSort = options.stateSort, this.mergeMode = null !== (_a = options.mergeMode) && void 0 !== _a ? _a : "shallow";
}
get activeStates() {
return this._activeStates;
}
get effectiveStates() {
return this._effectiveStates;
}
get resolvedPatch() {
return this._resolvedPatch;
}
get suppressed() {
return this._suppressed;
}
setResolveContext(graphic, baseAttributes) {
this.graphic === graphic && this.baseAttributes === baseAttributes || this.invalidateResolverCache(),
this.graphic = graphic, this.baseAttributes = baseAttributes;
}
applyStates(stateNames) {
const uniqueStates = Array.from(new Set(stateNames)), sortedStates = this.sortStates(uniqueStates), adjudicated = this.adjudicate(sortedStates), activeStates = adjudicated.active, effectiveStates = activeStates.filter((stateName => !adjudicated.suppressedSet.has(stateName))), suppressed = activeStates.filter((stateName => adjudicated.suppressedSet.has(stateName))), changed = !this.sameArray(this._activeStates, activeStates) || !this.sameArray(this._effectiveStates, effectiveStates) || !this.sameArray(this._suppressed, suppressed);
return this._activeStates = activeStates, this._effectiveStates = effectiveStates,
this._suppressed = suppressed, !changed && this.resolverCacheValid || this.recomputePatch(effectiveStates),
{
changed: changed,
activeStates: [ ...this._activeStates ],
effectiveStates: [ ...this._effectiveStates ],
suppressed: [ ...this._suppressed ]
};
}
addState(stateName, keepCurrentStates) {
if (this._activeStates.includes(stateName) && (keepCurrentStates || 1 === this._activeStates.length)) return {
changed: !1,
activeStates: [ ...this._activeStates ],
effectiveStates: [ ...this._effectiveStates ],
suppressed: [ ...this._suppressed ]
};
const nextStates = keepCurrentStates && this._activeStates.length ? this._activeStates.concat([ stateName ]) : [ stateName ];
return this.applyStates(nextStates);
}
removeState(stateNames) {
if (!this._activeStates.length) return {
changed: !1,
activeStates: [],
effectiveStates: [],
suppressed: []
};
const filteredNames = Array.isArray(stateNames) ? this._activeStates.filter((stateName => !stateNames.includes(stateName))) : this._activeStates.filter((stateName => stateName !== stateNames));
return filteredNames.length === this._activeStates.length ? {
changed: !1,
activeStates: [ ...this._activeStates ],
effectiveStates: [ ...this._effectiveStates ],
suppressed: [ ...this._suppressed ]
} : this.applyStates(filteredNames);
}
toggleState(stateName) {
return this.hasState(stateName) ? this.removeState(stateName) : this.applyStates(this._activeStates.concat([ stateName ]));
}
clearStates() {
const changed = this._activeStates.length > 0 || this._effectiveStates.length > 0 || this._suppressed.length > 0;
return this._activeStates = [], this._effectiveStates = [], this._suppressed = [],
this._resolvedPatch = {}, this.resolverPatchCache.clear(), this.resolverCacheKey = "",
this.resolverCacheValid = !1, {
changed: changed,
activeStates: [],
effectiveStates: [],
suppressed: []
};
}
invalidateResolverCache() {
this.resolverPatchCache.clear(), this.resolverCacheKey = "", this.resolverCacheValid = !1;
}
hasState(stateName) {
return !!this._activeStates.length && (null == stateName || this._activeStates.includes(stateName));
}
sortStates(states) {
const withDefinition = [], withoutDefinition = [];
return states.forEach((stateName => {
this.compiledDefinitions.has(stateName) ? withDefinition.push(stateName) : withoutDefinition.push(stateName);
})), withDefinition.sort(((left, right) => {
const leftDefinition = this.compiledDefinitions.get(left), rightDefinition = this.compiledDefinitions.get(right);
return leftDefinition && rightDefinition ? leftDefinition.priority !== rightDefinition.priority ? leftDefinition.priority - rightDefinition.priority : leftDefinition.rank - rightDefinition.rank : 0;
})), this.stateSort && withoutDefinition.length > 1 && withoutDefinition.sort(this.stateSort),
withDefinition.concat(withoutDefinition);
}
adjudicate(sortedStates) {
const candidate = sortedStates.slice(), suppressedSet = new Set;
for (let index = candidate.length - 1; index >= 0; index--) {
const stateName = candidate[index], definition = this.compiledDefinitions.get(stateName);
definition && (definition.exclude.forEach((excludedState => {
const excludedIndex = candidate.indexOf(excludedState);
-1 !== excludedIndex && (candidate.splice(excludedIndex, 1), excludedIndex < index && (index -= 1));
})), definition.suppress.forEach((suppressedState => {
suppressedSet.add(suppressedState);
})));
}
return {
active: candidate,
suppressedSet: suppressedSet
};
}
recomputePatch(effectiveStates) {
const cacheKey = effectiveStates.join(","), nextPatch = {}, useResolverCache = this.resolverCacheValid && this.resolverCacheKey === cacheKey;
useResolverCache || (this.resolverPatchCache.clear(), this.resolverCacheKey = cacheKey),
effectiveStates.forEach((stateName => {
var _a;
const definition = this.compiledDefinitions.get(stateName);
if (definition && (definition.patch && this.mergeInto(nextPatch, definition.patch),
definition.hasResolver)) {
const resolverPatch = useResolverCache ? this.resolverPatchCache.get(stateName) : null === (_a = definition.resolver) || void 0 === _a ? void 0 : _a.call(definition, {
graphic: this.graphic,
activeStates: this._activeStates,
effectiveStates: this._effectiveStates,
baseAttributes: this.baseAttributes,
resolvedPatch: nextPatch
});
resolverPatch && (useResolverCache || this.resolverPatchCache.set(stateName, resolverPatch),
this.mergeInto(nextPatch, resolverPatch));
}
})), useResolverCache || (this.resolverCacheValid = !0), this._resolvedPatch = nextPatch;
}
mergeInto(target, patch) {
"deep" !== this.mergeMode ? Object.keys(patch).forEach((key => {
target[key] = cloneValue(patch[key]);
})) : Object.keys(patch).forEach((key => {
var _a;
const nextValue = patch[key], previousValue = target[key], baseValue = null === (_a = this.baseAttributes) || void 0 === _a ? void 0 : _a[key];
isPlainObject(previousValue) && isPlainObject(nextValue) ? target[key] = deepMerge(previousValue, nextValue) : !isPlainObject(previousValue) && isPlainObject(baseValue) && isPlainObject(nextValue) ? target[key] = deepMerge(baseValue, nextValue) : target[key] = cloneValue(nextValue);
}));
}
sameArray(left, right) {
if (left.length !== right.length) return !1;
for (let index = 0; index < left.length; index++) if (left[index] !== right[index]) return !1;
return !0;
}
}
exports.StateEngine = StateEngine;
//# sourceMappingURL=state-engine.js.map