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 | 9x 9x 9x 7x 7x 7x 7x 7x 9x 30x 9x 17x 17x 9x | import React, { PropsWithChildren, createContext, useContext, useReducer } from 'react';
export interface StoreContextValue<Tag extends BlockTagType> extends InitialState<Tag> {
dispatch: React.Dispatch<Partial<InitialState<Tag>>>;
}
export type BlockTagType = keyof JSX.IntrinsicElements;
export type Index = Record<string, number>;
export type Fields = React.ReactElement<HTMLInputElement & { index?: number }>;
export type Buttons = React.ReactElement<HTMLButtonElement & { index?: number }>;
export type Blocks<Tag extends BlockTagType = 'div'> = React.ReactElement<Tag & { index?: number }>;
export interface RenderStateProps<T extends BlockTagType = 'div'> {
$$index?: Record<string, number>;
fields?: Record<string, Fields | null>;
buttons?: Record<string, Buttons | null>;
blocks?: Record<string, Blocks<T> | null>;
extra?: Record<string, React.ReactNode>;
[keyname: string]: any;
}
interface Control<T> {
name: string;
index: number;
children?: T | null;
}
export interface InitialState<Tag extends BlockTagType = 'div'> extends RenderStateProps<Tag> {
data: {
fields: Control<Fields>[];
buttons: Control<Buttons>[];
blocks: Control<Blocks<Tag>>[];
};
}
export const initialState: InitialState = {
index: {},
fields: {},
buttons: {},
blocks: {},
extra: {},
data: {
fields: [],
buttons: [],
blocks: [],
},
};
export const Context = createContext<StoreContextValue<'div'>>(initialState as StoreContextValue<'div'>);
Context.displayName = 'Login.Context';
export function reducer(state: InitialState, action: Partial<RenderStateProps>): InitialState {
const result = {
...state,
...action,
$$index: { ...state.$$index, ...action.$$index },
fields: { ...state.fields, ...action.fields },
buttons: { ...state.buttons, ...action.buttons },
blocks: { ...state.blocks, ...action.blocks },
extra: { ...state.extra, ...action.extra },
};
const fieldsArray = Object.keys(result.fields).map((key) => ({
name: key,
index: result.fields[key]?.props?.index || (result.$$index || {})[key] || 0,
children: result.fields[key],
}));
const buttonsArray = Object.keys(result.buttons).map((key) => ({
name: key,
index: result.buttons[key]?.props?.index || (result.$$index || {})[key] || 0,
children: result.buttons[key],
}));
const blocksArray = Object.keys(result.blocks).map((key) => ({
name: key,
index: result.blocks[key]?.props?.index || (result.$$index || {})[key] || 0,
children: result.blocks[key],
}));
return { ...result, data: { ...result.data, fields: fieldsArray, buttons: buttonsArray, blocks: blocksArray } };
}
export const useStore = () => {
return useContext(Context);
};
interface ProviderProps {
render?: any;
}
export const Provider: React.FC<PropsWithChildren<ProviderProps>> = ({ children, render }) => {
const [state, dispatch] = useReducer(reducer, initialState);
return <Context.Provider value={{ ...state, dispatch }}>{children}</Context.Provider>;
};
Provider.displayName = 'Login.Provider';
|