{"id":24082217,"url":"https://github.com/panmanfredini/lit-element-effector","last_synced_at":"2025-09-01T00:42:41.909Z","repository":{"id":79753035,"uuid":"306432206","full_name":"panManfredini/lit-element-effector","owner":"panManfredini","description":"Mixin to add an Effector Store to lit-element","archived":false,"fork":false,"pushed_at":"2020-10-30T22:26:45.000Z","size":123,"stargazers_count":7,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-16T14:41:02.835Z","etag":null,"topics":["effector","lit-element"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/panManfredini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-22T18:56:02.000Z","updated_at":"2022-08-16T23:59:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"55b23e69-f8e2-472a-b2c0-10f2741e98d0","html_url":"https://github.com/panManfredini/lit-element-effector","commit_stats":{"total_commits":25,"total_committers":1,"mean_commits":25.0,"dds":0.0,"last_synced_commit":"a56680428188343f9a2909f1da21cdc201740656"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panManfredini%2Flit-element-effector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panManfredini%2Flit-element-effector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panManfredini%2Flit-element-effector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panManfredini%2Flit-element-effector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/panManfredini","download_url":"https://codeload.github.com/panManfredini/lit-element-effector/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251755361,"owners_count":21638687,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["effector","lit-element"],"created_at":"2025-01-09T23:45:57.125Z","updated_at":"2025-04-30T17:47:55.122Z","avatar_url":"https://github.com/panManfredini.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lit-element-effector\nMinimal mixin to attach an [Effector](https://effector.now.sh/) Store to [lit-element](https://lit-element.polymer-project.org/).\n\n- Automatically request element update on effector store change.\n- Supports typescript.\n- Just a tiny wrapper, about [1kB minified](https://bundlephobia.com/result?p=lit-element-effector@latest).\n- Supports a pattern for inheritance.\n- Safe: makes a copy of the store into the custom element.\n- Built with best practices in mind.\n\n\n**/!\\ currently there is an [issue](https://github.com/panManfredini/lit-element-effector/issues/2) with ts-loader, but rollup and standalone webpack work.**\n\n\n# Usage \n\n```ts\n\nEffectorMxn( BaseClass, Store, FxAPI? ) =\u003e class extends BaseClass\n\n```\nThe mixin takes as input parameters a `BaseClass` which must inherit from a `LitElement`, an Effector `Store` and an optional object, `FxAPI`.\nThis last one is meant as dependency injection of the custom-element's effect interface, its values are expected to be \neither effector `effects` or `events` (or functions).\n\n\n```js\nimport {EffectorMxn} from \"lit-element-effector\"\nimport {html, LitElement} from \"lit-element\"\nimport {createStore} from \"effector\"\n\nconst store01 = createStore( {greetings:\"hello\"} );\n\nclass example01 extends EffectorMxn( LitElement, store ){\n    render(){\n        // the store state is available with the `$` property\n        return html`\u003ch1\u003e ${this.$.greetings} world! \u003c/h1\u003e`\n    }\n}\n\ncustomElements.define(\"example-01\",example01);\n```\nThe provided store is reflected to the LitElement property **$**. Supports any store types, from boolean to objects. \nThe store state is deeply-copied to **$**. Direct assignment to the property **$** should be avoided, altough it cannot affect the state.\n\n\n## Event and Effect API Helper\n\n```js\nimport {createEvent, createEffect} from \"effector\"\n\nconst evnt = createEvent();\nconst Fx = createEffect(/* some network call*/);\n\nstore01.on( evnt, (_,p) =\u003e { return {greetings:p} } );\n\nconst API = { changeGreetings: evnt,  networkCallFx: Fx } ;\n\nclass example02 extends EffectorMxn(LitElement, store01, API){\n    render(){\n        return html`\n            \u003ch1\u003e ${this.$.greetings} world! \u003c/h1\u003e\n            \u003cbutton @click=\"${this.clickme}\"\u003e\u003c/button\u003e\n        `\n    }\n\n    clickme(){\n        // the effects API is available under `dispatch` prop\n        this.dispatch.changeGreetings(\"Hey\");\n    }\n}\n\n```\n\nIf defined, the effect API is injected into the `dispatch` getter property. This is no more than a recommendation, \nit helps to keep the custom-element decoupled from the app-state (see an example in the test section below). \nIn some cases can be more convenient to override the `dispatch` getter, if you do so is a good practice to return \na shallow copy of the API object (since it could be used in multiple places).\n\n\n## React on Store change with user defined function\n\n```js\n\nclass example03 extends EffectorMxn(LitElement, store){\n    \n    on_store_update(stateCopy)\n    {\n        /* Do something on update */\n    }\n    render() { /* render component */ }\n}\n```\n\nIf defined, the function `on_store_update` will be executed any time a store change is triggered.\nThe only argument passed to the function is a copy of the current store. This function will run after the property **$** is \nset, but before any of the element's update/render.\n\n## Inheritance\n\n```js\n\nimport {combine} from \"effector\";\nconst store02 = createStore( {username:\"Alex\"} )\nconst combinedStore = combine(store01,store02, (a,b) =\u003e Object.assign({}, a,b) );\n\n// here applying the mixing to the previous example class\nclass example04 extends EffectorMxn(example01, combinedStore){ \n    \n    // adding a reflected attribute on top of the inherited ones\n    @property() type = \"dark\";\n    \n    render(){\n        return html `\n            ${super.render()}\n            \u003cp class=\"${this.type}\"\u003e This is ${this.$.username}. \u003c/p\u003e\n        `\n    }\n}\n\n```\nLitElement makes sure that reflected properties of inherited classes are present and functioning. One thing to notice is that when \napplying the mixin multiple times the store is actually swapped, so the provided store of a child class must be a combination \nof the parent store and the additional wanted properties.\n\n## Testing Helpers\n\n```ts\n      it(\"Detaches from current store, send fake data\", async ()=\u003e{\n\n        var ex01 = \u003cexample01\u003edocument.createElement(\"example-01\");\n\n        // this detaches from store (replace with undefined)\n        ex01.replaceStore(); \n        //ex01.replaceStore(newStore); \n\n        // the element is not initialized until it is connected\n        document.body.appendChild(ex01);\n        await ex01.updateComplete;  // wait for render\n\n        expect(ex01.$).to.be.undefined; // no store\n\n        // simulate a store update with fake data \n        ex01.store_update_handler( {greetings: \"Ciao\" } );\n\n        expect(ex01.$).to.deep.equal( {greetings: \"Ciao\" } );\n    });\n\n\n```\nThere are a few convenient helpers to aid testing a custom-element with attached store. A function `replaceStore` is provided to swap the store with a fake one.\nThe `store_update_handler` function can be used to simulate a store update with fake data, you can also use this to initialize the element before appending the element to DOM.\n\n```js\n  it(\"Reassign the event API of an instance\",()=\u003e{\n        customElements.define(\"example-02\",example02);\n        var ex02 = document.createElement(\"example-02\");\n        \n        ex02.dispatch.networkCallFx = ( ) =\u003e {};\n\n        document.body.appendChild(ex02);\n\n        /* go on with network related call disabled */\n\n    });\n\n```\nMany times during testing we would mock or stub effects that make network calls, here you can simply reassign the instance API injecting a different function. \nThe `dispatch` getter returns a shallow copy of the effect-API, this means that you can swap the keys of that instance with fakes without \naffecting the overall element class nor the original effect-API.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpanmanfredini%2Flit-element-effector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpanmanfredini%2Flit-element-effector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpanmanfredini%2Flit-element-effector/lists"}