Skip to content

Instantly share code, notes, and snippets.

@danybeltran
Last active May 4, 2022 16:57
Show Gist options
  • Save danybeltran/6057e377f94ff76110ce4c67d31dc34c to your computer and use it in GitHub Desktop.
Save danybeltran/6057e377f94ff76110ce4c67d31dc34c to your computer and use it in GitHub Desktop.
atomic-state for browsers
"use strict"
/** @license Atomic State
* Copyright (c) Dany Beltran
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var ReflectOwnKeys,
R = "object" == typeof Reflect ? Reflect : null,
ReflectApply =
R && "function" == typeof R.apply
? R.apply
: function (e, t, n) {
return Function.prototype.apply.call(e, t, n)
}
function ProcessEmitWarning(e) {
console && console.warn && console.warn(e)
}
ReflectOwnKeys =
R && "function" == typeof R.ownKeys
? R.ownKeys
: Object.getOwnPropertySymbols
? function (e) {
return Object.getOwnPropertyNames(e).concat(
Object.getOwnPropertySymbols(e)
)
}
: function (e) {
return Object.getOwnPropertyNames(e)
}
var NumberIsNaN =
Number.isNaN ||
function (e) {
return e != e
}
function EventEmitter() {
EventEmitter.init.call(this)
}
;(EventEmitter.EventEmitter = EventEmitter),
(EventEmitter.prototype._events = void 0),
(EventEmitter.prototype._eventsCount = 0),
(EventEmitter.prototype._maxListeners = void 0)
var defaultMaxListeners = 10
function checkListener(e) {
if ("function" != typeof e)
throw new TypeError(
'The "listener" argument must be of type Function. Received type ' +
typeof e
)
}
function _getMaxListeners(e) {
return void 0 === e._maxListeners
? EventEmitter.defaultMaxListeners
: e._maxListeners
}
function _addListener(e, t, n, r) {
var i, o, s
if (
(checkListener(n),
void 0 === (o = e._events)
? ((o = e._events = Object.create(null)), (e._eventsCount = 0))
: (void 0 !== o.newListener &&
(e.emit("newListener", t, n.listener ? n.listener : n),
(o = e._events)),
(s = o[t])),
void 0 === s)
)
(s = o[t] = n), ++e._eventsCount
else if (
("function" == typeof s
? (s = o[t] = r ? [n, s] : [s, n])
: r
? s.unshift(n)
: s.push(n),
(i = _getMaxListeners(e)) > 0 && s.length > i && !s.warned)
) {
s.warned = !0
var a = new Error(
"Possible EventEmitter memory leak detected. " +
s.length +
" " +
String(t) +
" listeners added. Use emitter.setMaxListeners() to increase limit"
)
;(a.name = "MaxListenersExceededWarning"),
(a.emitter = e),
(a.type = t),
(a.count = s.length),
ProcessEmitWarning(a)
}
return e
}
function onceWrapper() {
if (!this.fired)
return (
this.target.removeListener(this.type, this.wrapFn),
(this.fired = !0),
0 === arguments.length
? this.listener.call(this.target)
: this.listener.apply(this.target, arguments)
)
}
function _onceWrap(e, t, n) {
var r = { fired: !1, wrapFn: void 0, target: e, type: t, listener: n },
i = onceWrapper.bind(r)
return (i.listener = n), (r.wrapFn = i), i
}
function _listeners(e, t, n) {
var r = e._events
if (void 0 === r) return []
var i = r[t]
return void 0 === i
? []
: "function" == typeof i
? n
? [i.listener || i]
: [i]
: n
? unwrapListeners(i)
: arrayClone(i, i.length)
}
function listenerCount(e) {
var t = this._events
if (void 0 !== t) {
var n = t[e]
if ("function" == typeof n) return 1
if (void 0 !== n) return n.length
}
return 0
}
function arrayClone(e, t) {
for (var n = new Array(t), r = 0; r < t; ++r) n[r] = e[r]
return n
}
function spliceOne(e, t) {
for (; t + 1 < e.length; t++) e[t] = e[t + 1]
e.pop()
}
function unwrapListeners(e) {
for (var t = new Array(e.length), n = 0; n < t.length; ++n)
t[n] = e[n].listener || e[n]
return t
}
function once(e, t) {
return new Promise(function (n, r) {
function i(n) {
e.removeListener(t, o), r(n)
}
function o() {
"function" == typeof e.removeListener && e.removeListener("error", i),
n([].slice.call(arguments))
}
eventTargetAgnosticAddListener(e, t, o, { once: !0 }),
"error" !== t && addErrorHandlerIfEventEmitter(e, i, { once: !0 })
})
}
function addErrorHandlerIfEventEmitter(e, t, n) {
"function" == typeof e.on && eventTargetAgnosticAddListener(e, "error", t, n)
}
function eventTargetAgnosticAddListener(e, t, n, r) {
if ("function" == typeof e.on) r.once ? e.once(t, n) : e.on(t, n)
else {
if ("function" != typeof e.addEventListener)
throw new TypeError(
'The "emitter" argument must be of type EventEmitter. Received type ' +
typeof e
)
e.addEventListener(t, function i(o) {
r.once && e.removeEventListener(t, i), n(o)
})
}
}
Object.defineProperty(EventEmitter, "defaultMaxListeners", {
enumerable: !0,
get: function () {
return defaultMaxListeners
},
set: function (e) {
if ("number" != typeof e || e < 0 || NumberIsNaN(e))
throw new RangeError(
'The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' +
e +
"."
)
defaultMaxListeners = e
}
}),
(EventEmitter.init = function () {
;(void 0 !== this._events &&
this._events !== Object.getPrototypeOf(this)._events) ||
((this._events = Object.create(null)), (this._eventsCount = 0)),
(this._maxListeners = this._maxListeners || void 0)
}),
(EventEmitter.prototype.setMaxListeners = function (e) {
if ("number" != typeof e || e < 0 || NumberIsNaN(e))
throw new RangeError(
'The value of "n" is out of range. It must be a non-negative number. Received ' +
e +
"."
)
return (this._maxListeners = e), this
}),
(EventEmitter.prototype.getMaxListeners = function () {
return _getMaxListeners(this)
}),
(EventEmitter.prototype.emit = function (e) {
for (var t = [], n = 1; n < arguments.length; n++) t.push(arguments[n])
var r = "error" === e,
i = this._events
if (void 0 !== i) r = r && void 0 === i.error
else if (!r) return !1
if (r) {
var o
if ((t.length > 0 && (o = t[0]), o instanceof Error)) throw o
var s = new Error("Unhandled error." + (o ? " (" + o.message + ")" : ""))
throw ((s.context = o), s)
}
var a = i[e]
if (void 0 === a) return !1
if ("function" == typeof a) ReflectApply(a, this, t)
else {
var u = a.length,
c = arrayClone(a, u)
for (n = 0; n < u; ++n) ReflectApply(c[n], this, t)
}
return !0
}),
(EventEmitter.prototype.addListener = function (e, t) {
return _addListener(this, e, t, !1)
}),
(EventEmitter.prototype.on = EventEmitter.prototype.addListener),
(EventEmitter.prototype.prependListener = function (e, t) {
return _addListener(this, e, t, !0)
}),
(EventEmitter.prototype.once = function (e, t) {
return checkListener(t), this.on(e, _onceWrap(this, e, t)), this
}),
(EventEmitter.prototype.prependOnceListener = function (e, t) {
return (
checkListener(t), this.prependListener(e, _onceWrap(this, e, t)), this
)
}),
(EventEmitter.prototype.removeListener = function (e, t) {
var n, r, i, o, s
if ((checkListener(t), void 0 === (r = this._events))) return this
if (void 0 === (n = r[e])) return this
if (n === t || n.listener === t)
0 == --this._eventsCount
? (this._events = Object.create(null))
: (delete r[e],
r.removeListener && this.emit("removeListener", e, n.listener || t))
else if ("function" != typeof n) {
for (i = -1, o = n.length - 1; o >= 0; o--)
if (n[o] === t || n[o].listener === t) {
;(s = n[o].listener), (i = o)
break
}
if (i < 0) return this
0 === i ? n.shift() : spliceOne(n, i),
1 === n.length && (r[e] = n[0]),
void 0 !== r.removeListener && this.emit("removeListener", e, s || t)
}
return this
}),
(EventEmitter.prototype.off = EventEmitter.prototype.removeListener),
(EventEmitter.prototype.removeAllListeners = function (e) {
var t, n, r
if (void 0 === (n = this._events)) return this
if (void 0 === n.removeListener)
return (
0 === arguments.length
? ((this._events = Object.create(null)), (this._eventsCount = 0))
: void 0 !== n[e] &&
(0 == --this._eventsCount
? (this._events = Object.create(null))
: delete n[e]),
this
)
if (0 === arguments.length) {
var i,
o = Object.keys(n)
for (r = 0; r < o.length; ++r)
"removeListener" !== (i = o[r]) && this.removeAllListeners(i)
return (
this.removeAllListeners("removeListener"),
(this._events = Object.create(null)),
(this._eventsCount = 0),
this
)
}
if ("function" == typeof (t = n[e])) this.removeListener(e, t)
else if (void 0 !== t)
for (r = t.length - 1; r >= 0; r--) this.removeListener(e, t[r])
return this
}),
(EventEmitter.prototype.listeners = function (e) {
return _listeners(this, e, !0)
}),
(EventEmitter.prototype.rawListeners = function (e) {
return _listeners(this, e, !1)
}),
(EventEmitter.listenerCount = function (e, t) {
return "function" == typeof e.listenerCount
? e.listenerCount(t)
: listenerCount.call(e, t)
}),
(EventEmitter.prototype.listenerCount = listenerCount),
(EventEmitter.prototype.eventNames = function () {
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []
})
var __awaiter =
(this && this.__awaiter) ||
function (thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P
? value
: new P(function (resolve) {
resolve(value)
})
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value))
} catch (e) {
reject(e)
}
}
function rejected(value) {
try {
step(generator["throw"](value))
} catch (e) {
reject(e)
}
}
function step(result) {
result.done
? resolve(result.value)
: adopt(result.value).then(fulfilled, rejected)
}
step((generator = generator.apply(thisArg, _arguments || [])).next())
})
}
var __generator =
(this && this.__generator) ||
function (thisArg, body) {
var _ = {
label: 0,
sent: function () {
if (t[0] & 1) throw t[1]
return t[1]
},
trys: [],
ops: []
},
f,
y,
t,
g
return (
(g = { next: verb(0), throw: verb(1), return: verb(2) }),
typeof Symbol === "function" &&
(g[Symbol.iterator] = function () {
return this
}),
g
)
function verb(n) {
return function (v) {
return step([n, v])
}
}
function step(op) {
if (f) throw new TypeError("Generator is already executing.")
while (_)
try {
if (
((f = 1),
y &&
(t =
op[0] & 2
? y["return"]
: op[0]
? y["throw"] || ((t = y["return"]) && t.call(y), 0)
: y.next) &&
!(t = t.call(y, op[1])).done)
)
return t
if (((y = 0), t)) op = [op[0] & 2, t.value]
switch (op[0]) {
case 0:
case 1:
t = op
break
case 4:
_.label++
return { value: op[1], done: false }
case 5:
_.label++
y = op[1]
op = [0]
continue
case 7:
op = _.ops.pop()
_.trys.pop()
continue
default:
if (
!((t = _.trys), (t = t.length > 0 && t[t.length - 1])) &&
(op[0] === 6 || op[0] === 2)
) {
_ = 0
continue
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1]
break
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1]
t = op
break
}
if (t && _.label < t[2]) {
_.label = t[2]
_.ops.push(op)
break
}
if (t[2]) _.ops.pop()
_.trys.pop()
continue
}
op = body.call(thisArg, _)
} catch (e) {
op = [6, e]
y = 0
} finally {
f = t = 0
}
if (op[0] & 5) throw op[1]
return { value: op[0] ? op[1] : void 0, done: true }
}
}
var events_1 = { EventEmitter: EventEmitter }
var React = React
var atomEmitters = {}
function createEmitter() {
var emitter = new events_1.EventEmitter()
emitter.setMaxListeners(10e12)
function notify(storeName, hookCall, payload) {
if (payload === void 0) {
payload = {}
}
emitter.emit(storeName, { hookCall: hookCall, payload: payload })
}
return {
emitter: emitter,
notify: notify
}
}
var defaultAtomsValues = {}
var pendingAtoms = {}
var AtomicState = function (_a) {
var children = _a.children,
atoms = _a.atoms,
filters = _a.filters
if (atoms) {
for (var atomKey in atoms) {
defaultAtomsValues[atomKey] = atoms[atomKey]
}
}
if (filters) {
for (var filterKey in filters) {
defaultFiltersValues[filterKey] = filters[filterKey]
}
}
return children
}
window.AtomicState = AtomicState
function useAtomCreate(init) {
var _this = this
var hookCall = (0, React.useMemo)(function () {
return "".concat(Math.random()).split(".")[1]
}, [])
var isDefined = typeof init.default !== "undefined"
var initialValue = (function getInitialValue() {
var isFunction =
typeof defaultAtomsValues[init.name] === "undefined" &&
typeof init.default === "function"
var initVal = isDefined
? typeof defaultAtomsValues[init.name] === "undefined"
? init.default
: defaultAtomsValues[init.name]
: defaultAtomsValues[init.name]
try {
return init.localStoragePersistence
? typeof localStorage !== "undefined"
? typeof localStorage["store-".concat(init.name)] !== "undefined"
? JSON.parse(localStorage["store-".concat(init.name)])
: isFunction
? undefined
: initVal
: isFunction
? undefined
: initVal
: isFunction
? undefined
: initVal
} catch (err) {
return initVal
}
})()
var _a = (0, React.useState)(
(initialValue instanceof Promise || typeof initialValue === "function") &&
typeof defaultAtomsValues[init.name] === "undefined"
? undefined
: initialValue
),
state = _a[0],
setState = _a[1]
if (!pendingAtoms[init.name]) {
pendingAtoms[init.name] = 0
}
if (!atomEmitters[init.name]) {
atomEmitters[init.name] = createEmitter()
}
var _b = atomEmitters[init.name],
emitter = _b.emitter,
notify = _b.notify
var updateState = (0, React.useCallback)(
function (v) {
setState(function (previous) {
// First notify other subscribers
var newValue = typeof v === "function" ? v(previous) : v
defaultAtomsValues[init.name] = newValue
notify(init.name, hookCall, newValue)
// Finally update state
return newValue
})
},
[hookCall, notify, init.name]
)
;(0, React.useEffect)(
function () {
function getPromiseInitialValue() {
return __awaiter(this, void 0, void 0, function () {
var v
var _this = this
return __generator(this, function (_a) {
// Only resolve promise if default or resolved value are not present
if (typeof defaultAtomsValues[init.name] === "undefined") {
if (typeof init.default === "function") {
if (pendingAtoms[init.name] === 0) {
pendingAtoms[init.name] += 1
v =
typeof init.default !== "undefined"
? (function () {
return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [
2 /*return*/,
typeof init.default === "function"
? init.default()
: init.default
]
})
})
})()
: undefined
if (typeof v !== "undefined") {
v.then(function (val) {
defaultAtomsValues[init.name] = val
updateState(val)
})
}
} else {
pendingAtoms[init.name] += 1
if (state || defaultAtomsValues[init.name]) {
atomEmitters[init.name].notify(
init.name,
hookCall,
state || defaultAtomsValues[init.name]
)
}
}
}
}
return [2 /*return*/]
})
})
}
getPromiseInitialValue()
},
[state, init.default, updateState, init.name, hookCall]
)
;(0, React.useEffect)(
function () {
return function () {
pendingAtoms[init.name] = 0
}
},
[init.name]
)
;(0, React.useEffect)(function () {
var handler = function (e) {
return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (e.hookCall !== hookCall) {
setState(e.payload)
}
return [2 /*return*/]
})
})
}
emitter.addListener(init.name, handler)
return function () {
emitter.removeListener(init.name, handler)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
;(0, React.useEffect)(
function () {
if (typeof localStorage !== "undefined") {
if (init.localStoragePersistence) {
localStorage.setItem(
"store-".concat(init.name),
JSON.stringify(state)
)
} else {
if (typeof localStorage["store-".concat(init.name)] !== "undefined") {
localStorage.removeItem("store-".concat(init.name))
}
}
}
},
[init.name, init.localStoragePersistence, state]
)
// eslint-disable-next-line react-hooks/exhaustive-deps
var actions = (0, React.useMemo)(function () {
return init.actions || {}
}, [])
var __actions = (0, React.useMemo)(
function () {
return Object.fromEntries(
Object.keys(actions).map(function (key) {
return [
key,
function (args) {
return actions[key]({
args: args,
state: state,
dispatch: updateState
})
}
]
})
)
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[state]
)
return [state, updateState, __actions]
}
/**
* Creates an atom containing state
*/
function atom(init) {
var useCreate = function () {
return useAtomCreate(init)
}
useCreate["atom-name"] = init.name
return useCreate
}
var defaultFiltersValues = {}
function filter(_a) {
var name = _a.name,
get = _a.get
var filterDeps = {}
var getObject = {
get: function (atom) {
filterDeps[atom["atom-name"]] = true
return defaultAtomsValues[atom["atom-name"]]
}
}
var useFilterGet = function () {
var initialValue = defaultFiltersValues["".concat(name)] || get(getObject)
;(0, React.useEffect)(function () {
get(getObject)
}, [])
var _a = (0, React.useState)(
initialValue instanceof Promise || typeof initialValue === "undefined"
? undefined
: initialValue
),
filterValue = _a[0],
setFilterValue = _a[1]
;(0, React.useEffect)(
function () {
var _a
function renderValue(e) {
setTimeout(function () {
var newValue = get(getObject)
if (newValue instanceof Promise) {
newValue.then(function (v) {
defaultFiltersValues["".concat(name)] = newValue
setFilterValue(v)
})
} else {
defaultFiltersValues["".concat(name)] = newValue
setFilterValue(newValue)
}
}, 0)
}
for (var dep in filterDeps) {
;(_a = atomEmitters[dep]) === null || _a === void 0
? void 0
: _a.emitter.addListener(dep, renderValue)
}
return function () {
var _a
for (var dep in filterDeps) {
;(_a = atomEmitters[dep]) === null || _a === void 0
? void 0
: _a.emitter.removeListener(dep, renderValue)
}
}
},
[filterValue]
)
return filterValue
}
useFilterGet["filter-name"] = name
return useFilterGet
}
function useFilter(f) {
return f()
}
/**
* Get an atom's value and state setter
*/
function useAtom(atom) {
return atom()
}
/**
* Get an atom's value
*/
function useValue(atom) {
return atom()[0]
}
/**
* Get the function that updates the atom's value
*/
function useDispatch(atom) {
return atom()[1]
}
/**
* Get the actions of the atom as reducers
*/
function useActions(atom) {
return atom()[2]
}
// Selectors section
// localStorage utilities for web apps
var storageEmitter = (function () {
var emm = new events_1.EventEmitter()
emm.setMaxListeners(Math.pow(10, 10))
return emm
})()
function useStorage() {
var _a = (0, React.useState)({}),
keys = _a[0],
setKeys = _a[1]
function updateStore() {
return __awaiter(this, void 0, void 0, function () {
var $keys, k
return __generator(this, function (_a) {
$keys = {}
if (typeof localStorage !== "undefined") {
for (k in localStorage) {
if (!k.match(/clear|getItem|key|length|removeItem|setItem/)) {
try {
$keys[k] = JSON.parse(localStorage[k])
} catch (err) {
$keys[k] = localStorage[k]
}
}
}
}
setKeys($keys)
return [2 /*return*/]
})
})
}
;(0, React.useEffect)(function () {
updateStore()
}, [])
;(0, React.useEffect)(function () {
storageEmitter.addListener("store-changed", updateStore)
return function () {
storageEmitter.removeListener("store-changes", updateStore)
}
}, [])
return keys
}
const storage = {
set: function (k, v) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (typeof localStorage !== "undefined") {
if (typeof localStorage.setItem === "function") {
localStorage.setItem(k, JSON.stringify(v))
storageEmitter.emit("store-changed", v)
}
}
return [2 /*return*/]
})
})
},
remove: function (k) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (typeof localStorage !== "undefined") {
if (typeof localStorage.removeItem === "function") {
localStorage.removeItem(k)
storageEmitter.emit("store-changed", {})
}
}
return [2 /*return*/]
})
})
},
get: function (k) {
if (typeof localStorage !== "undefined") {
if (typeof localStorage.getItem === "function") {
try {
return JSON.parse(localStorage.getItem(k))
} catch (err) {
return ""
}
} else {
try {
return JSON.parse(localStorage[k])
} catch (err) {
return ""
}
}
}
}
}
"use strict";var ReflectOwnKeys,R="object"==typeof Reflect?Reflect:null,ReflectApply=R&&"function"==typeof R.apply?R.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};function ProcessEmitWarning(e){console&&console.warn&&console.warn(e)}ReflectOwnKeys=R&&"function"==typeof R.ownKeys?R.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var NumberIsNaN=Number.isNaN||function(e){return e!=e};function EventEmitter(){EventEmitter.init.call(this)}EventEmitter.EventEmitter=EventEmitter,EventEmitter.prototype._events=void 0,EventEmitter.prototype._eventsCount=0,EventEmitter.prototype._maxListeners=void 0;var defaultMaxListeners=10;function checkListener(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function _getMaxListeners(e){return void 0===e._maxListeners?EventEmitter.defaultMaxListeners:e._maxListeners}function _addListener(e,t,n,r){var i,o,a;if(checkListener(n),void 0===(o=e._events)?(o=e._events=Object.create(null),e._eventsCount=0):(void 0!==o.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),o=e._events),a=o[t]),void 0===a)a=o[t]=n,++e._eventsCount;else if("function"==typeof a?a=o[t]=r?[n,a]:[a,n]:r?a.unshift(n):a.push(n),(i=_getMaxListeners(e))>0&&a.length>i&&!a.warned){a.warned=!0;var s=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");s.name="MaxListenersExceededWarning",s.emitter=e,s.type=t,s.count=a.length,ProcessEmitWarning(s)}return e}function onceWrapper(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function _onceWrap(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},i=onceWrapper.bind(r);return i.listener=n,r.wrapFn=i,i}function _listeners(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];return void 0===i?[]:"function"==typeof i?n?[i.listener||i]:[i]:n?unwrapListeners(i):arrayClone(i,i.length)}function listenerCount(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function arrayClone(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}function spliceOne(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}function unwrapListeners(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}function once(e,t){return new Promise(function(n,r){function i(n){e.removeListener(t,o),r(n)}function o(){"function"==typeof e.removeListener&&e.removeListener("error",i),n([].slice.call(arguments))}eventTargetAgnosticAddListener(e,t,o,{once:!0}),"error"!==t&&addErrorHandlerIfEventEmitter(e,i,{once:!0})})}function addErrorHandlerIfEventEmitter(e,t,n){"function"==typeof e.on&&eventTargetAgnosticAddListener(e,"error",t,n)}function eventTargetAgnosticAddListener(e,t,n,r){if("function"==typeof e.on)r.once?e.once(t,n):e.on(t,n);else{if("function"!=typeof e.addEventListener)throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type '+typeof e);e.addEventListener(t,function i(o){r.once&&e.removeEventListener(t,i),n(o)})}}Object.defineProperty(EventEmitter,"defaultMaxListeners",{enumerable:!0,get:function(){return defaultMaxListeners},set:function(e){if("number"!=typeof e||e<0||NumberIsNaN(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");defaultMaxListeners=e}}),EventEmitter.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},EventEmitter.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||NumberIsNaN(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},EventEmitter.prototype.getMaxListeners=function(){return _getMaxListeners(this)},EventEmitter.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var r="error"===e,i=this._events;if(void 0!==i)r=r&&void 0===i.error;else if(!r)return!1;if(r){var o;if(t.length>0&&(o=t[0]),o instanceof Error)throw o;var a=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw a.context=o,a}var s=i[e];if(void 0===s)return!1;if("function"==typeof s)ReflectApply(s,this,t);else{var u=s.length,c=arrayClone(s,u);for(n=0;n<u;++n)ReflectApply(c[n],this,t)}return!0},EventEmitter.prototype.addListener=function(e,t){return _addListener(this,e,t,!1)},EventEmitter.prototype.on=EventEmitter.prototype.addListener,EventEmitter.prototype.prependListener=function(e,t){return _addListener(this,e,t,!0)},EventEmitter.prototype.once=function(e,t){return checkListener(t),this.on(e,_onceWrap(this,e,t)),this},EventEmitter.prototype.prependOnceListener=function(e,t){return checkListener(t),this.prependListener(e,_onceWrap(this,e,t)),this},EventEmitter.prototype.removeListener=function(e,t){var n,r,i,o,a;if(checkListener(t),void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(i=-1,o=n.length-1;o>=0;o--)if(n[o]===t||n[o].listener===t){a=n[o].listener,i=o;break}if(i<0)return this;0===i?n.shift():spliceOne(n,i),1===n.length&&(r[e]=n[0]),void 0!==r.removeListener&&this.emit("removeListener",e,a||t)}return this},EventEmitter.prototype.off=EventEmitter.prototype.removeListener,EventEmitter.prototype.removeAllListeners=function(e){var t,n,r;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var i,o=Object.keys(n);for(r=0;r<o.length;++r)"removeListener"!==(i=o[r])&&this.removeAllListeners(i);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(void 0!==t)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this},EventEmitter.prototype.listeners=function(e){return _listeners(this,e,!0)},EventEmitter.prototype.rawListeners=function(e){return _listeners(this,e,!1)},EventEmitter.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):listenerCount.call(e,t)},EventEmitter.prototype.listenerCount=listenerCount,EventEmitter.prototype.eventNames=function(){return this._eventsCount>0?ReflectOwnKeys(this._events):[]};var __awaiter=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function a(e){try{u(r.next(e))}catch(e){o(e)}}function s(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(a,s)}u((r=r.apply(e,t||[])).next())})},__generator=this&&this.__generator||function(e,t){var n,r,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(o){return function(s){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,r=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=(i=a.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){a.label=o[1];break}if(6===o[0]&&a.label<i[1]){a.label=i[1],i=o;break}if(i&&a.label<i[2]){a.label=i[2],a.ops.push(o);break}i[2]&&a.ops.pop(),a.trys.pop();continue}o=t.call(e,a)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,s])}}},events_1={EventEmitter:EventEmitter},React=React,atomEmitters={};function createEmitter(){var e=new events_1.EventEmitter;return e.setMaxListeners(1e13),{emitter:e,notify:function(t,n,r){void 0===r&&(r={}),e.emit(t,{hookCall:n,payload:r})}}}var defaultAtomsValues={},pendingAtoms={},AtomicState=function(e){var t=e.children,n=e.atoms,r=e.filters;if(n)for(var i in n)defaultAtomsValues[i]=n[i];if(r)for(var o in r)defaultFiltersValues[o]=r[o];return t};function useAtomCreate(e){var t=this,n=(0,React.useMemo)(function(){return"".concat(Math.random()).split(".")[1]},[]),r=void 0!==e.default,i=function(){var t=void 0===defaultAtomsValues[e.name]&&"function"==typeof e.default,n=r&&void 0===defaultAtomsValues[e.name]?e.default:defaultAtomsValues[e.name];try{return e.localStoragePersistence&&"undefined"!=typeof localStorage&&void 0!==localStorage["store-".concat(e.name)]?JSON.parse(localStorage["store-".concat(e.name)]):t?void 0:n}catch(e){return n}}(),o=(0,React.useState)((i instanceof Promise||"function"==typeof i)&&void 0===defaultAtomsValues[e.name]?void 0:i),a=o[0],s=o[1];pendingAtoms[e.name]||(pendingAtoms[e.name]=0),atomEmitters[e.name]||(atomEmitters[e.name]=createEmitter());var u=atomEmitters[e.name],c=u.emitter,f=u.notify,l=(0,React.useCallback)(function(t){s(function(r){var i="function"==typeof t?t(r):t;return defaultAtomsValues[e.name]=i,f(e.name,n,i),i})},[n,f,e.name]);(0,React.useEffect)(function(){!function(){__awaiter(this,void 0,void 0,function(){var t,r=this;return __generator(this,function(i){return void 0===defaultAtomsValues[e.name]&&"function"==typeof e.default&&(0===pendingAtoms[e.name]?(pendingAtoms[e.name]+=1,void 0!==(t=void 0!==e.default?__awaiter(r,void 0,void 0,function(){return __generator(this,function(t){return[2,"function"==typeof e.default?e.default():e.default]})}):void 0)&&t.then(function(t){defaultAtomsValues[e.name]=t,l(t)})):(pendingAtoms[e.name]+=1,(a||defaultAtomsValues[e.name])&&atomEmitters[e.name].notify(e.name,n,a||defaultAtomsValues[e.name]))),[2]})})}()},[a,e.default,l,e.name,n]),(0,React.useEffect)(function(){return function(){pendingAtoms[e.name]=0}},[e.name]),(0,React.useEffect)(function(){var r=function(e){return __awaiter(t,void 0,void 0,function(){return __generator(this,function(t){return e.hookCall!==n&&s(e.payload),[2]})})};return c.addListener(e.name,r),function(){c.removeListener(e.name,r)}},[]),(0,React.useEffect)(function(){"undefined"!=typeof localStorage&&(e.localStoragePersistence?localStorage.setItem("store-".concat(e.name),JSON.stringify(a)):void 0!==localStorage["store-".concat(e.name)]&&localStorage.removeItem("store-".concat(e.name)))},[e.name,e.localStoragePersistence,a]);var m=(0,React.useMemo)(function(){return e.actions||{}},[]),v=(0,React.useMemo)(function(){return Object.fromEntries(Object.keys(m).map(function(e){return[e,function(t){return m[e]({args:t,state:a,dispatch:l})}]}))},[a]);return[a,l,v]}function atom(e){var t=function(){return useAtomCreate(e)};return t["atom-name"]=e.name,t}window.AtomicState=AtomicState;var defaultFiltersValues={};function filter(e){var t=e.name,n=e.get,r={},i={get:function(e){return r[e["atom-name"]]=!0,defaultAtomsValues[e["atom-name"]]}},o=function(){var e=defaultFiltersValues["".concat(t)]||n(i);(0,React.useEffect)(function(){n(i)},[]);var o=(0,React.useState)(e instanceof Promise||void 0===e?void 0:e),a=o[0],s=o[1];return(0,React.useEffect)(function(){var e;function o(e){setTimeout(function(){var e=n(i);e instanceof Promise?e.then(function(n){defaultFiltersValues["".concat(t)]=e,s(n)}):(defaultFiltersValues["".concat(t)]=e,s(e))},0)}for(var a in r)null===(e=atomEmitters[a])||void 0===e||e.emitter.addListener(a,o);return function(){var e;for(var t in r)null===(e=atomEmitters[t])||void 0===e||e.emitter.removeListener(t,o)}},[a]),a};return o["filter-name"]=t,o}function useFilter(e){return e()}function useAtom(e){return e()}function useValue(e){return e()[0]}function useDispatch(e){return e()[1]}function useActions(e){return e()[2]}var storageEmitter=function(){var e=new events_1.EventEmitter;return e.setMaxListeners(Math.pow(10,10)),e}();function useStorage(){var e=(0,React.useState)({}),t=e[0],n=e[1];function r(){return __awaiter(this,void 0,void 0,function(){var e,t;return __generator(this,function(r){if(e={},"undefined"!=typeof localStorage)for(t in localStorage)if(!t.match(/clear|getItem|key|length|removeItem|setItem/))try{e[t]=JSON.parse(localStorage[t])}catch(n){e[t]=localStorage[t]}return n(e),[2]})})}return(0,React.useEffect)(function(){r()},[]),(0,React.useEffect)(function(){return storageEmitter.addListener("store-changed",r),function(){storageEmitter.removeListener("store-changes",r)}},[]),t}const storage={set:function(e,t){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(n){return"undefined"!=typeof localStorage&&"function"==typeof localStorage.setItem&&(localStorage.setItem(e,JSON.stringify(t)),storageEmitter.emit("store-changed",t)),[2]})})},remove:function(e){return __awaiter(this,void 0,void 0,function(){return __generator(this,function(t){return"undefined"!=typeof localStorage&&"function"==typeof localStorage.removeItem&&(localStorage.removeItem(e),storageEmitter.emit("store-changed",{})),[2]})})},get:function(e){if("undefined"!=typeof localStorage)if("function"==typeof localStorage.getItem)try{return JSON.parse(localStorage.getItem(e))}catch(e){return""}else try{return JSON.parse(localStorage[e])}catch(e){return""}}};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script
src="https://unpkg.com/react@18/umd/react.production.min.js"
crossorigin
></script>
<script type="text/babel" src="https://gist.githubusercontent.com/danybeltran/6057e377f94ff76110ce4c67d31dc34c/raw/[email protected]"></script>
<script
src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"
crossorigin
></script>
<title>Static Template</title>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const countAtom = atom({
name: "counter"
// default: 0,
// localStoragePersistence: true
})
function App() {
const [count, setCount] = useAtom(countAtom)
return (
<div>
<h2>Atomic state in browser, {count}</h2>
<button
onClick={() => {
setCount((c) => c + 1)
}}
>
+
</button>
</div>
)
}
const domContainer = document.querySelector("#root")
const root = ReactDOM.createRoot(domContainer)
root.render(
<AtomicState
atoms={{
counter: 10
}}
>
<App />
</AtomicState>
)
</script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment