summaryrefslogtreecommitdiff
path: root/src/zoom/hooks/useZoom.tsx
blob: e3fb0c46f9db07ced20f8fc197c4fe328a24cad9 (plain)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"use client";
import React, { createContext, useState, useContext, ReactNode } from "react";
import { ViewLevel, ViewState } from "../logic/types";

// Type definitions for the context
interface ZoomContextType {
  viewState: ViewState;
  setLevel: (level: ViewLevel) => void;
  setParagraphIndex: (idx: number | null) => void;
  setSentenceIndex: (idx: number | null) => void;
  setClauseIndex: (idx: number | null) => void;
  setWordIndex: (idx: number | null) => void;
  setSyllableIndex: (idx: number | null) => void;
  setPhonemeIndex: (idx: number | null) => void;
  navigateBack: () => void;
  handleElementClick: (e: React.MouseEvent, idx: number) => void;
}

// Create the context with default empty values
const ZoomContext = createContext<ZoomContextType>({
  viewState: {
    level: "text",
    pIndex: null,
    sIndex: null,
    cIndex: null,
    wIndex: null,
    yIndex: null,
    fIndex: null,
  },
  setLevel: () => {},
  setParagraphIndex: () => {},
  setSentenceIndex: () => {},
  setClauseIndex: () => {},
  setWordIndex: () => {},
  setSyllableIndex: () => {},
  setPhonemeIndex: () => {},
  navigateBack: () => {},
  handleElementClick: () => {},
});

// Provider component
export const ZoomProvider: React.FC<{ children: ReactNode }> = ({
  children,
}) => {
  const [viewState, setViewState] = useState<ViewState>({
    level: "text",
    pIndex: null,
    sIndex: null,
    cIndex: null,
    wIndex: null,
    yIndex: null,
    fIndex: null,
  });

  // Helper functions to update individual parts of the state
  const setLevel = (level: ViewLevel) =>
    setViewState((prev) => ({ ...prev, level }));
  const setParagraphIndex = (pIndex: number | null) =>
    setViewState((prev) => ({ ...prev, pIndex }));
  const setSentenceIndex = (sIndex: number | null) =>
    setViewState((prev) => ({ ...prev, sIndex }));
  const setClauseIndex = (cIndex: number | null) =>
    setViewState((prev) => ({ ...prev, cIndex }));
  const setWordIndex = (wIndex: number | null) =>
    setViewState((prev) => ({ ...prev, wIndex }));
  const setSyllableIndex = (yIndex: number | null) =>
    setViewState((prev) => ({ ...prev, yIndex }));
  const setPhonemeIndex = (fIndex: number | null) =>
    setViewState((prev) => ({ ...prev, fIndex }));

  // Handle navigation levels
  const navigateBack = () => {
    const { level } = viewState;

    if (level === "paragraph") {
      setViewState((prev) => ({ ...prev, level: "text", pIndex: null }));
    } else if (level === "sentence") {
      setViewState((prev) => ({ ...prev, level: "paragraph", sIndex: null }));
    } else if (level === "clause") {
      setViewState((prev) => ({ ...prev, level: "sentence", cIndex: null }));
    } else if (level === "word") {
      setViewState((prev) => ({ ...prev, level: "clause", wIndex: null }));
    } else if (level === "syllable") {
      setViewState((prev) => ({ ...prev, level: "word", yIndex: null }));
    } else if (level === "phoneme") {
      setViewState((prev) => ({ ...prev, level: "syllable", fIndex: null }));
    }
  };

  // Handle clicks on elements to navigate forward
  const handleElementClick = (e: React.MouseEvent, idx: number) => {
    e.stopPropagation();
    const { level } = viewState;

    if (level === "text") {
      setViewState((prev) => ({ ...prev, level: "paragraph", pIndex: idx }));
    } else if (level === "paragraph") {
      setViewState((prev) => ({ ...prev, level: "sentence", sIndex: idx }));
    } else if (level === "sentence") {
      setViewState((prev) => ({ ...prev, level: "clause", cIndex: idx }));
    } else if (level === "clause") {
      setViewState((prev) => ({ ...prev, level: "word", wIndex: idx }));
    } else if (level === "word") {
      setViewState((prev) => ({ ...prev, level: "syllable", yIndex: idx }));
    } else if (level === "syllable") {
      setViewState((prev) => ({ ...prev, level: "phoneme", fIndex: idx }));
    }
  };

  return (
    <ZoomContext.Provider
      value={{
        viewState,
        setLevel,
        setParagraphIndex,
        setSentenceIndex,
        setClauseIndex,
        setWordIndex,
        setSyllableIndex,
        setPhonemeIndex,
        navigateBack,
        handleElementClick,
      }}
    >
      {children}
    </ZoomContext.Provider>
  );
};

// Custom hook to use the zoom context
export const useZoom = () => useContext(ZoomContext);