UNPKG

fluxel

Version:

An ultra-lightweight, high-performance library for efficient DOM building and dynamic web UIs

272 lines (271 loc) 10 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { default: function() { return _default; }, pureStateReservedKeys: function() { return pureStateReservedKeys; } }); const _index = /*#__PURE__*/ _interop_require_default(require("./index.js")); const _internalStore = require("./internalStore.js"); const _reactiveDependency = /*#__PURE__*/ _interop_require_default(require("./reactiveDependency.js")); function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _object_spread(target) { for(var i = 1; i < arguments.length; i++){ var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === "function") { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function(key) { _define_property(target, key, source[key]); }); } return target; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function(sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _object_spread_props(target, source) { source = source != null ? source : {}; if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function(key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } const Fluxel = _index.default; const pureStateReservedKeys = [ "render", "use", "useWithMemo", "listenTarget" ]; Fluxel.reactive = function(initialState, renderer) { const stateListenerMap = Object.create(null); const pureState = _object_spread_props(_object_spread({}, initialState), { render: (targetProperty, skipEventDispatch = false)=>{ if (!skipEventDispatch && targetProperty) { pureState.listenTarget.dispatchEvent(new CustomEvent(targetProperty, { detail: { newValue: pureState[targetProperty] } })); } if (targetProperty) { var _stateListenerMap_targetProperty; (_stateListenerMap_targetProperty = stateListenerMap[targetProperty]) === null || _stateListenerMap_targetProperty === void 0 ? void 0 : _stateListenerMap_targetProperty.listeners.forEach((listener)=>listener.call(null)); } else { for(const key in stateListenerMap){ stateListenerMap[key].listeners.forEach((listener)=>listener.call(null)); } } }, use: (key, deriveFn)=>{ let memoIndex = -1; let usedMemoCount = -1; const memos = []; let usedPureMemos = new Map(); let pureMemos = new Map(); const memoize = (factory, deps, pure = false)=>{ if (pure) { const key = JSON.stringify(deps); if (pureMemos.has(key)) { const usedValue = pureMemos.get(key); usedPureMemos.set(key, usedValue); return usedValue; } const value = factory(); usedPureMemos.set(key, value); return value; } if (memos[memoIndex]) { if (memos[memoIndex].deps.every((d, i)=>d === deps[i])) { return memos[memoIndex++].memoValue; } memos[memoIndex].deps = deps; const newValue = memos[memoIndex].memoValue = factory(); memoIndex++; return newValue; } else { memos.push({ deps, memoValue: factory() }); return memos[memoIndex++].memoValue; } }; const memorableDeriveFn = deriveFn ? (v)=>{ if (memoIndex === -1 && usedMemoCount !== -1) { usedMemoCount = memoIndex; } memoIndex = 0; usedPureMemos = new Map(); const derived = deriveFn(v, memoize); if (usedMemoCount !== -1 && usedMemoCount !== memoIndex) { throw new TypeError("Memoization count mismatch"); } pureMemos = usedPureMemos; return derived; } : undefined; if (Array.isArray(key)) { const entries = key.map((k)=>[ k, pureState.use(k) ]); return new _reactiveDependency.default({ get: ()=>Object.fromEntries(entries.map((entry)=>[ entry[0], entry[1].value ])), set: (_)=>{ throw new TypeError("Invalid"); } }, (targetObj, dep)=>{ const throttledDep = createThrottledDep(dep); entries.forEach((entry)=>entry[1].addDependency(targetObj, throttledDep)); }).derive(memorableDeriveFn); } else { let dep; if (stateListenerMap[key]) { dep = stateListenerMap[key].dep; } else if (pureState[key] instanceof _reactiveDependency.default) { dep = pureState[key]; } else { dep = new _reactiveDependency.default({ get: ()=>pureState[key], set: (val)=>{ pureState[key] = val; } }, function addDependency(targetObj, dep) { if (!stateListenerMap[key].listeners.includes(dep)) { stateListenerMap[key].listeners.push(dep); const cleanupDep = ()=>{ stateListenerMap[key].listeners = stateListenerMap[key].listeners.filter((listener)=>listener !== dep); }; if (_internalStore.targetListenerMap.has(targetObj)) { _internalStore.targetListenerMap.get(targetObj).add(cleanupDep); } else { _internalStore.targetListenerMap.set(targetObj, new Set([ cleanupDep ])); } } }); stateListenerMap[key] = { dep, listeners: [] }; } if (memorableDeriveFn) { return dep.derive(memorableDeriveFn); } return dep; } }, useWithMemo: (key)=>{ let memo = null; const dep = pureState.use(key, (v, _memo)=>{ memo = _memo; return v; }); dep.value; return [ dep, memo ]; }, listenTarget: new EventTarget() }); const state = new Proxy(pureState, { set (target, prop, value) { if (pureStateReservedKeys.includes(prop)) { throw new TypeError(`Cannot set the specified property: ${String(prop)}`); } const oldValue = target[prop]; if (oldValue === value) { return true; } target[prop] = value; target.listenTarget.dispatchEvent(new CustomEvent(prop, { detail: { oldValue, newValue: value } })); target.render(prop); return true; } }); return renderer(state); }; Fluxel.schedule = function(fn) { if (typeof window !== "undefined") { setTimeout(fn, 0); } }; Fluxel.mergeDependencies = function(...deps) { return new _reactiveDependency.default({ get: ()=>deps.map((dep)=>dep.value), set: (val)=>{ throw new TypeError("Invalid operation"); } }, (targetObj, dep)=>{ const throttledDep = createThrottledDep(dep); deps.forEach((d)=>d.addDependency(targetObj, throttledDep)); }); }; function createThrottledDep(dep) { let depCallPending = false; return ()=>{ if (depCallPending) return; depCallPending = true; window.setTimeout(()=>{ depCallPending = false; dep(); }, 0); }; } const _default = Fluxel;