Spaces:
Sleeping
Sleeping
| /* eslint-disable react-refresh/only-export-components */ | |
| import { createContext, useContext, useMemo, useReducer } from 'react' | |
| function getDefaultActiveTable(annotation, activePage) { | |
| const tables = annotation?.tables || [] | |
| const first = tables.find((table) => (table.page || 0) === activePage) | |
| return first?.table_id ?? null | |
| } | |
| function buildInitialState(annotation) { | |
| const activePage = 0 | |
| return { | |
| activePage, | |
| activeCell: null, | |
| activeTable: getDefaultActiveTable(annotation, activePage), | |
| tdThreshold: 0, | |
| selectionPadding: 0, | |
| showTableGrid: true, | |
| showTextBoxes: false, | |
| showHeatmap: false, | |
| toast: null, | |
| errorCount: 0, | |
| undoStack: [], | |
| redoStack: [], | |
| activeTool: 'pointer', | |
| selection: null, | |
| cellSelection: null, | |
| } | |
| } | |
| function studioReducer(state, action) { | |
| switch (action.type) { | |
| case 'setActivePage': | |
| return { | |
| ...state, | |
| activePage: action.page, | |
| } | |
| case 'setActiveTable': | |
| return { | |
| ...state, | |
| activeTable: action.tableId, | |
| } | |
| case 'setActiveCell': | |
| return { | |
| ...state, | |
| activeCell: action.cell, | |
| } | |
| case 'setThreshold': | |
| return { | |
| ...state, | |
| tdThreshold: action.value, | |
| } | |
| case 'setPadding': | |
| return { | |
| ...state, | |
| selectionPadding: action.value, | |
| } | |
| case 'toggleFlag': | |
| return { | |
| ...state, | |
| [action.flag]: !state[action.flag], | |
| } | |
| case 'showToast': | |
| return { | |
| ...state, | |
| toast: action.toast, | |
| } | |
| case 'clearToast': | |
| return { | |
| ...state, | |
| toast: null, | |
| } | |
| case 'incrementErrors': | |
| return { | |
| ...state, | |
| errorCount: state.errorCount + 1, | |
| } | |
| case 'recordEdit': | |
| return { | |
| ...state, | |
| undoStack: [...state.undoStack, action.edit], | |
| redoStack: [], | |
| } | |
| case 'completeUndo': | |
| if (!state.undoStack.length) { | |
| return state | |
| } | |
| return { | |
| ...state, | |
| undoStack: state.undoStack.slice(0, -1), | |
| redoStack: [...state.redoStack, state.undoStack[state.undoStack.length - 1]], | |
| } | |
| case 'completeRedo': | |
| if (!state.redoStack.length) { | |
| return state | |
| } | |
| return { | |
| ...state, | |
| undoStack: [...state.undoStack, state.redoStack[state.redoStack.length - 1]], | |
| redoStack: state.redoStack.slice(0, -1), | |
| } | |
| case 'setTool': | |
| return { | |
| ...state, | |
| activeTool: action.tool, | |
| selection: null, | |
| } | |
| case 'setSelection': | |
| return { | |
| ...state, | |
| selection: action.selection, | |
| } | |
| case 'setCellSelection': | |
| return { | |
| ...state, | |
| cellSelection: action.selection, | |
| } | |
| default: | |
| return state | |
| } | |
| } | |
| const StudioContext = createContext(null) | |
| export function StudioProvider({ annotation, children }) { | |
| const [state, dispatch] = useReducer(studioReducer, annotation, buildInitialState) | |
| const value = useMemo(() => ({ state, dispatch }), [state]) | |
| return <StudioContext.Provider value={value}>{children}</StudioContext.Provider> | |
| } | |
| export function useStudio() { | |
| const value = useContext(StudioContext) | |
| if (!value) { | |
| throw new Error('useStudio must be used within StudioProvider') | |
| } | |
| return value | |
| } | |