UNPKG

@toolpad/utils

Version:

Shared utilities used by Toolpad packages.

1 lines 5.72 kB
{"version":3,"sources":["../src/react.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as ReactIs from 'react-is';\n\n/**\n * Like `Array.prototype.join`, but for React nodes.\n */\nexport function interleave(items: React.ReactNode[], separator: React.ReactNode): React.ReactNode {\n const result: React.ReactNode[] = [];\n\n for (let i = 0; i < items.length; i += 1) {\n if (i > 0) {\n if (ReactIs.isElement(separator)) {\n result.push(React.cloneElement(separator, { key: `separator-${i}` }));\n } else {\n result.push(separator);\n }\n }\n\n const item = items[i];\n result.push(item);\n }\n\n return <React.Fragment>{result}</React.Fragment>;\n}\n\n/**\n * Consume a context but throw when used outside of a provider.\n */\nexport function useNonNullableContext<T>(context: React.Context<T>, name?: string): NonNullable<T> {\n const maybeContext = React.useContext(context);\n if (maybeContext === null || maybeContext === undefined) {\n throw new Error(`context \"${name}\" was used without a Provider`);\n }\n return maybeContext;\n}\n\n/**\n * Context that throws when used outside of a provider.\n */\nexport function createProvidedContext<T>(\n name?: string,\n): [() => T, React.ComponentType<React.ProviderProps<T>>] {\n const context = React.createContext<T | undefined>(undefined);\n const useContext = () => useNonNullableContext(context, name);\n return [useContext, context.Provider as React.ComponentType<React.ProviderProps<T>>];\n}\n\nexport function useAssertedContext<T>(context: React.Context<T | undefined>): T {\n const value = React.useContext(context);\n if (value === undefined) {\n throw new Error('context was used without a Provider');\n }\n return value;\n}\n\n/**\n * Debugging tool that logs updates to props.\n */\nexport function useTraceUpdates<P extends object>(prefix: string, props: P) {\n const prev = React.useRef<P>(props);\n React.useEffect(() => {\n const changedProps: Partial<P> = {};\n\n for (const key of Object.keys(props) as (keyof P)[]) {\n if (!Object.is(prev.current[key], props[key])) {\n changedProps[key] = props[key];\n }\n }\n\n if (Object.keys(changedProps).length > 0) {\n // eslint-disable-next-line no-console\n console.log(`${prefix} changed props:`, changedProps);\n }\n\n prev.current = props;\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default function getComponentDisplayName(Component: React.ComponentType<any> | string) {\n if (typeof Component === 'string') {\n return Component || 'Unknown';\n }\n\n return Component.displayName || Component.name;\n}\n\n/**\n * Create a shared state to be used across the application. Returns a useState hook that\n * is synchronized on the same state between all instances where it is called.\n */\nexport function createGlobalState<T>(initialState: T) {\n let state = initialState;\n const listeners: Array<(state: T) => void> = [];\n\n const subscribe = (cb: (state: T) => void) => {\n listeners.push(cb);\n return () => {\n const index = listeners.indexOf(cb);\n listeners.splice(index, 1);\n };\n };\n\n const getState = () => state;\n\n const setState = (newState: T | ((oldValue: T) => T)) => {\n state = typeof newState === 'function' ? (newState as Function)(state) : newState;\n listeners.forEach((cb) => cb(state));\n };\n\n const useValue = () => React.useSyncExternalStore(subscribe, getState, getState);\n\n const useState = (): [T, React.Dispatch<React.SetStateAction<T>>] => {\n const value = useValue();\n return [value, setState];\n };\n\n return {\n getState,\n setState,\n useValue,\n useState,\n subscribe,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAuB;AACvB,cAAyB;AAKlB,SAAS,WAAW,OAA0B,WAA6C;AAChG,QAAM,SAA4B,CAAC;AAEnC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,QAAI,IAAI,GAAG;AACT,UAAY,kBAAU,SAAS,GAAG;AAChC,eAAO,KAAW,mBAAa,WAAW,EAAE,KAAK,aAAa,CAAC,GAAG,CAAC,CAAC;AAAA,MACtE,OAAO;AACL,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,CAAC;AACpB,WAAO,KAAK,IAAI;AAAA,EAClB;AAEA,SAAO,oCAAO,gBAAN,MAAgB,MAAO;AACjC;AAKO,SAAS,sBAAyB,SAA2B,MAA+B;AACjG,QAAM,eAAqB,iBAAW,OAAO;AAC7C,MAAI,iBAAiB,QAAQ,iBAAiB,QAAW;AACvD,UAAM,IAAI,MAAM,YAAY,IAAI,+BAA+B;AAAA,EACjE;AACA,SAAO;AACT;AAKO,SAAS,sBACd,MACwD;AACxD,QAAM,UAAgB,oBAA6B,MAAS;AAC5D,QAAMA,cAAa,MAAM,sBAAsB,SAAS,IAAI;AAC5D,SAAO,CAACA,aAAY,QAAQ,QAAuD;AACrF;AAEO,SAAS,mBAAsB,SAA0C;AAC9E,QAAM,QAAc,iBAAW,OAAO;AACtC,MAAI,UAAU,QAAW;AACvB,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,SAAO;AACT;AAKO,SAAS,gBAAkC,QAAgB,OAAU;AAC1E,QAAM,OAAa,aAAU,KAAK;AAClC,EAAM,gBAAU,MAAM;AACpB,UAAM,eAA2B,CAAC;AAElC,eAAW,OAAO,OAAO,KAAK,KAAK,GAAkB;AACnD,UAAI,CAAC,OAAO,GAAG,KAAK,QAAQ,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG;AAC7C,qBAAa,GAAG,IAAI,MAAM,GAAG;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GAAG;AAExC,cAAQ,IAAI,GAAG,MAAM,mBAAmB,YAAY;AAAA,IACtD;AAEA,SAAK,UAAU;AAAA,EACjB,CAAC;AACH;AAGe,SAAR,wBAAyC,WAA8C;AAC5F,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO,aAAa;AAAA,EACtB;AAEA,SAAO,UAAU,eAAe,UAAU;AAC5C;AAMO,SAAS,kBAAqB,cAAiB;AACpD,MAAI,QAAQ;AACZ,QAAM,YAAuC,CAAC;AAE9C,QAAM,YAAY,CAAC,OAA2B;AAC5C,cAAU,KAAK,EAAE;AACjB,WAAO,MAAM;AACX,YAAM,QAAQ,UAAU,QAAQ,EAAE;AAClC,gBAAU,OAAO,OAAO,CAAC;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAEvB,QAAM,WAAW,CAAC,aAAuC;AACvD,YAAQ,OAAO,aAAa,aAAc,SAAsB,KAAK,IAAI;AACzE,cAAU,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;AAAA,EACrC;AAEA,QAAM,WAAW,MAAY,2BAAqB,WAAW,UAAU,QAAQ;AAE/E,QAAM,WAAW,MAAoD;AACnE,UAAM,QAAQ,SAAS;AACvB,WAAO,CAAC,OAAO,QAAQ;AAAA,EACzB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useContext"]}