UNPKG

@yandex/ui

Version:

Yandex UI components

92 lines (91 loc) 3.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultiRenderOverrideProvider = exports.RenderOverrideProvider = exports.useRenderOverride = void 0; var tslib_1 = require("tslib"); var react_1 = require("react"); var createGlobalState_1 = require("../createGlobalState"); /** * Реакт-хук для создания компонента с возможностью переопределения. * * @example * const ElementOriginal = ({ children }) => <div>{children}</div> * * const MyComponent = ({ renderElement }) => { * const Element = useRenderOverride(ElementOriginal, renderElement) * return <Element /> * } */ function useRenderOverride(component, render) { // Создаем глобальное состояние, чтобы иметь возможность // обновлять каждый инстанс переопределенного компонента. var useDeps = react_1.useRef(createGlobalState_1.createGlobalState([component, render])).current; var _a = tslib_1.__read(useDeps(), 2), setDeps = _a[1]; // Используем useRef для кэширования функции, т.к. реакт // не гарантирует постоянную мемоизацию для useMemo/Callback. var renderer = react_1.useRef(function RenderOverride(props) { var _a = tslib_1.__read(useDeps(), 1), deps = _a[0]; var _b = tslib_1.__read(deps || [], 2), nextComponent = _b[0], nextRender = _b[1]; if (deps === undefined || nextRender === undefined) { return react_1.createElement(nextComponent, props); } return nextRender(props, nextComponent); }).current; react_1.useEffect(function () { setDeps([component, render]); }, [setDeps, component, render]); return renderer; } exports.useRenderOverride = useRenderOverride; /** * Реакт-провайдер для создания компонента с возможностью переопределения. * * @example * const ElementOriginal = ({ children }) => <div>{children}</div> * * const MyComponent = ({ renderElement }) => { * <RenderOverrideProvider component={ElementOriginal} render={renderElement}> * {(Element) => <Element />} * </RenderOverrideProvider> * } */ var RenderOverrideProvider = function (_a) { var children = _a.children, component = _a.component, render = _a.render; var renderer = useRenderOverride(component, render); return children(renderer); }; exports.RenderOverrideProvider = RenderOverrideProvider; exports.RenderOverrideProvider.displayName = 'RenderOverrideProvider'; /** * Реакт-провайдер для создания нескольких компонентов с возможностью переопределения. * * @example * const ElementOriginal1 = ({ children }) => <div>{children}</div> * const ElementOriginal2 = ({ children }) => <div>{children}</div> * * const MyComponent = ({ renderElement1, renderElement2 }) => { * <MultiRenderOverrideProvider * components={[ * [ElementOriginal2, renderElement1], * [ElementOriginal2, renderElement2], * ]} * > * {(Element1, Element2) => ( * <> * <Element1 /> * <Element2 /> * </> * )} * </MultiRenderOverrideProvider> * } */ var MultiRenderOverrideProvider = function (_a) { var children = _a.children, components = _a.components; // eslint-disable-next-line react-hooks/rules-of-hooks var renderers = components.map(function (_a) { var _b = tslib_1.__read(_a, 2), component = _b[0], render = _b[1]; return useRenderOverride(component, render); }); return children.apply(void 0, tslib_1.__spread(renderers)); }; exports.MultiRenderOverrideProvider = MultiRenderOverrideProvider; exports.MultiRenderOverrideProvider.displayName = 'MultiRenderOverrideProvider';