All files / collaborative-react/src context.tsx

94.28% Statements 33/35
100% Branches 2/2
77.77% Functions 7/9
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 885x 5x                                                                                                     5x 6x 6x 19x   6x 3x   6x 6x 6x 25x 25x 21x   6x 6x 6x 6x                           5x   5x  
import {createContext, useContext} from 'react';
import * as React from 'react';
import type {Model} from 'json-joy/lib/json-crdt';
import type {CrdtNodeApi} from './types';
 
// -------------------------------------------------------------- Model context
 
export interface ModelProviderProps<M extends Model<any> = Model<any>> {
  model: M;
  children: React.ReactNode;
}
 
export interface CtxModelProps<M extends Model<any> = Model<any>> {
  render: (model: M | undefined) => React.ReactNode;
}
 
// export const createCtx = <M extends Model<any>>(model?: M) => {
//   const ctx = createContext<M | undefined>(model);
//   const ModelCtx: React.FC<ModelProviderProps<M>> = ({children, model}) => {
//     return <ctx.Provider value={model}>{children}</ctx.Provider>;
//   };
//   const useCtxModel = <MM extends Model<any> = M>(): MM | undefined => useContext(ctx) as unknown as MM;
//   const useCtxModelStrict = <MM extends Model<any> = M>(): MM => {
//     const model = useContext(ctx) as unknown as MM;
//     if (!model) throw new Error('NO_MODEL');
//     return model;
//   };
//   const CtxModel: React.FC<CtxModelProps<M>> = ({render}) => render(useCtxModel());
//   return {ctx, ModelCtx, useCtxModel, useCtxModelStrict, CtxModel};
// };
 
// const {ctx, ModelCtx, useCtxModel, useCtxModelStrict, CtxModel} = createCtx();
 
// export {
//   ctx,
//   ModelCtx,
//   useCtxModel,
//   useCtxModelStrict,
//   CtxModel,
// };
 
// --------------------------------------------------------------- Node context
 
export interface NodeProviderProps<N extends CrdtNodeApi = CrdtNodeApi> {
  node: N;
  children: React.ReactNode;
}
 
export interface CtxNodeProps<N extends CrdtNodeApi = CrdtNodeApi> {
  render: (node: N | undefined) => React.ReactNode;
}
 
export const createNodeCtx = <N extends CrdtNodeApi = CrdtNodeApi>(node?: N) => {
  const ctx = createContext<N | undefined>(node);
  const NodeCtx: React.FC<NodeProviderProps<N>> = ({children, node}) => (
    <ctx.Provider value={node}>{children}</ctx.Provider>
  );
  const ModelCtx: React.FC<ModelProviderProps> = ({children, model}) => (
    <NodeCtx node={model.api as unknown as N}>{children}</NodeCtx>
  );
  const useCtxNode = (): N | undefined => useContext(ctx) as unknown as N;
  const useCtxModel = (): Model<any> | undefined => useContext(ctx)?.api.model;
  const useCtxNodeStrict = (): N => {
    const node = useContext(ctx) as unknown as N;
    if (!node) throw new Error('NO_NODE');
    return node;
  };
  const useCtxModelStrict = (): Model<any> => useCtxNodeStrict().api.model;
  const CtxNode: React.FC<CtxNodeProps<N>> = ({render}) => render(useCtxNode());
  const CtxModel: React.FC<CtxModelProps> = ({render}) => render(useCtxModel());
  return {
    ctx,
    NodeCtx,
    ModelCtx,
    useCtxNode,
    useCtxModel,
    useCtxNodeStrict,
    useCtxModelStrict,
    CtxNode,
    CtxModel,
  };
};
 
const {ctx, NodeCtx, ModelCtx, useCtxNode, useCtxModel, useCtxNodeStrict, useCtxModelStrict, CtxNode, CtxModel} =
  createNodeCtx();
 
export {ctx, NodeCtx, ModelCtx, useCtxNode, useCtxModel, useCtxNodeStrict, useCtxModelStrict, CtxNode, CtxModel};