figure-modal-context.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { FC, createContext, useContext, useReducer } from 'react'
  2. import { PastedImageData } from '../../extensions/figure-modal'
  3. /* eslint-disable no-unused-vars */
  4. export enum FigureModalSource {
  5. NONE,
  6. FILE_UPLOAD,
  7. FILE_TREE,
  8. FROM_URL,
  9. OTHER_PROJECT,
  10. EDIT_FIGURE,
  11. }
  12. /* eslint-enable no-unused-vars */
  13. type FigureModalState = {
  14. source: FigureModalSource
  15. helpShown: boolean
  16. sourcePickerShown: boolean
  17. getPath?: () => Promise<string>
  18. width: number | undefined
  19. includeCaption: boolean
  20. includeLabel: boolean
  21. error?: string
  22. pastedImageData?: PastedImageData
  23. selectedItemId?: string
  24. }
  25. type FigureModalStateUpdate = Partial<FigureModalState>
  26. const FigureModalContext = createContext<
  27. | (FigureModalState & {
  28. dispatch: (update: FigureModalStateUpdate) => void
  29. })
  30. | undefined
  31. >(undefined)
  32. export const useFigureModalContext = () => {
  33. const context = useContext(FigureModalContext)
  34. if (!context) {
  35. throw new Error(
  36. 'useFigureModalContext is only available inside FigureModalProvider'
  37. )
  38. }
  39. return context
  40. }
  41. const reducer = (prev: FigureModalState, action: Partial<FigureModalState>) => {
  42. if ('source' in action && prev.source === FigureModalSource.NONE) {
  43. // Reset when showing modal
  44. return {
  45. ...prev,
  46. width: 0.5,
  47. includeLabel: true,
  48. includeCaption: true,
  49. helpShown: false,
  50. sourcePickerShown: false,
  51. getPath: undefined,
  52. error: undefined,
  53. pastedImageData: undefined,
  54. ...action,
  55. }
  56. }
  57. return { ...prev, ...action }
  58. }
  59. type FigureModalExistingFigureState = {
  60. name: string | undefined
  61. hasComplexGraphicsArgument?: boolean
  62. }
  63. type FigureModalExistingFigureStateUpdate =
  64. Partial<FigureModalExistingFigureState>
  65. const FigureModalExistingFigureContext = createContext<
  66. | (FigureModalExistingFigureState & {
  67. dispatch: (update: FigureModalExistingFigureStateUpdate) => void
  68. })
  69. | undefined
  70. >(undefined)
  71. export const FigureModalProvider: FC = ({ children }) => {
  72. const [state, dispatch] = useReducer(reducer, {
  73. source: FigureModalSource.NONE,
  74. helpShown: false,
  75. sourcePickerShown: false,
  76. getPath: undefined,
  77. includeLabel: true,
  78. includeCaption: true,
  79. width: 0.5,
  80. })
  81. const [existingFigureState, dispatchFigureState] = useReducer(
  82. (
  83. prev: FigureModalExistingFigureState,
  84. action: FigureModalExistingFigureStateUpdate
  85. ) => ({ ...prev, ...action }),
  86. {
  87. name: undefined,
  88. }
  89. )
  90. return (
  91. <FigureModalContext.Provider value={{ ...state, dispatch }}>
  92. <FigureModalExistingFigureContext.Provider
  93. value={{ ...existingFigureState, dispatch: dispatchFigureState }}
  94. >
  95. {children}
  96. </FigureModalExistingFigureContext.Provider>
  97. </FigureModalContext.Provider>
  98. )
  99. }
  100. export const useFigureModalExistingFigureContext = () => {
  101. const context = useContext(FigureModalExistingFigureContext)
  102. if (!context) {
  103. throw new Error(
  104. 'useFigureModalExistingFigureContext is only available inside FigureModalProvider'
  105. )
  106. }
  107. return context
  108. }