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'; |