UNPKG

@wener/ui

Version:

140 lines 5.67 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createSubscriptionContainer = void 0; const react_1 = __importStar(require("react")); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const useConstant_1 = require("./useConstant"); const immer_1 = __importDefault(require("immer")); /// https://github.com/jamiebuilds/unstated-next/blob/master/src/unstated-next.tsx const EMPTY = Symbol(); function createSubscriptionContainer(useHook, { isEqual } = { isEqual: (a, b) => a === b }) { const Context = react_1.default.createContext(EMPTY); function Provider(props) { const subject = useConstant_1.useConstant(() => { const initialState = props.initialState; // type fixing return new rxjs_1.BehaviorSubject(typeof initialState === 'function' ? initialState() : initialState); }); const container = useConstant_1.useConstant(() => { const setStateReal = (state) => { let next; if (typeof state === 'function') { next = state(subject.getValue()); } else { next = state; } subject.next(next); }; // handle change state when subscribe let changing = false; const setState = (state) => { if (changing) { setTimeout(() => setState(state), 0); return; } changing = true; try { setStateReal(state); } finally { changing = false; } }; const options = { getState: () => subject.getValue(), setState, updateState(fn) { // todo produced is immutable setState(immer_1.default((v) => { fn(v); // ensure return void })); }, subscribe(cb) { const subscription = subject.subscribe(cb); return subscription.unsubscribe.bind(subscription); }, }; return useHook(options); }); return react_1.default.createElement(Context.Provider, { value: { container, subject } }, props.children); } function useContainer() { const context = react_1.default.useContext(Context); if (context === EMPTY) { throw new Error('Component must be wrapped with <SubscriptionContainer.Provider>'); } return context.container; } function useSelector(selector, eq = isEqual) { const context = react_1.default.useContext(Context); if (context === EMPTY) { throw new Error('Component must be wrapped with <SubscriptionContainer.Provider>'); } const subject = context.subject; const [state, setState] = react_1.default.useState(() => selector(subject.getValue())); react_1.useEffect(() => { const subscription = subject.pipe(operators_1.skip(1)).subscribe((s) => { setState((old) => { const next = selector(s); if (eq(old, next)) { return old; } return next; }); }); return () => subscription.unsubscribe(); }, []); return state; } function useState() { return useSelector((v) => v); } function useWhenValueChange(selector, cb, eq = isEqual) { const context = react_1.default.useContext(Context); if (context === EMPTY) { throw new Error('Component must be wrapped with <SubscriptionContainer.Provider>'); } const subject = context.subject; const ref = react_1.default.useRef(); react_1.useEffect(() => { ref.current = selector(subject.getValue()); const subscription = subject.subscribe((s) => { const old = ref.current; const next = selector(s); if (!eq(old, next)) { cb(next); ref.current = next; } }); return () => subscription.unsubscribe(); }, []); } return { Provider, useContainer, useSelector, useState, useWhenValueChange }; } exports.createSubscriptionContainer = createSubscriptionContainer; //# sourceMappingURL=substated.js.map