All files / src/store Section.tsx

100% Statements 13/13
100% Branches 0/0
83.33% Functions 5/6
100% Lines 12/12

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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111                                                        22x                                                                                             22x 22x         22x 3994x     22x 22x     123x       44x               22x 123x             22x  
import React, { FC, PropsWithChildren, ComponentPropsWithoutRef, createContext, useContext, useReducer } from 'react';
import { type TagType } from './Types';
 
export interface SectionElementResult<T extends object, K = string | number> {
  value?: T;
  parentValue?: T;
  keyName?: K;
  /** Index of the parent `keyName` */
  keys?: K[];
}
 
export type SectionElementProps<T extends TagType = 'span'> = {
  as?: T;
  render?: (props: SectionElement<T>, result: SectionElementResult<object>) => React.ReactNode;
};
 
export type SectionElement<T extends TagType = 'span'> = SectionElementProps<T> & ComponentPropsWithoutRef<T>;
 
type InitialState<T extends TagType> = {
  Copied?: SectionElement<T>;
  CountInfo?: SectionElement<T>;
  CountInfoExtra?: SectionElement<T>;
  Ellipsis?: SectionElement<T>;
  Row?: SectionElement<T>;
  KeyName?: SectionElement<T>;
};
 
type Dispatch = React.Dispatch<InitialState<TagType>>;
const initialState: InitialState<TagType> = {
  Copied: {
    className: 'w-rjv-copied',
    style: {
      height: '1em',
      width: '1em',
      cursor: 'pointer',
      verticalAlign: 'middle',
      marginLeft: 5,
    },
  },
  CountInfo: {
    as: 'span',
    className: 'w-rjv-object-size',
    style: {
      color: 'var(--w-rjv-info-color, #0000004d)',
      paddingLeft: 8,
      fontStyle: 'italic',
    },
  },
  CountInfoExtra: {
    as: 'span',
    className: 'w-rjv-object-extra',
    style: {
      paddingLeft: 8,
    },
  },
  Ellipsis: {
    as: 'span',
    style: {
      cursor: 'pointer',
      color: 'var(--w-rjv-ellipsis-color, #cb4b16)',
      userSelect: 'none',
    },
    className: 'w-rjv-ellipsis',
    children: '...',
  },
  Row: {
    as: 'div',
    className: 'w-rjv-line',
  },
  KeyName: {
    as: 'span',
    className: 'w-rjv-object-key',
  },
};
 
const Context = createContext<InitialState<TagType>>(initialState);
const reducer = (state: InitialState<TagType>, action: InitialState<TagType>) => ({
  ...state,
  ...action,
});
 
export const useSectionStore = () => {
  return useContext(Context);
};
 
const DispatchSection = createContext<Dispatch>(() => {});
DispatchSection.displayName = 'JVR.DispatchSection';
 
export function useSection() {
  return useReducer(reducer, initialState);
}
 
export function useSectionDispatch() {
  return useContext(DispatchSection);
}
 
interface SectionProps {
  initial: InitialState<TagType>;
  dispatch: Dispatch;
}
 
export const Section: FC<PropsWithChildren<SectionProps>> = ({ initial, dispatch, children }) => {
  return (
    <Context.Provider value={initial}>
      <DispatchSection.Provider value={dispatch}>{children}</DispatchSection.Provider>
    </Context.Provider>
  );
};
 
Section.displayName = 'JVR.Section';