| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- import * as React from 'react';
- import React__default, { useState, useEffect, useRef, useMemo, createContext, useCallback, useContext } from 'react';
- import { RediError, Injector, Quantity } from '@wendellhu/redi';
- import { BehaviorSubject } from 'rxjs';
- var __REDI_CONTEXT_LOCK__ = 'REDI_CONTEXT_LOCK';
- var isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
- var globalObject = (typeof globalThis !== 'undefined' && globalThis) ||
- (typeof window !== 'undefined' && window) ||
- (typeof global !== 'undefined' && global);
- if (!globalObject[__REDI_CONTEXT_LOCK__]) {
- globalObject[__REDI_CONTEXT_LOCK__] = true;
- }
- else if (!isNode) {
- console.error('[redi]: "RediContext" is already created. You may import "RediContext" from different paths. Use "import { RediContext } from \'@wendellhu/redi/react-bindings\'; instead."');
- }
- var RediContext = React.createContext({
- injector: null,
- });
- RediContext.displayName = 'RediContext';
- var RediProvider = RediContext.Provider;
- var RediConsumer = RediContext.Consumer;
- var __extends$1 = (undefined && undefined.__extends) || (function () {
- 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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
- return extendStatics(d, b);
- };
- return function (d, b) {
- if (typeof b !== "function" && b !== null)
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
- })();
- var HooksNotInRediContextError = /** @class */ (function (_super) {
- __extends$1(HooksNotInRediContextError, _super);
- function HooksNotInRediContextError() {
- return _super.call(this, 'Using dependency injection outside of a RediContext.') || this;
- }
- return HooksNotInRediContextError;
- }(RediError));
- function useInjector() {
- var injectionContext = React.useContext(RediContext);
- if (!injectionContext.injector) {
- throw new HooksNotInRediContextError();
- }
- return injectionContext.injector;
- }
- function useDependency(id, quantityOrLookUp, lookUp) {
- var injector = useInjector();
- return injector.get(id, quantityOrLookUp, lookUp);
- }
- var __assign = (undefined && undefined.__assign) || function () {
- __assign = Object.assign || function(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
- t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
- };
- function RediInjector(props) {
- var children = props.children, dependencies = props.dependencies;
- var childInjectorRef = React.useRef(null);
- // dispose the injector when the container Injector unmounts
- React.useEffect(function () { return function () { var _a; return (_a = childInjectorRef.current) === null || _a === void 0 ? void 0 : _a.dispose(); }; }, []);
- return (React.createElement(RediConsumer, null, function (context) {
- var childInjector;
- if (childInjectorRef.current) {
- childInjector = childInjectorRef.current;
- }
- else {
- childInjector = context.injector
- ? context.injector.createChild(dependencies)
- : new Injector(dependencies);
- childInjectorRef.current = childInjector;
- }
- return (React.createElement(RediProvider, { value: { injector: childInjector } }, children));
- }));
- }
- /**
- * @param Comp
- * @param injector
- * @returns
- */
- function connectInjector(Comp, injector) {
- return function ComponentWithInjector(props) {
- return (React.createElement(RediProvider, { value: { injector: injector } },
- React.createElement(Comp, __assign({}, props))));
- };
- }
- function connectDependencies(Comp, dependencies) {
- return function ComponentWithInjector(props) {
- return (React.createElement(RediInjector, { dependencies: dependencies },
- React.createElement(Comp, __assign({}, props))));
- };
- }
- var __extends = (undefined && undefined.__extends) || (function () {
- 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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
- return extendStatics(d, b);
- };
- return function (d, b) {
- if (typeof b !== "function" && b !== null)
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
- })();
- var ClassComponentNotInRediContextError = /** @class */ (function (_super) {
- __extends(ClassComponentNotInRediContextError, _super);
- function ClassComponentNotInRediContextError(component) {
- return _super.call(this, "You should make \"RediContext\" as ".concat(component.constructor.name, "'s default context type. ") +
- 'If you want to use multiple context, please check this on React doc site. ' +
- 'https://reactjs.org/docs/context.html#classcontexttype') || this;
- }
- return ClassComponentNotInRediContextError;
- }(RediError));
- function WithDependency(id, quantity, lookUp) {
- return function () {
- return {
- get: function () {
- var thisComponent = this;
- var context = thisComponent.context;
- if (!context || !context.injector) {
- throw new ClassComponentNotInRediContextError(thisComponent);
- }
- var injector = context.injector;
- var thing = injector.get(id, quantity || Quantity.REQUIRED, lookUp);
- return thing;
- },
- };
- };
- }
- var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
- if (ar || !(i in from)) {
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
- ar[i] = from[i];
- }
- }
- return to.concat(ar || Array.prototype.slice.call(from));
- };
- /**
- * unwrap an observable value, return it to the component for rendering, and
- * trigger re-render when value changes
- *
- * **IMPORTANT**. Parent and child components better not subscribe to the same
- * observable, otherwise unnecessary re-render would be triggered. Instead, the
- * top-most component should subscribe and pass value of the observable to
- * its offspring, by props or context. Please consider using `useDependencyContext` and
- * `useDependencyContextValue` in this case.
- *
- * @deprecated Please use `useObservable` instead.
- */
- function useDependencyValue(depValue$, defaultValue) {
- var firstValue = depValue$ instanceof BehaviorSubject && typeof defaultValue === 'undefined'
- ? depValue$.getValue()
- : defaultValue;
- var _a = useState(firstValue), value = _a[0], setValue = _a[1];
- useEffect(function () {
- var subscription = depValue$.subscribe(function (val) { return setValue(val); });
- return function () { return subscription.unsubscribe(); };
- }, [depValue$]);
- return value;
- }
- function unwrap(o) {
- if (typeof o === 'function') {
- return o();
- }
- return o;
- }
- /**
- * Subscribe to an observable and return its value. The component will re-render when the observable emits a new value.
- *
- * @param observable An observable or a function that returns an observable
- * @param defaultValue The default value of the observable. It the `observable` can omit an initial value, this value will be neglected.
- * @param shouldHaveSyncValue If the observable should have a sync value. If it does not have a sync value, an error will be thrown.
- * @param deps A dependency array to decide if we should re-subscribe when the `observable` is a function.
- * @returns
- */
- function useObservable(observable, defaultValue, shouldHaveSyncValue, deps) {
- if (typeof observable === 'function' && !deps) {
- throw new RediError("Expected deps to be provided when observable is a function!");
- }
- var observableRef = useRef(null);
- var initializedRef = useRef(false);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- var destObservable = useMemo(function () { return observable; }, __spreadArray([], (typeof deps !== 'undefined' ? deps : [observable]), true));
- // This state is only for trigger React to re-render. We do not use `setValue` directly because it may cause
- // memory leaking.
- var _a = useState(0), _ = _a[0], setRenderCounter = _a[1];
- var valueRef = useRef((function () {
- var innerDefaultValue;
- if (destObservable) {
- var sub = unwrap(destObservable).subscribe(function (value) {
- initializedRef.current = true;
- innerDefaultValue = value;
- });
- sub.unsubscribe();
- }
- return innerDefaultValue !== null && innerDefaultValue !== void 0 ? innerDefaultValue : defaultValue;
- })());
- useEffect(function () {
- var subscription = null;
- if (destObservable) {
- observableRef.current = unwrap(destObservable);
- subscription = observableRef.current.subscribe(function (value) {
- valueRef.current = value;
- setRenderCounter(function (prev) { return prev + 1; });
- });
- }
- return function () { return subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe(); };
- }, [destObservable]);
- if (shouldHaveSyncValue && !initializedRef.current) {
- throw new Error('Expect `shouldHaveSyncValue` but not getting a sync value!');
- }
- return valueRef.current;
- }
- /**
- * subscribe to a signal that emits whenever data updates and re-render
- *
- * @param update$ a signal that the data the functional component depends has updated
- */
- function useUpdateBinder(update$) {
- var _a = useState(0), dumpSet = _a[1];
- useEffect(function () {
- var subscription = update$.subscribe(function () { return dumpSet(function (prev) { return prev + 1; }); });
- return function () { return subscription.unsubscribe(); };
- }, []);
- }
- var DepValueMapProvider = new WeakMap();
- /**
- * subscribe to an observable value from a service, creating a context for it so
- * it child component won't have to subscribe again and cause unnecessary
- */
- function useDependencyContext(depValue$, defaultValue) {
- var depRef = useRef(undefined);
- var value = useDependencyValue(depValue$, defaultValue);
- var Context = useMemo(function () {
- return createContext(value);
- }, [depValue$]);
- var Provider = useCallback(function (props) {
- return React__default.createElement(Context.Provider, { value: value }, props.children);
- }, [depValue$, value]);
- if (depRef.current !== depValue$) {
- if (depRef.current) {
- DepValueMapProvider.delete(depRef.current);
- }
- depRef.current = depValue$;
- DepValueMapProvider.set(depValue$, Context);
- }
- return {
- Provider: Provider,
- value: value,
- };
- }
- function useDependencyContextValue(depValue$) {
- var context = DepValueMapProvider.get(depValue$);
- if (!context) {
- throw new RediError("try to read context value but no ancestor component subscribed it.");
- }
- return useContext(context);
- }
- export { RediConsumer, RediContext, RediProvider, WithDependency, connectDependencies, connectInjector, useDependency, useDependencyContext, useDependencyContextValue, useDependencyValue, useInjector, useObservable, useUpdateBinder };
- //# sourceMappingURL=react-bindings.js.map
|