71 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
| import PropTypes from 'prop-types';
 | |
| import { createContext, useContext } from 'react';
 | |
| 
 | |
| import hoistStatics from 'hoist-non-react-statics';
 | |
| 
 | |
| import type { InitialState } from 'flavours/glitch/initial_state';
 | |
| 
 | |
| export interface IdentityContextType {
 | |
|   signedIn: boolean;
 | |
|   accountId: string | undefined;
 | |
|   disabledAccountId: string | undefined;
 | |
|   permissions: number;
 | |
| }
 | |
| 
 | |
| export const identityContextPropShape = PropTypes.shape({
 | |
|   signedIn: PropTypes.bool.isRequired,
 | |
|   accountId: PropTypes.string,
 | |
|   disabledAccountId: PropTypes.string,
 | |
| }).isRequired;
 | |
| 
 | |
| export const createIdentityContext = (state: InitialState) => ({
 | |
|   signedIn: !!state.meta.me,
 | |
|   accountId: state.meta.me,
 | |
|   disabledAccountId: state.meta.disabled_account_id,
 | |
|   permissions: state.role?.permissions ?? 0,
 | |
| });
 | |
| 
 | |
| export const IdentityContext = createContext<IdentityContextType>({
 | |
|   signedIn: false,
 | |
|   permissions: 0,
 | |
|   accountId: undefined,
 | |
|   disabledAccountId: undefined,
 | |
| });
 | |
| 
 | |
| export const useIdentity = () => useContext(IdentityContext);
 | |
| 
 | |
| export interface IdentityProps {
 | |
|   ref?: unknown;
 | |
|   wrappedComponentRef?: unknown;
 | |
| }
 | |
| 
 | |
| /* Injects an `identity` props into the wrapped component to be able to use the new context in class components */
 | |
| export function withIdentity<
 | |
|   ComponentType extends React.ComponentType<IdentityProps>,
 | |
| >(Component: ComponentType) {
 | |
|   const displayName = `withIdentity(${Component.displayName ?? Component.name})`;
 | |
|   const C = (props: React.ComponentProps<ComponentType>) => {
 | |
|     const { wrappedComponentRef, ...remainingProps } = props;
 | |
| 
 | |
|     return (
 | |
|       <IdentityContext.Consumer>
 | |
|         {(context) => {
 | |
|           return (
 | |
|             // @ts-expect-error - Dynamic covariant generic components are tough to type.
 | |
|             <Component
 | |
|               {...remainingProps}
 | |
|               identity={context}
 | |
|               ref={wrappedComponentRef}
 | |
|             />
 | |
|           );
 | |
|         }}
 | |
|       </IdentityContext.Consumer>
 | |
|     );
 | |
|   };
 | |
| 
 | |
|   C.displayName = displayName;
 | |
|   C.WrappedComponent = Component;
 | |
| 
 | |
|   return hoistStatics(C, Component);
 | |
| }
 |