Last active
January 24, 2020 20:46
-
-
Save porfirioribeiro/17adefa89a57985f4fe89c2aaef6771e to your computer and use it in GitHub Desktop.
preact-composition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { PreactContext, JSX, Component } from 'preact'; | |
export * from './store'; | |
type FC<P> = (props: P) => JSX.Element; | |
type createComponentFN<P> = (c: Component<P>) => FC<P>; | |
/** | |
* Wraps a FunctionalComponent to be handled with the composition api | |
* @param fn | |
*/ | |
export function createComponent<P>(fn: createComponentFN<P>): FC<P>; | |
export function memo<P = {}>(comparer?: (prev: P, next: P) => boolean): void; | |
export type ReactiveHolder<T extends {}> = T & { | |
// get or set the immutable inner value of this reactive | |
$value: T; | |
}; | |
/** | |
* Creates a Proxy around the `value` object that any time its change it will update the component | |
* @param value | |
*/ | |
export function reactive<T extends {}>(value: T): ReactiveHolder<T>; | |
export type ValueHolder<T> = { value: T }; | |
/** | |
* Returns a reference with a `value` property, that when it changes will update the component if not `staticRef` | |
* @param v | |
*/ | |
export function value<T>(v?: T): ValueHolder<T>; | |
export function unwrap<T>( | |
refOrValue: ValueHolder<T> | ReactiveHolder<T> | T | |
): T; | |
export function isReactive(v: any): boolean; | |
/** | |
* @param callback run on mount | |
*/ | |
export function onMounted(callback: () => void): void; | |
/** | |
* @param callback run on unmount | |
*/ | |
export function onUnmounted(cb: () => void): void; | |
export type EffectCallback<T> = ( | |
args: T, | |
oldArgs: T, | |
onCleanup: Function | |
) => void; | |
export type PropGetter<P, T> = (props: P) => T; | |
export type WatchSrc<T, P> = | |
| PropGetter<P, T> | |
| ValueHolder<T> | |
| ReactiveHolder<T> | |
| PreactContext<T>; | |
type WatchCb<T extends Array<any>, R> = (...value: T) => R; | |
export type WatchResult<T> = { readonly value: T }; | |
/** | |
* `watch` function can operate in many ways. | |
* | |
* Before each render all `watch`'ers are run or updated with the new value | |
* and if any args from src changed `callback` is called with the new args and the old args | |
* ```js | |
* watch(props => props.id) //returns `value` id props value (kinda irrelevant) | |
* watch(props => props.a + props.b) //acts like a compute function and returns a `value` summing props a + b | |
* watch(someValue, value => console.log('The value of someValue is: ', value)) | |
* ``` | |
* @param src | |
* @param callback optional callback to call if the args returned from src changed | |
* @returns `value` holding the result from the first `src` specified or the return of the `callback` | |
*/ | |
/** watch values */ | |
export function watch<P, T>(src: WatchSrc<T, P>): WatchResult<T>; | |
export function watch<P, T0, T1>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>] | |
): WatchResult<[T0, T1]>; | |
export function watch<P, T0, T1, T2>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>, WatchSrc<T2, P>] | |
): WatchResult<[T0, T1, T2]>; | |
/** watch values with a callback returning a promise and default value */ | |
export function watch<P, R>( | |
src: [], | |
cb: () => PromiseLike<R>, | |
def: R | |
): WatchResult<R>; | |
export function watch<P, T, R>( | |
src: WatchSrc<T, P>, | |
cb: (value: T) => PromiseLike<R>, | |
def: R | |
): WatchResult<R>; | |
export function watch<P, T0, T1, R>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>], | |
cb: WatchCb<[T0, T1], PromiseLike<R>>, | |
def: R | |
): WatchResult<R>; | |
export function watch<P, T0, T1, T2, R>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>, WatchSrc<T2, P>], | |
cb: WatchCb<[T0, T1, T2], PromiseLike<R>>, | |
def: R | |
): WatchResult<R>; | |
/** watch values with a callback returning a promise */ | |
export function watch<P, R>( | |
src: [], | |
cb: WatchCb<[], PromiseLike<R>> | |
): WatchResult<R | undefined>; | |
export function watch<P, T, R>( | |
src: WatchSrc<T, P>, | |
cb: WatchCb<[T], PromiseLike<R>> | |
): WatchResult<R | undefined>; | |
export function watch<P, T0, T1, R>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>], | |
cb: WatchCb<[T0, T1], PromiseLike<R>> | |
): WatchResult<R | undefined>; | |
export function watch<P, T0, T1, T2, R>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>, WatchSrc<T2, P>], | |
cb: WatchCb<[T0, T1, T2], PromiseLike<R>> | |
): WatchResult<R | undefined>; | |
/** watch values with a callback returning a value */ | |
export function watch<P, R>( | |
src: [], | |
cb: WatchCb<[], R> | |
): WatchResult<R>; | |
export function watch<P, T, R>( | |
src: WatchSrc<T, P>, | |
cb: WatchCb<[T], R> | |
): WatchResult<R>; | |
export function watch<P, T0, T1, R>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>], | |
cb: WatchCb<[T0, T1], R> | |
): WatchResult<R>; | |
export function watch<P, T0, T1, T2, R>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>, WatchSrc<T2, P>], | |
cb: WatchCb<[T0, T1, T2], R> | |
): WatchResult<R>; | |
/** | |
* `effect` its run after render it can also be used to callback when something changed | |
* The callback will receive newArgs, oldArgs and onCleanup to assign a cleanup function | |
* @param src | |
* @param callback optional callback to call if the args returned from src changed | |
* @returns nothing | |
*/ | |
export function effect<P, T>(src: WatchSrc<T, P>, cb: EffectCallback<T>): void; | |
export function effect<P, T0, T1>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>], | |
cb: EffectCallback<[T0, T1]> | |
): void; | |
export function effect<P, T0, T1, T2>( | |
src: [WatchSrc<T0, P>, WatchSrc<T1, P>, WatchSrc<T2, P>], | |
cb: EffectCallback<[T0, T1, T2]> | |
): void; | |
// todo more effect overloads to cover all cases | |
export interface InjectionKey<T> extends String {} | |
export function provide<T>(key: InjectionKey<T> | string, value: T): void; | |
export function inject<T>(key: InjectionKey<T> | string): T | undefined; | |
export function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import{Component as n}from"preact";function r(n,r){void 0===r&&(r=t);var u,i=[];function o(r){(n!=n?r==r:n!==r)&&(n=r,u&&i.some(function(r){r(n)}))}return{get:function(){return n},set:o,update:function(r){o(r(n))},subscribe:function(e){return i.push(e),1===i.length&&(u=r(o)||t),e(n),function(){var n=i.indexOf(e);-1!==n&&i.splice(n,1),0===i.length&&(u(),u=null)}}}}function t(){}var u,i=Symbol();function o(){for(var n;n=this.__C.t.pop();)w(n),n.u(n.__v,n.i,function(r){return n.o=r}),n.i=n.v?n.__v.slice():n.__v}function e(){this.__C.l.some(w)}function f(r){function t(){}return(t.prototype=new n).componentWillMount=function(){var n,t=u=this;t.__C={_:{},s:[],p:[],t:[],l:[],h:function(){n&&t.forceUpdate()}};var i=r(t);t.render=function(r){n&&(t.__C.s.some(x),c(t));var u=t.__C.m=t.__v.ref;return t.__v.ref=null,n=!0,i(r,u)},u=null},t}function c(n){for(var r;r=n.__C.p.pop();){var t=r.u?r.u.apply(null,r.v?r.__v:[r.__v]):r.__v,u=r.g;t&&t.then?t.then(u.set).then(n.__C.h):u.set(t),r.i=r.v?r.__v.slice():r.__v}}function a(n){u.shouldComponentUpdate=function(r,t,u,i){return i.ref!==this.__C.m||(n||function(n,r){for(var t in n)if("__source"!==t&&!(t in r))return!0;for(var u in r)if("__source"!==u&&n[u]!==r[u])return!0;return!1})(this.props,r)}}function v(n,r,t){var o=g(t,!0,!1);return _(u.__C.p,n,r,o[i]),c(u),o}function l(n,r){_(u.__C.t,n,r)}function _(n,r,t,u){var i=Array.isArray(r),o={v:i,__v:i?[]:null,u:t,g:u};i?r.length?r.forEach(function(r,t){return s(o,n,r,t)}):A(n,o):s(o,n,r)}function s(n,r,t,i){var e=u,f=function(t,u){null==i?n.__v=t:n.__v[i]=t,A(r,n)&&!u&&e.__C.h(),n.g||A(e.__h,o)};if(t){var c,a,v=t.Provider;if("function"==typeof t||v){if(v){var l=t.__c,_=e.context[l];_&&!e.__C._[l]&&(_.sub(e),e.__C._[l]=t)}var s=function(){var n=v?(c=e.context[t.__c])?c.props.value:t.__p:t(e.props);n!==a&&f(a=n,!0)};return s(),e.__C.s.push(s)}if(m(t,f))return}f(t)}function p(n){u.__h.push(n)}function b(n){u.componentWillUnmount||(u.componentWillUnmount=e),u.__C.l.push({o:n})}function d(n,r){var t=u;t.__C.j||(t.__C.j={},t.getChildContext=function(){return t.__C.j}),t.__C.j["__sC_"+n]={__c:t,__v:r}}function h(n,r){var t=u.context["__sC_"+n],i=t?t.__v:r;return m(i,u.__C.h),i}function m(n,r,t){if((t=n[i])||(t=n.subscribe&&n)){var u=t.subscribe(r);return b(u.unsubscribe?function(){return u.unsubscribe()}:u),!0}}function y(n){var r=g(n),t=r[i];delete r.value;var u={$value:t};return Object.keys(n).forEach(function(n){u[n]=j(function(){return t.get()[n]},function(r){var u=t.get();r!==u[n]&&((u=function(n,r){for(var t in r)n[t]=r[t];return n}({},u))[n]=r,t.set(u))})}),Object.defineProperties(r,u)}function g(n,t,o){var e;void 0===o&&(o=u);var f=r(n),c=t?void 0:f.set,a=f.get;return o&&b(f.subscribe(o.__C.h)),Object.defineProperties({},((e={})[i]={value:f},e.value=j(a,c),e))}function j(n,r){return{get:n,set:r,enumerable:!0,configurable:!0}}function C(n){var r;return n&&((r=n[i])||(r=n.subscribe&&n.get&&n))?r.get():n}function O(n){return!(!n||!(n[i]||n.subscribe&&n.get))}function w(n){n.o&&(n.o(),n.o=void 0)}function x(n){n()}function A(n,r){return n.indexOf(r)<0&&!!n.push(r)}export{f as createComponent,a as memo,v as watch,l as effect,p as onMounted,b as onUnmounted,d as provide,h as inject,y as reactive,g as value,C as unwrap,O as isReactive,r as createStore}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "preact-composition", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"module": "index.js", | |
"sideEffects": false | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Callback to inform of a value updates. */ | |
declare type Subscriber<T> = (value: T) => void; | |
/** Unsubscribes from value updates. */ | |
declare type Unsubscriber = () => void; | |
/** Callback to update a value. */ | |
declare type Updater<T> = (value: T) => T; | |
/** Cleanup logic callback. */ | |
declare type Invalidator<T> = (value?: T) => void; | |
/** Start and stop notification callbacks. */ | |
declare type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void; | |
export interface Store<T> { | |
/** | |
* Get the current value on the store | |
*/ | |
get(): T; | |
/** | |
* Subscribe on value changes. | |
* @param run subscription callback | |
* @param invalidate cleanup callback | |
*/ | |
subscribe(run: Subscriber<T>, invalidate?: Invalidator<T>): Unsubscriber; | |
/** | |
* Set value and inform subscribers. | |
* @param value to set | |
*/ | |
set(value: T): void; | |
/** | |
* Update value using callback and inform subscribers. | |
* @param updater callback | |
*/ | |
update(updater: Updater<T>): void; | |
} | |
/** | |
* Create a `Store` store that allows both updating and reading by subscription. | |
* @param {*=}value initial value | |
* @param {StartStopNotifier=}start start and stop notifications for subscriptions | |
*/ | |
export declare function createStore<T>( | |
value: T, | |
start?: StartStopNotifier<T> | |
): Store<T>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment