@ryangjchandler/spruce
Advanced tools
Comparing version 1.1.2 to 2.0.0
@@ -1,2 +0,2 @@ | ||
function t(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function e(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,r)}return n}var n=function(t){return null==t},r=function(t){return Object.getPrototypeOf(t)===Object.prototype},s=function(t,e){return Object.entries(t).forEach(function(i){var o=i[0],c=i[1];n(c)||!r(c)&&!Array.isArray(c)||(t[o]=s(c,e))}),new Proxy(t,{set:function(t,i,o){return!n(o)&&r(o)&&(o=s(o,e)),e.set(t,i,t[i]=o),!0}})},i={events:{watchers:{},events:{},on:function(t,e,n){var r=this;return void 0===n&&(n=!1),this.events[t]||(this.events[t]=[]),this.events[t].push({callback:e,once:n}),function(){return r.off(t,e)}},once:function(t,e){this.on(t,e,!0)},off:function(t,e){this.events[t]=this.events[t].filter(function(t){return t.callback!==e&&!0!==t.once})},emit:function(t,e){var n=this;void 0===e&&(e={}),(this.events[t]||[]).forEach(function(r){r.callback(e),r.once&&n.off(t,r)}),window.dispatchEvent(new CustomEvent("spruce:"+t,{detail:e,bubbles:!0}))},watch:function(t,e){this.watchers[t]||(this.watchers[t]=[]),this.watchers[t].push(e)},runWatchers:function(t,e,n,r){var s=this;if(s.watchers[n])return s.watchers[n].forEach(function(t){return t(r)});Object.keys(s.watchers).filter(function(t){return t.includes(".")}).forEach(function(i){var o=i.split(".");n===o[o.length-1]&&o.reduce(function(t,o){return(t[n]===e[n]||Object.is(e,t))&&s.watchers[i].forEach(function(t){return t(r)}),t[o]},t)})}},stores:{},subscribers:[],start:function(){try{var t=this;return Promise.resolve(new Promise(function(t){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()})).then(function(){t.emit("init"),t.attach(),t.stores=s(t.stores,{set:function(e,n,r){t.events.runWatchers(t.stores,e,n,r),t.updateSubscribers()}})})}catch(t){return Promise.reject(t)}},attach:function(){if(!window.Alpine)throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var t=this;window.Alpine.addMagicProperty("store",function(e){return t.subscribe(e),t.stores})},store:function(t,e){return this.stores[t]||(this.stores[t]=e),this.stores[t]},reset:function(t,e){this.stores[t]=e},subscribe:function(t){return this.subscribers.includes(t)||this.subscribers.push(t),this.stores},updateSubscribers:function(){this.subscribers.filter(function(t){return!!t.__x}).forEach(function(t){t.__x.updateElements(t)})},on:function(t,e){return this.events.on(t,e)},once:function(t,e){return this.events.once(t,e)},off:function(t,e){this.events.off(t,e)},emit:function(n,r){void 0===r&&(r={}),this.events.emit(n,function(n){for(var r=1;r<arguments.length;r++){var s=null!=arguments[r]?arguments[r]:{};r%2?e(Object(s),!0).forEach(function(e){t(n,e,s[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(s)):e(Object(s)).forEach(function(t){Object.defineProperty(n,t,Object.getOwnPropertyDescriptor(s,t))})}return n}({},r,{store:this.stores}))},watch:function(t,e){this.events.watch(t,e)}},o=window.deferLoadingAlpine||function(t){t()};window.deferLoadingAlpine=function(t){window.Spruce=i,window.Spruce.start(),o(t)},module.exports=i; | ||
var t=function(t){return null==t},e=function(t){return Object.getPrototypeOf(t)===Object.prototype},r=function(n,s){return Object.entries(n).forEach(function(i){var o=i[0],c=i[1];t(c)||!e(c)&&!Array.isArray(c)||(n[o]=r(c,s))}),new Proxy(n,{set:function(n,i,o){return!t(o)&&e(o)&&(o=r(o,s)),s.set(n,i,n[i]=o),!0}})},n={stores:{},persisted:[],subscribers:[],watchers:{},disableReactivity:!1,start:function(){try{var t=this;return Promise.resolve(new Promise(function(t){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()})).then(function(){t.attach(),t.stores=r(t.stores,{set:function(e,r,n){if(!t.disableReactivity){t.updateSubscribers(),t.runWatchers(t.stores,e,r,n),t.disableReactivity=!0;try{t.persisted.forEach(t.updateLocalStorage.bind(t))}catch(t){}t.disableReactivity=!1}}})})}catch(t){return Promise.reject(t)}},attach:function(){if(!window.Alpine)throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var t=this;window.Alpine.addMagicProperty("store",function(e){return t.subscribe(e),t.stores})},store:function(t,e,r){if(void 0===r&&(r=!1),r)try{this.stores[t]=this.retrieveFromLocalStorage(t,(n={},Object.entries(e).filter(function(t){return"function"==typeof t[1]}).forEach(function(t){return n[t[0]]=t[1]}),n)),this.persisted.includes(t)||this.persisted.push(t)}catch(t){}var n;return this.stores[t]||(this.stores[t]=e),this.stores[t]},reset:function(t,e){this.stores[t]=e},subscribe:function(t){return this.subscribers.includes(t)||this.subscribers.push(t),this.stores},updateSubscribers:function(){this.subscribers.filter(function(t){return!!t.__x}).forEach(function(t){t.__x.updateElements(t)})},retrieveFromLocalStorage:function(t,e){void 0===e&&(e={});var r=JSON.parse(window.localStorage.getItem("__spruce:"+t));return r?Object.assign(e,r):null},updateLocalStorage:function(t){window.localStorage.setItem("__spruce:"+t,JSON.stringify(this.store(t)))},watch:function(t,e){this.watchers[t]||(this.watchers[t]=[]),this.watchers[t].push(e)},runWatchers:function(t,e,r,n){var s=this;if(s.watchers[r])return s.watchers[r].forEach(function(t){return t(n)});Object.keys(s.watchers).filter(function(t){return t.includes(".")}).forEach(function(i){var o=i.split(".");r===o[o.length-1]&&o.reduce(function(t,o){return(t[r]===e[r]||Object.is(e,t))&&s.watchers[i].forEach(function(t){return t(n)}),t[o]},t)})}},s=window.deferLoadingAlpine||function(t){t()};window.deferLoadingAlpine=function(t){window.Spruce=n,window.Spruce.start(),s(t)},module.exports=n; | ||
//# sourceMappingURL=spruce.js.map |
@@ -1,2 +0,2 @@ | ||
function t(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function e(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,r)}return n}var n=function(t){return null==t},r=function(t){return Object.getPrototypeOf(t)===Object.prototype},s=function(t,e){return Object.entries(t).forEach(function(i){var o=i[0],c=i[1];n(c)||!r(c)&&!Array.isArray(c)||(t[o]=s(c,e))}),new Proxy(t,{set:function(t,i,o){return!n(o)&&r(o)&&(o=s(o,e)),e.set(t,i,t[i]=o),!0}})},i={events:{watchers:{},events:{},on:function(t,e,n){var r=this;return void 0===n&&(n=!1),this.events[t]||(this.events[t]=[]),this.events[t].push({callback:e,once:n}),function(){return r.off(t,e)}},once:function(t,e){this.on(t,e,!0)},off:function(t,e){this.events[t]=this.events[t].filter(function(t){return t.callback!==e&&!0!==t.once})},emit:function(t,e){var n=this;void 0===e&&(e={}),(this.events[t]||[]).forEach(function(r){r.callback(e),r.once&&n.off(t,r)}),window.dispatchEvent(new CustomEvent("spruce:"+t,{detail:e,bubbles:!0}))},watch:function(t,e){this.watchers[t]||(this.watchers[t]=[]),this.watchers[t].push(e)},runWatchers:function(t,e,n,r){var s=this;if(s.watchers[n])return s.watchers[n].forEach(function(t){return t(r)});Object.keys(s.watchers).filter(function(t){return t.includes(".")}).forEach(function(i){var o=i.split(".");n===o[o.length-1]&&o.reduce(function(t,o){return(t[n]===e[n]||Object.is(e,t))&&s.watchers[i].forEach(function(t){return t(r)}),t[o]},t)})}},stores:{},subscribers:[],start:function(){try{var t=this;return Promise.resolve(new Promise(function(t){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()})).then(function(){t.emit("init"),t.attach(),t.stores=s(t.stores,{set:function(e,n,r){t.events.runWatchers(t.stores,e,n,r),t.updateSubscribers()}})})}catch(t){return Promise.reject(t)}},attach:function(){if(!window.Alpine)throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var t=this;window.Alpine.addMagicProperty("store",function(e){return t.subscribe(e),t.stores})},store:function(t,e){return this.stores[t]||(this.stores[t]=e),this.stores[t]},reset:function(t,e){this.stores[t]=e},subscribe:function(t){return this.subscribers.includes(t)||this.subscribers.push(t),this.stores},updateSubscribers:function(){this.subscribers.filter(function(t){return!!t.__x}).forEach(function(t){t.__x.updateElements(t)})},on:function(t,e){return this.events.on(t,e)},once:function(t,e){return this.events.once(t,e)},off:function(t,e){this.events.off(t,e)},emit:function(n,r){void 0===r&&(r={}),this.events.emit(n,function(n){for(var r=1;r<arguments.length;r++){var s=null!=arguments[r]?arguments[r]:{};r%2?e(Object(s),!0).forEach(function(e){t(n,e,s[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(s)):e(Object(s)).forEach(function(t){Object.defineProperty(n,t,Object.getOwnPropertyDescriptor(s,t))})}return n}({},r,{store:this.stores}))},watch:function(t,e){this.events.watch(t,e)}},o=window.deferLoadingAlpine||function(t){t()};window.deferLoadingAlpine=function(t){window.Spruce=i,window.Spruce.start(),o(t)};export default i; | ||
var t=function(t){return null==t},e=function(t){return Object.getPrototypeOf(t)===Object.prototype},r=function(n,s){return Object.entries(n).forEach(function(i){var o=i[0],c=i[1];t(c)||!e(c)&&!Array.isArray(c)||(n[o]=r(c,s))}),new Proxy(n,{set:function(n,i,o){return!t(o)&&e(o)&&(o=r(o,s)),s.set(n,i,n[i]=o),!0}})},n={stores:{},persisted:[],subscribers:[],watchers:{},disableReactivity:!1,start:function(){try{var t=this;return Promise.resolve(new Promise(function(t){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()})).then(function(){t.attach(),t.stores=r(t.stores,{set:function(e,r,n){if(!t.disableReactivity){t.updateSubscribers(),t.runWatchers(t.stores,e,r,n),t.disableReactivity=!0;try{t.persisted.forEach(t.updateLocalStorage.bind(t))}catch(t){}t.disableReactivity=!1}}})})}catch(t){return Promise.reject(t)}},attach:function(){if(!window.Alpine)throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var t=this;window.Alpine.addMagicProperty("store",function(e){return t.subscribe(e),t.stores})},store:function(t,e,r){if(void 0===r&&(r=!1),r)try{this.stores[t]=this.retrieveFromLocalStorage(t,(n={},Object.entries(e).filter(function(t){return"function"==typeof t[1]}).forEach(function(t){return n[t[0]]=t[1]}),n)),this.persisted.includes(t)||this.persisted.push(t)}catch(t){}var n;return this.stores[t]||(this.stores[t]=e),this.stores[t]},reset:function(t,e){this.stores[t]=e},subscribe:function(t){return this.subscribers.includes(t)||this.subscribers.push(t),this.stores},updateSubscribers:function(){this.subscribers.filter(function(t){return!!t.__x}).forEach(function(t){t.__x.updateElements(t)})},retrieveFromLocalStorage:function(t,e){void 0===e&&(e={});var r=JSON.parse(window.localStorage.getItem("__spruce:"+t));return r?Object.assign(e,r):null},updateLocalStorage:function(t){window.localStorage.setItem("__spruce:"+t,JSON.stringify(this.store(t)))},watch:function(t,e){this.watchers[t]||(this.watchers[t]=[]),this.watchers[t].push(e)},runWatchers:function(t,e,r,n){var s=this;if(s.watchers[r])return s.watchers[r].forEach(function(t){return t(n)});Object.keys(s.watchers).filter(function(t){return t.includes(".")}).forEach(function(i){var o=i.split(".");r===o[o.length-1]&&o.reduce(function(t,o){return(t[r]===e[r]||Object.is(e,t))&&s.watchers[i].forEach(function(t){return t(n)}),t[o]},t)})}},s=window.deferLoadingAlpine||function(t){t()};window.deferLoadingAlpine=function(t){window.Spruce=n,window.Spruce.start(),s(t)};export default n; | ||
//# sourceMappingURL=spruce.module.js.map |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.spruce=e()}(this,function(){function t(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function e(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,r)}return n}var n=function(t){return null==t},r=function(t){return Object.getPrototypeOf(t)===Object.prototype},i=function(t,e){return Object.entries(t).forEach(function(s){var o=s[0],c=s[1];n(c)||!r(c)&&!Array.isArray(c)||(t[o]=i(c,e))}),new Proxy(t,{set:function(t,s,o){return!n(o)&&r(o)&&(o=i(o,e)),e.set(t,s,t[s]=o),!0}})},s={events:{watchers:{},events:{},on:function(t,e,n){var r=this;return void 0===n&&(n=!1),this.events[t]||(this.events[t]=[]),this.events[t].push({callback:e,once:n}),function(){return r.off(t,e)}},once:function(t,e){this.on(t,e,!0)},off:function(t,e){this.events[t]=this.events[t].filter(function(t){return t.callback!==e&&!0!==t.once})},emit:function(t,e){var n=this;void 0===e&&(e={}),(this.events[t]||[]).forEach(function(r){r.callback(e),r.once&&n.off(t,r)}),window.dispatchEvent(new CustomEvent("spruce:"+t,{detail:e,bubbles:!0}))},watch:function(t,e){this.watchers[t]||(this.watchers[t]=[]),this.watchers[t].push(e)},runWatchers:function(t,e,n,r){var i=this;if(i.watchers[n])return i.watchers[n].forEach(function(t){return t(r)});Object.keys(i.watchers).filter(function(t){return t.includes(".")}).forEach(function(s){var o=s.split(".");n===o[o.length-1]&&o.reduce(function(t,o){return(t[n]===e[n]||Object.is(e,t))&&i.watchers[s].forEach(function(t){return t(r)}),t[o]},t)})}},stores:{},subscribers:[],start:function(){try{var t=this;return Promise.resolve(new Promise(function(t){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()})).then(function(){t.emit("init"),t.attach(),t.stores=i(t.stores,{set:function(e,n,r){t.events.runWatchers(t.stores,e,n,r),t.updateSubscribers()}})})}catch(t){return Promise.reject(t)}},attach:function(){if(!window.Alpine)throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var t=this;window.Alpine.addMagicProperty("store",function(e){return t.subscribe(e),t.stores})},store:function(t,e){return this.stores[t]||(this.stores[t]=e),this.stores[t]},reset:function(t,e){this.stores[t]=e},subscribe:function(t){return this.subscribers.includes(t)||this.subscribers.push(t),this.stores},updateSubscribers:function(){this.subscribers.filter(function(t){return!!t.__x}).forEach(function(t){t.__x.updateElements(t)})},on:function(t,e){return this.events.on(t,e)},once:function(t,e){return this.events.once(t,e)},off:function(t,e){this.events.off(t,e)},emit:function(n,r){void 0===r&&(r={}),this.events.emit(n,function(n){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?e(Object(i),!0).forEach(function(e){t(n,e,i[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(n,t,Object.getOwnPropertyDescriptor(i,t))})}return n}({},r,{store:this.stores}))},watch:function(t,e){this.events.watch(t,e)}},o=window.deferLoadingAlpine||function(t){t()};return window.deferLoadingAlpine=function(t){window.Spruce=s,window.Spruce.start(),o(t)},s}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.spruce=e()}(this,function(){var t=function(t){return null==t},e=function(t){return Object.getPrototypeOf(t)===Object.prototype},r=function(n,i){return Object.entries(n).forEach(function(s){var o=s[0],c=s[1];t(c)||!e(c)&&!Array.isArray(c)||(n[o]=r(c,i))}),new Proxy(n,{set:function(n,s,o){return!t(o)&&e(o)&&(o=r(o,i)),i.set(n,s,n[s]=o),!0}})},n={stores:{},persisted:[],subscribers:[],watchers:{},disableReactivity:!1,start:function(){try{var t=this;return Promise.resolve(new Promise(function(t){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()})).then(function(){t.attach(),t.stores=r(t.stores,{set:function(e,r,n){if(!t.disableReactivity){t.updateSubscribers(),t.runWatchers(t.stores,e,r,n),t.disableReactivity=!0;try{t.persisted.forEach(t.updateLocalStorage.bind(t))}catch(t){}t.disableReactivity=!1}}})})}catch(t){return Promise.reject(t)}},attach:function(){if(!window.Alpine)throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var t=this;window.Alpine.addMagicProperty("store",function(e){return t.subscribe(e),t.stores})},store:function(t,e,r){if(void 0===r&&(r=!1),r)try{this.stores[t]=this.retrieveFromLocalStorage(t,(n={},Object.entries(e).filter(function(t){return"function"==typeof t[1]}).forEach(function(t){return n[t[0]]=t[1]}),n)),this.persisted.includes(t)||this.persisted.push(t)}catch(t){}var n;return this.stores[t]||(this.stores[t]=e),this.stores[t]},reset:function(t,e){this.stores[t]=e},subscribe:function(t){return this.subscribers.includes(t)||this.subscribers.push(t),this.stores},updateSubscribers:function(){this.subscribers.filter(function(t){return!!t.__x}).forEach(function(t){t.__x.updateElements(t)})},retrieveFromLocalStorage:function(t,e){void 0===e&&(e={});var r=JSON.parse(window.localStorage.getItem("__spruce:"+t));return r?Object.assign(e,r):null},updateLocalStorage:function(t){window.localStorage.setItem("__spruce:"+t,JSON.stringify(this.store(t)))},watch:function(t,e){this.watchers[t]||(this.watchers[t]=[]),this.watchers[t].push(e)},runWatchers:function(t,e,r,n){var i=this;if(i.watchers[r])return i.watchers[r].forEach(function(t){return t(n)});Object.keys(i.watchers).filter(function(t){return t.includes(".")}).forEach(function(s){var o=s.split(".");r===o[o.length-1]&&o.reduce(function(t,o){return(t[r]===e[r]||Object.is(e,t))&&i.watchers[s].forEach(function(t){return t(n)}),t[o]},t)})}},i=window.deferLoadingAlpine||function(t){t()};return window.deferLoadingAlpine=function(t){window.Spruce=n,window.Spruce.start(),i(t)},n}); | ||
//# sourceMappingURL=spruce.umd.js.map |
{ | ||
"name": "@ryangjchandler/spruce", | ||
"description": "A lightweight state management layer for Alpine.js", | ||
"version": "1.1.2", | ||
"version": "2.0.0", | ||
"repository": { | ||
@@ -6,0 +6,0 @@ "type": "git", |
@@ -200,59 +200,37 @@ > ✨ Help support the maintenance of this package by [sponsoring me](https://github.com/sponsors/ryangjchandler). | ||
### Event bus | ||
### Persisting stores | ||
Spruce ships with a basic event bus. It exposes two methods: | ||
You can persist the state of a global store between page loads using [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) by passing a third boolean argument to the `Spruce.store()` method. | ||
* `Spruce.on(eventName, callback)` - this can be used to register an event listener. This will react to any internal events, such as `init` . Your callback will receive a single `detail` property which contains any data sent from the event, as well as the global store. | ||
```js | ||
Spruce.on('init', ({ store }) => { | ||
// do something with the store here... | ||
}) | ||
Spruce.store('form', { | ||
name: 'Ryan', | ||
email: 'support@ryangjchandler.co.uk' | ||
}, true) | ||
``` | ||
* `Spruce.once(eventName, callback)` - this can be used to register an event listener that is only run **a single time**. This is useful for one time events, such as fetching HTML from the server when hovering over a button or similar. | ||
When the `form` store is updated, any changes will be persisted to `__spruce:form` key in local storage. | ||
``` js | ||
Spruce.once('event', () => { | ||
// do something once... | ||
}) | ||
``` | ||
> **Note**: some browsers will disable access to local storage when browsing in private mode. | ||
* `Spruce.off(eventName, callback)` - this can be used to unhook or de-register an event listener. | ||
**Persisted stores with methods** | ||
``` js | ||
var callback = () => {} | ||
Stores that contain methods can still be persisted. These methods cannot be JSON-serialized, so will be re-added to the data that was retrieved from local storage. | ||
Spruce.off('init', callback) | ||
``` | ||
```js | ||
Spruce.store('form', { | ||
name: 'Ryan', | ||
email: 'support@ryangjchandler.co.uk', | ||
logName() { | ||
console.log(this.name) | ||
} | ||
}, true) | ||
You can also unhook a listener using the function returned by `Spruce.on()` . This is especially useful for anonymous function callbacks. | ||
``` js | ||
var off = Spruce.on('event', () => {}) | ||
off() | ||
Spruce.store('form').logName() // logs `Ryan` to console. | ||
``` | ||
* `Spruce.emit(eventName, data = {})` - this can be used to emit an event. The first argument should be the name of the event, the second should be an object containing data. This will be merged in with the core data, which consists of a `store` property. When emitting an event, a browser event will also be dispatched with a `spruce:` prefix. | ||
``` js | ||
Spruce.emit('event-name', { | ||
foo: 'bar' | ||
}) | ||
``` | ||
In the example above, a `spruce:event-name` event will be fired on the `window` level, so you could register an event listener inside of your Alpine component: | ||
``` html | ||
<div x-data @spruce:event-name.window="foo = $event.detail.store.foo"> | ||
</div> | ||
``` | ||
k | ||
## Versioning | ||
This project follows the [Semantic Versioning](https://semver.org/) guidelines. This means that there *could* be breaking changes on minor version changes, up until v1.x is reached. | ||
This project follows the [Semantic Versioning](https://semver.org/) guidelines. | ||
For example, 0.1 -> 0.2 might introduce a breaking change. | ||
## License | ||
@@ -259,0 +237,0 @@ |
@@ -1,17 +0,18 @@ | ||
import { domReady } from './utils' | ||
import { domReady, getMethods } from './utils' | ||
import { createObservable } from './observable' | ||
import EventBus from './bus' | ||
const Spruce = { | ||
events: EventBus, | ||
stores: {}, | ||
persisted: [], | ||
subscribers: [], | ||
watchers: {}, | ||
disableReactivity: false, | ||
async start() { | ||
await domReady() | ||
this.emit('init') | ||
this.attach() | ||
@@ -21,5 +22,19 @@ | ||
set: (target, key, value) => { | ||
this.events.runWatchers(this.stores, target, key, value) | ||
if (this.disableReactivity) { | ||
return | ||
} | ||
this.updateSubscribers() | ||
this.runWatchers(this.stores, target, key, value) | ||
this.disableReactivity = true | ||
try { | ||
this.persisted.forEach(this.updateLocalStorage.bind(this)) | ||
} catch (e) { | ||
// Do nothing here (thanks Safari!) | ||
} | ||
this.disableReactivity = false | ||
} | ||
@@ -30,3 +45,3 @@ }) | ||
attach() { | ||
if (! window.Alpine) { | ||
if (!window.Alpine) { | ||
throw new Error('[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.') | ||
@@ -44,4 +59,16 @@ } | ||
store(name, state) { | ||
if (! this.stores[name]) { | ||
store(name, state, persist = false) { | ||
if (persist) { | ||
try { | ||
this.stores[name] = this.retrieveFromLocalStorage(name, getMethods(state)) | ||
if (!this.persisted.includes(name)) { | ||
this.persisted.push(name) | ||
} | ||
} catch (e) { | ||
// Do nothing here (thanks Safari!) | ||
} | ||
} | ||
if (!this.stores[name]) { | ||
this.stores[name] = state | ||
@@ -58,3 +85,3 @@ } | ||
subscribe(el) { | ||
if (! this.subscribers.includes(el)) { | ||
if (!this.subscribers.includes(el)) { | ||
this.subscribers.push(el) | ||
@@ -67,3 +94,3 @@ } | ||
updateSubscribers() { | ||
this.subscribers.filter(el => !! el.__x).forEach(el => { | ||
this.subscribers.filter(el => !!el.__x).forEach(el => { | ||
el.__x.updateElements(el) | ||
@@ -73,20 +100,42 @@ }) | ||
on(name, callback) { | ||
return this.events.on(name, callback) | ||
}, | ||
retrieveFromLocalStorage(name, methods = {}) { | ||
const storage = JSON.parse(window.localStorage.getItem(`__spruce:${name}`)) | ||
once(name, callback) { | ||
return this.events.once(name, callback) | ||
return storage ? Object.assign(methods, storage) : null | ||
}, | ||
off(name, callback) { | ||
this.events.off(name, callback) | ||
updateLocalStorage(name) { | ||
window.localStorage.setItem(`__spruce:${name}`, JSON.stringify(this.store(name))) | ||
}, | ||
emit(name, data = {}) { | ||
this.events.emit(name, { ...data, store: this.stores }) | ||
watch(name, callback) { | ||
if (!this.watchers[name]) { | ||
this.watchers[name] = [] | ||
} | ||
this.watchers[name].push(callback) | ||
}, | ||
watch(dotNotation, callback) { | ||
this.events.watch(dotNotation, callback) | ||
runWatchers(stores, target, key, value) { | ||
const self = this | ||
if (self.watchers[key]) { | ||
return self.watchers[key].forEach(callback => callback(value)) | ||
} | ||
Object.keys(self.watchers) | ||
.filter(watcher => watcher.includes('.')) | ||
.forEach(fullDotNotationKey => { | ||
let dotNotationParts = fullDotNotationKey.split('.') | ||
if (key !== dotNotationParts[dotNotationParts.length - 1]) return | ||
dotNotationParts.reduce((comparison, part) => { | ||
if (comparison[key] === target[key] || Object.is(target, comparison)) { | ||
self.watchers[fullDotNotationKey].forEach(callback => callback(value)) | ||
} | ||
return comparison[part] | ||
}, stores) | ||
}) | ||
} | ||
@@ -93,0 +142,0 @@ } |
@@ -11,12 +11,2 @@ export const domReady = () => { | ||
export const buildInitExpression = el => { | ||
let expression = "$store = Spruce.subscribe($el)" | ||
if (el.hasAttribute('x-init')) { | ||
expression = `${expression}; ${el.getAttribute('x-init')}` | ||
} | ||
return expression | ||
} | ||
export const isNullOrUndefined = value => { | ||
@@ -30,2 +20,10 @@ return value === null || value === undefined | ||
export const isArray = _ => Array.isArray(_) | ||
export const isArray = _ => Array.isArray(_) | ||
export const getMethods = obj => { | ||
let methods = {} | ||
Object.entries(obj).filter(([key, value]) => typeof value === 'function').forEach(([key, value]) => methods[key] = value) | ||
return methods | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
59222
489
240