stencil-prop-store-sync
Version:
A Stencil decorator for synchronizing @Prop and @State changes with a store, so you don't have to worry about prop drilling.
66 lines (65 loc) • 1.91 kB
JavaScript
// src/lib/index.ts
import { createStore } from "@stencil/store";
import { getElement } from "@stencil/core";
function createStoreSync(initialState) {
const store = createStore(initialState);
const elementsMap = /* @__PURE__ */ new Map();
store.use({
set: (propName, newValue, oldValue) => {
const elements = elementsMap.get(propName);
if (elements) {
elementsMap.set(
propName,
elements.filter((element) => {
const currentValue = element[propName];
if (currentValue === oldValue) {
element[propName] = newValue;
return true;
} else {
return false;
}
})
);
}
}
});
function appendElement(propName, element) {
const elements = elementsMap.get(propName);
if (!elements) {
elementsMap.set(propName, [element]);
} else {
elements.push(element);
}
}
function removeElement(propName, element) {
const elements = elementsMap.get(propName) || [];
const index = elements.indexOf(element);
if (index !== -1) {
elements.splice(index, 1);
elementsMap.set(propName, elements);
}
}
function SyncWithStore() {
return function(proto, propName) {
const { connectedCallback, disconnectedCallback } = proto;
proto.connectedCallback = function() {
const host = getElement(this);
const value = host[propName];
if (!value) {
const storeValue = store.state[propName];
host[propName] = storeValue;
appendElement(propName, host);
}
return connectedCallback?.call(this);
};
proto.disconnectedCallback = function() {
removeElement(propName, getElement(this));
return disconnectedCallback?.call(this);
};
};
}
return { store, SyncWithStore };
}
export {
createStoreSync
};