@yandex/ui
Version:
Yandex UI components
92 lines (91 loc) • 3.96 kB
JavaScript
;
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';