UNPKG

svelte

Version:

The magical disappearing UI framework

233 lines (185 loc) • 5.17 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.svelte = global.svelte || {}))); }(this, (function (exports) { 'use strict'; function assign(target) { var k, source, i = 1, len = arguments.length; for (; i < len; i++) { source = arguments[i]; for (k in source) target[k] = source[k]; } return target; } function blankObject() { return Object.create(null); } function differs(a, b) { return a !== b || ((a && typeof a === 'object') || typeof a === 'function'); } function dispatchObservers(component, group, changed, newState, oldState) { for (var key in group) { if (!changed[key]) continue; var newValue = newState[key]; var oldValue = oldState[key]; var callbacks = group[key]; if (!callbacks) continue; for (var i = 0; i < callbacks.length; i += 1) { var callback = callbacks[i]; if (callback.__calling) continue; callback.__calling = true; callback.call(component, newValue, oldValue); callback.__calling = false; } } } function get(key) { return key ? this._state[key] : this._state; } function observe(key, callback, options) { var group = options && options.defer ? this._observers.post : this._observers.pre; (group[key] || (group[key] = [])).push(callback); if (!options || options.init !== false) { callback.__calling = true; callback.call(this, this._state[key]); callback.__calling = false; } return { cancel: function() { var index = group[key].indexOf(callback); if (~index) group[key].splice(index, 1); } }; } function Store(state) { this._observers = { pre: blankObject(), post: blankObject() }; this._changeHandlers = []; this._dependents = []; this._computed = blankObject(); this._sortedComputedProperties = []; this._state = assign({}, state); } assign(Store.prototype, { _add: function(component, props) { this._dependents.push({ component: component, props: props }); }, _init: function(props) { var state = {}; for (var i = 0; i < props.length; i += 1) { var prop = props[i]; state['$' + prop] = this._state[prop]; } return state; }, _remove: function(component) { var i = this._dependents.length; while (i--) { if (this._dependents[i].component === component) { this._dependents.splice(i, 1); return; } } }, _sortComputedProperties: function() { var computed = this._computed; var sorted = this._sortedComputedProperties = []; var cycles; var visited = blankObject(); function visit(key) { if (cycles[key]) { throw new Error('Cyclical dependency detected'); } if (visited[key]) return; visited[key] = true; var c = computed[key]; if (c) { cycles[key] = true; c.deps.forEach(visit); sorted.push(c); } } for (var key in this._computed) { cycles = blankObject(); visit(key); } }, compute: function(key, deps, fn) { var store = this; var value; var c = { deps: deps, update: function(state, changed, dirty) { var values = deps.map(function(dep) { if (dep in changed) dirty = true; return state[dep]; }); if (dirty) { var newValue = fn.apply(null, values); if (differs(newValue, value)) { value = newValue; changed[key] = true; state[key] = value; } } } }; c.update(this._state, {}, true); this._computed[key] = c; this._sortComputedProperties(); }, get: get, observe: observe, onchange: function(callback) { this._changeHandlers.push(callback); return { cancel: function() { var index = this._changeHandlers.indexOf(callback); if (~index) this._changeHandlers.splice(index, 1); } }; }, set: function(newState) { var oldState = this._state, changed = this._changed = {}, dirty = false; for (var key in newState) { if (this._computed[key]) throw new Error("'" + key + "' is a read-only property"); if (differs(newState[key], oldState[key])) changed[key] = dirty = true; } if (!dirty) return; this._state = assign({}, oldState, newState); for (var i = 0; i < this._sortedComputedProperties.length; i += 1) { this._sortedComputedProperties[i].update(this._state, changed); } for (var i = 0; i < this._changeHandlers.length; i += 1) { this._changeHandlers[i](this._state, changed); } dispatchObservers(this, this._observers.pre, changed, this._state, oldState); var dependents = this._dependents.slice(); // guard against mutations for (var i = 0; i < dependents.length; i += 1) { var dependent = dependents[i]; var componentState = {}; dirty = false; for (var j = 0; j < dependent.props.length; j += 1) { var prop = dependent.props[j]; if (prop in changed) { componentState['$' + prop] = this._state[prop]; dirty = true; } } if (dirty) dependent.component.set(componentState); } dispatchObservers(this, this._observers.post, changed, this._state, oldState); } }); exports.Store = Store; Object.defineProperty(exports, '__esModule', { value: true }); })));