UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

185 lines (182 loc) 6.23 kB
import { useCallback, useEffect, useLayoutEffect, useRef } from 'react'; import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime"; const renderErr = 'Renderer Error ☝️'; export const actions = { init: 'init' }; export const defaultRenderer = ({ value = '' }) => value; export const emptyRenderer = () => /*#__PURE__*/_jsx(_Fragment, { children: "\xA0" }); export const defaultColumn = { Cell: defaultRenderer, width: 150, minWidth: 0, maxWidth: Number.MAX_SAFE_INTEGER }; function mergeProps(...propList) { return propList.reduce((props, next) => { const { style, className, ...rest } = next; props = { ...props, ...rest }; if (style) { props.style = props.style ? { ...props.style, ...style } : style; } if (className) { props.className = props.className ? props.className + ' ' + className : className; } if (props.className === '') { delete props.className; } return props; }, {}); } function handlePropGetter(prevProps, userProps, meta) { if (typeof userProps === 'function') { return handlePropGetter({}, userProps(prevProps, meta)); } if (Array.isArray(userProps)) { return mergeProps(prevProps, ...userProps); } return mergeProps(prevProps, userProps); } export const makePropGetter = (hooks, meta = {}) => { return (userProps = {}) => [...hooks, userProps].reduce((prev, next) => handlePropGetter(prev, next, { ...meta, userProps }), {}); }; export const reduceHooks = (hooks, initial, meta = {}, allowUndefined) => hooks.reduce((prev, next) => { const nextValue = next(prev, meta); if (process.env.NODE_ENV !== 'production') { if (!allowUndefined && typeof nextValue === 'undefined') { console.info(next); throw new Error('React Table: A reducer hook ☝️ just returned undefined! This is not allowed.'); } } return nextValue; }, initial); export const loopHooks = (hooks, context, meta = {}) => hooks.forEach(hook => { const nextValue = hook(context, meta); if (process.env.NODE_ENV !== 'production') { if (typeof nextValue !== 'undefined') { console.info(hook, nextValue); throw new Error('React Table: A loop-type hook ☝️ just returned a value! This is not allowed.'); } } }); export function ensurePluginOrder(plugins, befores, pluginName, afters) { if (process.env.NODE_ENV !== 'production' && afters) { throw new Error(`Defining plugins in the "after" section of ensurePluginOrder is no longer supported (see plugin ${pluginName})`); } const pluginIndex = plugins.findIndex(plugin => plugin.pluginName === pluginName); if (pluginIndex === -1) { if (process.env.NODE_ENV !== 'production') { throw new Error(`The plugin "${pluginName}" was not found in the plugin list! This usually means you need to need to name your plugin hook by setting the 'pluginName' property of the hook function, eg: ${pluginName}.pluginName = '${pluginName}' `); } } befores.forEach(before => { const beforeIndex = plugins.findIndex(plugin => plugin.pluginName === before); if (beforeIndex > -1 && beforeIndex > pluginIndex) { if (process.env.NODE_ENV !== 'production') { throw new Error(`React Table: The ${pluginName} plugin hook must be placed after the ${before} plugin hook!`); } } }); } export function functionalUpdate(updater, old) { return typeof updater === 'function' ? updater(old) : updater; } export function useGetLatest(obj) { const ref = useRef(obj); // eslint-disable-next-line react-hooks/refs ref.current = obj; return useCallback(() => ref.current, []); } export const safeUseLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; export function useMountedLayoutEffect(fn, deps) { const mountedRef = useRef(false); // eslint-disable-next-line react-hooks/refs safeUseLayoutEffect(() => { if (mountedRef.current) { fn(); } mountedRef.current = true; }, deps); } export function useAsyncDebounce(defaultFn, defaultWait = 0) { const debounceRef = useRef({}); const getDefaultFn = useGetLatest(defaultFn); const getDefaultWait = useGetLatest(defaultWait); return useCallback( // eslint-disable-next-line @typescript-eslint/require-await async (...args) => { if (!debounceRef.current.promise) { debounceRef.current.promise = new Promise((resolve, reject) => { debounceRef.current.resolve = resolve; debounceRef.current.reject = reject; }); } if (debounceRef.current.timeout) { clearTimeout(debounceRef.current.timeout); } // eslint-disable-next-line @typescript-eslint/no-misused-promises debounceRef.current.timeout = setTimeout(async () => { delete debounceRef.current.timeout; try { debounceRef.current.resolve(await getDefaultFn()(...args)); } catch (err) { debounceRef.current.reject(err); } finally { delete debounceRef.current.promise; } }, getDefaultWait()); return debounceRef.current.promise; }, [getDefaultFn, getDefaultWait]); } export function makeRenderer(instance, column, meta = {}) { return (type, userProps = {}) => { const Comp = typeof type === 'string' ? column[type] : type; if (typeof Comp === 'undefined') { console.info(column); throw new Error(renderErr); } return flexRender(Comp, { ...instance, column, ...meta, ...userProps }); }; } export function flexRender(Comp, props) { return isReactComponent(Comp) ? /*#__PURE__*/_jsx(Comp, { ...props }) : Comp; } function isReactComponent(component) { return isClassComponent(component) || typeof component === 'function' || isExoticComponent(component); } function isClassComponent(component) { return typeof component === 'function' && (() => { const proto = Object.getPrototypeOf(component); return proto.prototype && proto.prototype.isReactComponent; })(); } function isExoticComponent(component) { return typeof component === 'object' && typeof component.$$typeof === 'symbol' && ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description); }