index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { domReady, getMethods } from './utils'
  2. import { createObservable } from './observable'
  3. const Spruce = {
  4. stores: {},
  5. persisted: [],
  6. subscribers: [],
  7. disableReactivity: false,
  8. async start() {
  9. await domReady()
  10. this.attach()
  11. document.addEventListener('turbolinks:render', this.attach)
  12. this.stores = createObservable(this.stores, {
  13. set: () => {
  14. if (this.disableReactivity) {
  15. return
  16. }
  17. this.updateSubscribers()
  18. this.disableReactivity = true
  19. this.persisted.forEach(this.updateLocalStorage.bind(this))
  20. this.disableReactivity = false
  21. }
  22. })
  23. },
  24. attach() {
  25. if (! window.Alpine) {
  26. throw new Error('[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.')
  27. }
  28. const self = this
  29. window.Alpine.addMagicProperty('store', el => {
  30. self.subscribe(el)
  31. return self.stores
  32. })
  33. },
  34. store(name, state, persist = false) {
  35. if (persist) {
  36. this.stores[name] = this.retrieveFromLocalStorage(name, getMethods(state))
  37. if (! this.persisted.includes(name)) {
  38. this.persisted.push(name)
  39. }
  40. }
  41. if (! this.stores[name]) {
  42. this.stores[name] = state
  43. }
  44. return this.stores[name]
  45. },
  46. reset(name, state) {
  47. this.stores[name] = state
  48. },
  49. subscribe(el) {
  50. if (! this.subscribers.includes(el)) {
  51. this.subscribers.push(el)
  52. }
  53. return this.stores
  54. },
  55. updateSubscribers() {
  56. this.subscribers.filter(el => !! el.__x).forEach(el => {
  57. el.__x.updateElements(el)
  58. })
  59. },
  60. retrieveFromLocalStorage(name, methods = {}) {
  61. const storage = JSON.parse(window.localStorage.getItem(`__spruce:${name}`))
  62. return storage ? Object.assign(methods, storage) : null
  63. },
  64. updateLocalStorage(name) {
  65. window.localStorage.setItem(`__spruce:${name}`, JSON.stringify(this.store(name)))
  66. }
  67. }
  68. const deferrer = window.deferLoadingAlpine || function (callback) { callback() }
  69. window.deferLoadingAlpine = function (callback) {
  70. window.Spruce = Spruce
  71. window.Spruce.start()
  72. deferrer(callback)
  73. }
  74. export default Spruce