• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SNApp-notes / web / 20233079137

15 Dec 2025 01:00PM UTC coverage: 86.171% (-1.2%) from 87.362%
20233079137

push

github

jcubic
fix tests

696 of 850 branches covered (81.88%)

Branch coverage included in aggregate %.

6 of 20 new or added lines in 3 files covered. (30.0%)

30 existing lines in 3 files now uncovered.

1379 of 1558 relevant lines covered (88.51%)

2342.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.73
/src/components/notes/MiddlePanel.tsx
1
/**
2
 * Middle panel component for note editing and content display.
3
 *
4
 * @remarks
5
 * Dependencies: Chakra UI v3, React, Editor component
6
 *
7
 * **Features:**
8
 * - Note title display
9
 * - Real-time save status indicator
10
 * - CodeMirror-based markdown editor
11
 * - Line selection support
12
 * - Empty state for no selected note
13
 * - Editor reference callback for parent control
14
 *
15
 * **Save Status:**
16
 * - idle: No indicator shown
17
 * - saving: Blue "Saving..." text
18
 * - saved: Green "Saved" text
19
 * - error: Red "Save failed" text
20
 *
21
 * **Performance:**
22
 * - Memoized component and computed values
23
 * - useCallback for event handlers
24
 *
25
 * @example
26
 * ```tsx
27
 * <MiddlePanel
28
 *   note={currentNote}
29
 *   content={noteContent}
30
 *   saveStatus="saved"
31
 *   selectedLine={42}
32
 *   onContentChange={handleChange}
33
 *   onEditorReady={(ref) => editorRef.current = ref}
34
 * />
35
 * ```
36
 *
37
 * @public
38
 */
39
'use client';
40

41
import { Box, Text, Flex } from '@chakra-ui/react';
42
import { memo, useMemo, useCallback } from 'react';
43
import type { NoteTreeNode } from '@/types/tree';
44
import type { SaveStatus } from '@/types/notes';
45
import type { EditorRef } from '@/types/editor';
46
import Editor from '@/components/Editor';
47

48
/**
49
 * Props for the MiddlePanel component.
50
 *
51
 * @public
52
 */
53
interface MiddlePanelProps {
54
  /** Currently selected note or null if none selected */
55
  note: NoteTreeNode | null;
56
  /** Current content of the note */
57
  content: string;
58
  /** Current save status of the note */
59
  saveStatus: SaveStatus;
60
  /** Optional line number to highlight in editor */
61
  selectedLine?: number;
62
  /** Callback invoked when content changes */
63
  onContentChange: (content: string) => void;
64
  /** Optional callback invoked when editor is ready */
65
  onEditorReady?: (editorRef: EditorRef) => void;
66
  /** Optional callback invoked when cursor position changes */
67
  onCursorChange?: () => void;
68
  /** Optional callback invoked when scroll position changes */
69
  onScrollChange?: () => void;
70
}
71

72
/**
73
 * Renders the middle panel with note editor and status bar.
74
 *
75
 * @param props - Component props
76
 * @param props.note - Currently selected note
77
 * @param props.content - Note content string
78
 * @param props.saveStatus - Current save status
79
 * @param props.selectedLine - Line number to highlight
80
 * @param props.onContentChange - Handler for content changes
81
 * @param props.onEditorReady - Handler for editor initialization
82
 * @returns Memoized middle panel component
83
 *
84
 * @remarks
85
 * Displays empty state when no note is selected.
86
 * Save status bar shows note name and color-coded status.
87
 *
88
 * @public
89
 */
90
const MiddlePanel = memo(function MiddlePanel({
107✔
91
  note,
92
  content,
93
  saveStatus,
94
  selectedLine,
95
  onContentChange,
96
  onEditorReady,
97
  onCursorChange,
98
  onScrollChange
99
}: MiddlePanelProps) {
100
  const saveStatusText = useMemo(() => {
2,962✔
101
    switch (saveStatus) {
328!
102
      case 'saving':
103
        return 'Saving...';
12✔
104
      case 'saved':
105
        return 'Saved';
12✔
106
      case 'error':
UNCOV
107
        return 'Save failed';
×
108
      default:
109
        return '';
304✔
110
    }
111
  }, [saveStatus]);
112

113
  const saveStatusColor = useMemo(() => {
2,962✔
114
    switch (saveStatus) {
328!
115
      case 'saving':
116
        return 'blue.500';
12✔
117
      case 'saved':
118
        return 'green.500';
12✔
119
      case 'error':
UNCOV
120
        return 'red.500';
×
121
      default:
122
        return 'gray.500';
304✔
123
    }
124
  }, [saveStatus]);
125

126
  const handleContentChange = useCallback(
2,962✔
127
    (value: string | undefined) => {
128
      onContentChange(value || '');
1,124!
129
    },
130
    [onContentChange]
131
  );
132

UNCOV
133
  return (
×
134
    <Box as="main" h="100%" display="flex" flexDirection="column">
135
      {/* Save status bar */}
136
      <Flex
137
        justify="space-between"
138
        align="center"
139
        p={3}
140
        borderBottom="1px solid"
141
        borderColor="border"
142
      >
143
        <Text fontSize="lg" fontWeight="semibold">
144
          {note?.name || 'Select a note'}
3,236✔
145
        </Text>
146
        {saveStatus !== 'idle' && (
2,962!
147
          <Text fontSize="sm" color={saveStatusColor}>
148
            {saveStatusText}
149
          </Text>
150
        )}
151
      </Flex>
152

153
      {/* Editor area */}
154
      <Box flex={1} overflow="hidden" position="relative" minH={0}>
155
        {note ? (
×
156
          <Editor
2,688✔
157
            value={content}
158
            onChange={handleContentChange}
159
            selectedLine={selectedLine}
160
            onEditorReady={onEditorReady}
161
            onCursorChange={onCursorChange}
162
            onScrollChange={onScrollChange}
163
            placeholder="Start writing your note..."
164
          />
165
        ) : (
166
          <Flex h="100%" align="center" justify="center">
167
            <Text color="fg.muted">Select or create a note to start editing</Text>
168
          </Flex>
169
        )}
170
      </Box>
171
    </Box>
172
  );
173
});
174

175
export default MiddlePanel;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc