UNPKG

preact-context

Version:
187 lines (175 loc) 8.24 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('preact')) : typeof define === 'function' && define.amd ? define(['exports', 'preact'], factory) : (global = global || self, factory(global.preactContext = {}, global.preact)); }(this, function (exports, preact) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function createEmitter(initialValue, bitmaskFactory) { var registeredUpdaters = []; var value = initialValue; var diff = function (newValue) { return bitmaskFactory(value, newValue) | 0; }; return { register: function (updater) { registeredUpdaters.push(updater); updater(value, diff(value)); }, unregister: function (updater) { registeredUpdaters = registeredUpdaters.filter(function (i) { return i !== updater; }); }, val: function (newValue) { if (newValue === undefined || newValue == value) { return value; } var bitmask = diff(newValue); value = newValue; registeredUpdaters.forEach(function (up) { return up(newValue, bitmask); }); return value; } }; } var noopEmitter = { register: function (_) { console.warn("Consumer used without a Provider"); }, unregister: function (_) { // do nothing }, val: function (_) { //do nothing; } }; /* * Extracts the children from the props and returns an object containing the * only element of the given array (preact always passes children as an array) * or null otherwise. The result contains always a reference to the original * array of children * * @param {RenderableProps<*>} props - the component's properties * @return {{ child: JSX.Element | null, children: JSX.Element[]}} */ function getOnlyChildAndChildren(props) { var children = props.children; var child = children.length === 1 ? children[0] : null; return { child: child, children: children }; } function getRenderer(props) { var child = getOnlyChildAndChildren(props).child; // TODO: "render" in props check is only done to make TS happy return child || ("render" in props && props.render); } var MAX_SIGNED_31_BIT_INT = 1073741823; var defaultBitmaskFactory = function () { return MAX_SIGNED_31_BIT_INT; }; var ids = 0; function _createContext(value, bitmaskFactory) { var key = "_preactContextProvider-" + ids++; var Provider = /** @class */ (function (_super) { __extends(Provider, _super); function Provider(props) { var _this = _super.call(this, props) || this; _this._emitter = createEmitter(props.value, bitmaskFactory || defaultBitmaskFactory); return _this; } Provider.prototype.getChildContext = function () { var _a; return _a = {}, _a[key] = this._emitter, _a; }; Provider.prototype.componentDidUpdate = function () { this._emitter.val(this.props.value); }; Provider.prototype.render = function () { var _a = getOnlyChildAndChildren(this.props), child = _a.child, children = _a.children; if (child) { return child; } // preact does not support fragments, // therefore we wrap the children in a span return preact.h("span", null, children); }; return Provider; }(preact.Component)); var Consumer = /** @class */ (function (_super) { __extends(Consumer, _super); function Consumer(props, ctx) { var _this = _super.call(this, props, ctx) || this; _this._updateContext = function (value, bitmask) { var unstable_observedBits = _this.props.unstable_observedBits; var observed = unstable_observedBits === undefined || unstable_observedBits === null ? MAX_SIGNED_31_BIT_INT : unstable_observedBits; observed = observed | 0; if ((observed & bitmask) === 0) { return; } _this.setState({ value: value }); }; _this.state = { value: _this._getEmitter().val() || value }; return _this; } Consumer.prototype.componentDidMount = function () { this._getEmitter().register(this._updateContext); }; Consumer.prototype.shouldComponentUpdate = function (nextProps, nextState) { return (this.state.value !== nextState.value || getRenderer(this.props) !== getRenderer(nextProps)); }; Consumer.prototype.componentWillUnmount = function () { this._getEmitter().unregister(this._updateContext); }; Consumer.prototype.componentDidUpdate = function (_, __, prevCtx) { var previousProvider = prevCtx[key]; if (previousProvider === this.context[key]) { return; } (previousProvider || noopEmitter).unregister(this._updateContext); this.componentDidMount(); }; Consumer.prototype.render = function () { // TODO: "render" in props check is only done to make TS happy var render = "render" in this.props && this.props.render; var r = getRenderer(this.props); if (render && render !== r) { console.warn("Both children and a render function are defined. Children will be used"); } if (typeof r === "function") { return r(this.state.value); } console.warn("Consumer is expecting a function as one and only child but didn't find any"); }; Consumer.prototype._getEmitter = function () { return this.context[key] || noopEmitter; }; return Consumer; }(preact.Component)); return { Provider: Provider, Consumer: Consumer }; } var createContext = _createContext; exports.default = _createContext; exports.createContext = createContext; Object.defineProperty(exports, '__esModule', { value: true }); }));