UNPKG

@visactor/vrender-core

Version:

```typescript import { xxx } from '@visactor/vrender-core'; ```

164 lines (160 loc) 8.82 kB
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; } export 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; } } //# sourceMappingURL=state-engine.js.map