fluidstate
Version:
Library for fine-grained reactivity state management
107 lines (106 loc) • 4.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createReactiveArray = void 0;
var _reactiveNames = require("../extras/reactive-names");
var _reactivePluginArray = require("../extras/reactive-plugin-array");
var _reactivePlugin = require("../extras/reactive-plugin");
var _reactiveAtom = require("../primitives/reactive-atom");
var _reactiveOptions = require("../primitives/reactive-options");
var _reactiveChildren = require("./reactive-children");
var _reactiveProxy = require("./reactive-proxy");
const createReactiveArray = (inertArr, reactiveOptions, nameOptions) => {
const atomName = (0, _reactiveNames.createAtomNameFromOptions)(nameOptions);
const proxy = new Proxy(inertArr, new ReactiveArrayProxyHandler(atomName, {
items: (0, _reactiveAtom.createAtom)((0, _reactiveNames.createArrayAtomName)(atomName))
}, () => proxy, reactiveOptions));
return proxy;
};
exports.createReactiveArray = createReactiveArray;
class ReactiveArrayProxyHandler {
#atomName;
#reactive;
#getProxy;
#options;
constructor(atomName, reactive, getProxy, reactiveOptions) {
this.#atomName = atomName;
this.#reactive = reactive;
this.#getProxy = getProxy;
this.#options = {
reactiveOptions
};
}
get(inertArr, property, receiver) {
const p = property;
const ownPropertyDescriptor = Reflect.getOwnPropertyDescriptor(inertArr, p);
const isInherited = Reflect.has(inertArr, p) && !ownPropertyDescriptor;
if (!isInherited) {
this.#reactive.items.reportObserved();
}
const result = Reflect.get(inertArr, p, receiver);
return (0, _reactiveChildren.getChild)(this.#options, result, () => (0, _reactiveProxy.createProxy)(result, (0, _reactiveChildren.getChildOptions)(this.#options), {
parentAtomName: this.#atomName,
createAtomName: _reactiveNames.createArrayItemAtomName,
childIndex: p.toString()
}));
}
set(inertArr, property, newValue, receiver) {
const p = property;
const hasProperty = inertArr.hasOwnProperty(property);
const newStoredValue = this.#options.reactiveOptions?.deep === false ? newValue : (0, _reactiveProxy.ensureInert)(newValue);
const currentValue = Reflect.get(inertArr, property, receiver);
const isChanged = !(0, _reactiveOptions.reactiveValueEquals)(currentValue, newValue);
const previousLength = inertArr.length;
const willChangeForPlugins = this.#hasPlugins() && (isChanged && p !== "length" || p === "length" && Number(newValue) !== previousLength || !hasProperty);
const changes = !willChangeForPlugins ? null : (0, _reactivePluginArray.getArraySetChanges)(this.#getProxy(), inertArr, p, currentValue, newStoredValue, previousLength);
if (changes) {
(0, _reactivePlugin.beforeChange)(changes, this.#options.reactiveOptions?.plugins);
}
const result = Reflect.set(inertArr, property, newStoredValue, receiver);
const isLengthChanged = previousLength !== inertArr.length;
if (result) {
// The length property does not automatically get trapped when, for example,
// setting the value like this: `array[array.length] = 10`, because there
// is no internal call to a function where `this` refers to a proxy; hence,
// we have to manually check it after applying the update
if (isChanged && p !== "length" || isLengthChanged || !hasProperty) {
this.#reactive.items.reportChanged();
}
}
if (changes) {
(0, _reactivePlugin.afterChange)(changes, this.#options.reactiveOptions?.plugins);
}
return result;
}
deleteProperty(inertArr, property) {
const p = property; // p can be 'length' or a number here
const hasProperty = inertArr.hasOwnProperty(property);
const currentValue = Reflect.get(inertArr, property);
const isChanged = !(0, _reactiveOptions.reactiveValueEquals)(currentValue, undefined);
const previousLength = inertArr.length;
const changes = !this.#hasPlugins() || !isChanged ? null : (0, _reactivePluginArray.getArrayDeleteChanges)(this.#getProxy(), p, currentValue);
if (changes) {
(0, _reactivePlugin.beforeChange)(changes, this.#options.reactiveOptions?.plugins);
}
const result = Reflect.deleteProperty(inertArr, property);
const isLengthChanged = previousLength !== inertArr.length;
if (result) {
if (isChanged && p !== "length" || isLengthChanged || hasProperty) {
this.#reactive.items.reportChanged();
}
}
if (changes) {
(0, _reactivePlugin.afterChange)(changes, this.#options.reactiveOptions?.plugins);
}
return result;
}
ownKeys(inertArr) {
this.#reactive.items.reportObserved();
return Reflect.ownKeys(inertArr);
}
#hasPlugins() {
return (this.#options.reactiveOptions?.plugins?.length ?? 0) > 0;
}
}
//# sourceMappingURL=reactive-array.js.map