floatnote 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/.beads/config.json +6 -0
  2. package/.beads/issues/floatnote-1.md +21 -0
  3. package/.beads/issues/floatnote-10.md +28 -0
  4. package/.beads/issues/floatnote-11.md +36 -0
  5. package/.beads/issues/floatnote-12.md +25 -0
  6. package/.beads/issues/floatnote-13.md +37 -0
  7. package/.beads/issues/floatnote-14.md +22 -0
  8. package/.beads/issues/floatnote-15.md +22 -0
  9. package/.beads/issues/floatnote-16.md +20 -0
  10. package/.beads/issues/floatnote-17.md +20 -0
  11. package/.beads/issues/floatnote-18.md +21 -0
  12. package/.beads/issues/floatnote-19.md +19 -0
  13. package/.beads/issues/floatnote-2.md +32 -0
  14. package/.beads/issues/floatnote-20.md +22 -0
  15. package/.beads/issues/floatnote-3.md +50 -0
  16. package/.beads/issues/floatnote-4.md +31 -0
  17. package/.beads/issues/floatnote-5.md +28 -0
  18. package/.beads/issues/floatnote-6.md +30 -0
  19. package/.beads/issues/floatnote-7.md +38 -0
  20. package/.beads/issues/floatnote-8.md +29 -0
  21. package/.beads/issues/floatnote-9.md +32 -0
  22. package/CLAUDE.md +61 -0
  23. package/README.md +95 -0
  24. package/bin/floatnote.js +218 -0
  25. package/coverage/base.css +224 -0
  26. package/coverage/bin/floatnote.js.html +739 -0
  27. package/coverage/bin/index.html +116 -0
  28. package/coverage/block-navigation.js +87 -0
  29. package/coverage/favicon.png +0 -0
  30. package/coverage/index.html +131 -0
  31. package/coverage/lcov-report/base.css +224 -0
  32. package/coverage/lcov-report/bin/floatnote.js.html +739 -0
  33. package/coverage/lcov-report/bin/index.html +116 -0
  34. package/coverage/lcov-report/block-navigation.js +87 -0
  35. package/coverage/lcov-report/favicon.png +0 -0
  36. package/coverage/lcov-report/index.html +131 -0
  37. package/coverage/lcov-report/prettify.css +1 -0
  38. package/coverage/lcov-report/prettify.js +2 -0
  39. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  40. package/coverage/lcov-report/sorter.js +210 -0
  41. package/coverage/lcov-report/src/index.html +146 -0
  42. package/coverage/lcov-report/src/main.js.html +1483 -0
  43. package/coverage/lcov-report/src/preload.js.html +361 -0
  44. package/coverage/lcov-report/src/renderer.js.html +8767 -0
  45. package/coverage/lcov.info +3273 -0
  46. package/coverage/prettify.css +1 -0
  47. package/coverage/prettify.js +2 -0
  48. package/coverage/sort-arrow-sprite.png +0 -0
  49. package/coverage/sorter.js +210 -0
  50. package/coverage/src/index.html +146 -0
  51. package/coverage/src/main.js.html +1483 -0
  52. package/coverage/src/preload.js.html +361 -0
  53. package/coverage/src/renderer.js.html +8767 -0
  54. package/jest.config.js +48 -0
  55. package/package.json +59 -0
  56. package/src/icon-template.png +0 -0
  57. package/src/index.html +296 -0
  58. package/src/main.js +494 -0
  59. package/src/preload.js +96 -0
  60. package/src/renderer.js +3203 -0
  61. package/src/styles.css +1448 -0
  62. package/tests/cli/floatnote.test.js +167 -0
  63. package/tests/main/main.test.js +287 -0
  64. package/tests/mocks/electron.js +126 -0
  65. package/tests/mocks/fs.js +17 -0
  66. package/tests/preload/preload.test.js +218 -0
  67. package/tests/renderer/history.test.js +234 -0
  68. package/tests/renderer/notes.test.js +262 -0
  69. package/tests/renderer/settings.test.js +178 -0
package/jest.config.js ADDED
@@ -0,0 +1,48 @@
1
+ module.exports = {
2
+ testEnvironment: 'node',
3
+ roots: ['<rootDir>/tests'],
4
+ collectCoverage: true,
5
+ coverageDirectory: 'coverage',
6
+ coverageReporters: ['text', 'lcov', 'html'],
7
+ collectCoverageFrom: [
8
+ 'src/**/*.js',
9
+ 'bin/**/*.js',
10
+ '!**/node_modules/**'
11
+ ],
12
+ coverageThreshold: {
13
+ global: {
14
+ statements: 0,
15
+ branches: 0,
16
+ functions: 0,
17
+ lines: 0
18
+ }
19
+ },
20
+ projects: [
21
+ {
22
+ displayName: 'main',
23
+ testEnvironment: 'node',
24
+ testMatch: ['<rootDir>/tests/main/**/*.test.js'],
25
+ moduleNameMapper: {
26
+ '^electron$': '<rootDir>/tests/mocks/electron.js'
27
+ }
28
+ },
29
+ {
30
+ displayName: 'renderer',
31
+ testEnvironment: 'jsdom',
32
+ testMatch: ['<rootDir>/tests/renderer/**/*.test.js']
33
+ },
34
+ {
35
+ displayName: 'cli',
36
+ testEnvironment: 'node',
37
+ testMatch: ['<rootDir>/tests/cli/**/*.test.js']
38
+ },
39
+ {
40
+ displayName: 'preload',
41
+ testEnvironment: 'node',
42
+ testMatch: ['<rootDir>/tests/preload/**/*.test.js'],
43
+ moduleNameMapper: {
44
+ '^electron$': '<rootDir>/tests/mocks/electron.js'
45
+ }
46
+ }
47
+ ]
48
+ };
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "floatnote",
3
+ "version": "1.0.0",
4
+ "description": "Transparent always-on-top drawing and note-taking overlay for macOS",
5
+ "main": "src/main.js",
6
+ "bin": {
7
+ "floatnote": "bin/floatnote.js"
8
+ },
9
+ "scripts": {
10
+ "start": "electron .",
11
+ "dev": "electron . --enable-logging",
12
+ "build": "electron-builder --mac --publish never",
13
+ "release": "electron-builder --mac --publish always",
14
+ "test": "jest",
15
+ "test:watch": "jest --watch",
16
+ "test:coverage": "jest --coverage"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/josmanvis/floatnote.git"
21
+ },
22
+ "homepage": "https://github.com/josmanvis/floatnote",
23
+ "keywords": [
24
+ "electron",
25
+ "drawing",
26
+ "overlay",
27
+ "notes",
28
+ "macos",
29
+ "transparent",
30
+ "annotation"
31
+ ],
32
+ "author": "Jose",
33
+ "license": "MIT",
34
+ "engines": {
35
+ "node": ">=16.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "electron": "^33.0.0",
39
+ "electron-builder": "^25.0.0",
40
+ "jest": "^29.7.0",
41
+ "jest-environment-jsdom": "^29.7.0"
42
+ },
43
+ "build": {
44
+ "appId": "com.floatnote.app",
45
+ "productName": "Floatnote",
46
+ "mac": {
47
+ "category": "public.app-category.productivity",
48
+ "target": [
49
+ "dmg",
50
+ "zip"
51
+ ]
52
+ },
53
+ "publish": {
54
+ "provider": "github",
55
+ "owner": "josmanvis",
56
+ "repo": "floatnote"
57
+ }
58
+ }
59
+ }
Binary file
package/src/index.html ADDED
@@ -0,0 +1,296 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'">
7
+ <title>Floatnote</title>
8
+ <link rel="stylesheet" href="styles.css">
9
+ </head>
10
+ <body>
11
+ <div id="app">
12
+ <!-- Focus border overlay -->
13
+ <div id="focus-border"></div>
14
+
15
+ <!-- Size toolbar (left) -->
16
+ <div id="size-toolbar">
17
+ <div class="dropdown-container">
18
+ <button id="size-toggle" class="tool-btn" title="Window size">
19
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
20
+ <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/>
21
+ </svg>
22
+ </button>
23
+ <div class="dropdown-menu">
24
+ <button class="dropdown-item" data-size="sm">
25
+ <span class="size-label">SM</span>
26
+ <span class="size-desc">33% × 50%</span>
27
+ </button>
28
+ <button class="dropdown-item active" data-size="md">
29
+ <span class="size-label">MD</span>
30
+ <span class="size-desc">33% × 100%</span>
31
+ </button>
32
+ <button class="dropdown-item" data-size="lg">
33
+ <span class="size-label">LG</span>
34
+ <span class="size-desc">100% × 100%</span>
35
+ </button>
36
+ </div>
37
+ </div>
38
+
39
+ <label class="pin-toggle" title="Keep window on top">
40
+ <input type="checkbox" id="pin-checkbox" checked>
41
+ <svg class="pin-icon" viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
42
+ <path d="M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z"/>
43
+ </svg>
44
+ </label>
45
+ </div>
46
+
47
+ <!-- Main toolbar (right) -->
48
+ <div id="toolbar">
49
+ <div class="toolbar-group">
50
+ <button id="select-mode" class="tool-btn" title="Select mode (V)">
51
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
52
+ <path d="M4 2l14 11-6 .5 3.5 7.5-2.5 1-3.5-7.5L4 19V2z"/>
53
+ </svg>
54
+ </button>
55
+ <button id="draw-mode" class="tool-btn active" title="Draw mode (B)">
56
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
57
+ <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
58
+ </svg>
59
+ </button>
60
+ <button id="text-mode" class="tool-btn" title="Text mode (T)">
61
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
62
+ <path d="M5 4v3h5.5v12h3V7H19V4z"/>
63
+ </svg>
64
+ </button>
65
+ </div>
66
+
67
+ <div class="toolbar-divider"></div>
68
+
69
+ <div class="dropdown-container">
70
+ <button id="color-toggle" class="tool-btn color-swatch-btn" title="Color">
71
+ <span class="current-color" style="background: #ffffff"></span>
72
+ </button>
73
+ <div class="dropdown-menu color-dropdown">
74
+ <div class="color-grid">
75
+ <button class="color-btn active" data-color="#ffffff" style="background: #ffffff"></button>
76
+ <button class="color-btn" data-color="#1a1a1a" style="background: #1a1a1a"></button>
77
+ <button class="color-btn" data-color="#ef4444" style="background: #ef4444"></button>
78
+ <button class="color-btn" data-color="#f97316" style="background: #f97316"></button>
79
+ <button class="color-btn" data-color="#eab308" style="background: #eab308"></button>
80
+ <button class="color-btn" data-color="#22c55e" style="background: #22c55e"></button>
81
+ <button class="color-btn" data-color="#3b82f6" style="background: #3b82f6"></button>
82
+ <button class="color-btn" data-color="#a855f7" style="background: #a855f7"></button>
83
+ <button class="color-btn" data-color="#ec4899" style="background: #ec4899"></button>
84
+ <button class="color-btn" data-color="#06b6d4" style="background: #06b6d4"></button>
85
+ <button class="color-btn" data-color="#84cc16" style="background: #84cc16"></button>
86
+ <button class="color-btn" data-color="#f43f5e" style="background: #f43f5e"></button>
87
+ </div>
88
+ </div>
89
+ </div>
90
+
91
+ <div class="dropdown-container">
92
+ <button id="stroke-toggle" class="tool-btn" title="Stroke size">
93
+ <span class="current-stroke"></span>
94
+ </button>
95
+ <div class="dropdown-menu stroke-dropdown">
96
+ <button class="stroke-option" data-width="2">
97
+ <span class="stroke-dot" style="width: 4px; height: 4px"></span>
98
+ <span>Fine</span>
99
+ </button>
100
+ <button class="stroke-option active" data-width="4">
101
+ <span class="stroke-dot" style="width: 8px; height: 8px"></span>
102
+ <span>Medium</span>
103
+ </button>
104
+ <button class="stroke-option" data-width="8">
105
+ <span class="stroke-dot" style="width: 12px; height: 12px"></span>
106
+ <span>Thick</span>
107
+ </button>
108
+ <button class="stroke-option" data-width="12">
109
+ <span class="stroke-dot" style="width: 16px; height: 16px"></span>
110
+ <span>Heavy</span>
111
+ </button>
112
+ </div>
113
+ </div>
114
+
115
+ <div class="toolbar-divider"></div>
116
+
117
+ <button id="clear-btn" class="tool-btn danger" title="Clear all">
118
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
119
+ <path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
120
+ </svg>
121
+ </button>
122
+ </div>
123
+
124
+ <!-- Drag handle -->
125
+ <div id="drag-handle" title="Drag to move"></div>
126
+
127
+ <!-- Left edge resize handle -->
128
+ <div id="left-resize-handle" title="Drag to resize"></div>
129
+
130
+ <!-- Canvas for drawing -->
131
+ <canvas id="draw-canvas"></canvas>
132
+
133
+ <!-- Container for text items -->
134
+ <div id="text-container"></div>
135
+
136
+ <!-- Selection rectangle overlay -->
137
+ <div id="selection-rect"></div>
138
+
139
+ <!-- Pagination island (right side) -->
140
+ <div id="pagination-island">
141
+ <button id="prev-note" class="pagination-btn" title="Previous note ([)">
142
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
143
+ <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
144
+ </svg>
145
+ </button>
146
+ <span id="note-counter">1/1</span>
147
+ <button id="next-note" class="pagination-btn" title="Next note (])">
148
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
149
+ <path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z"/>
150
+ </svg>
151
+ </button>
152
+ <div class="toolbar-divider"></div>
153
+ <button id="new-note" class="pagination-btn" title="New note (N)">
154
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
155
+ <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
156
+ </svg>
157
+ </button>
158
+ </div>
159
+
160
+ <!-- Settings panel -->
161
+ <div id="settings-panel" class="settings-panel">
162
+ <div class="settings-header">
163
+ <h2>Settings</h2>
164
+ <button id="settings-close" class="settings-close-btn">✕</button>
165
+ </div>
166
+ <div class="settings-content">
167
+ <div class="settings-section">
168
+ <h3>Gestures</h3>
169
+ <label class="settings-toggle">
170
+ <span>Pinch to zoom</span>
171
+ <input type="checkbox" id="setting-pinch-zoom" checked>
172
+ <span class="toggle-slider"></span>
173
+ </label>
174
+ <label class="settings-toggle">
175
+ <span>Two-finger pan</span>
176
+ <input type="checkbox" id="setting-pan" checked>
177
+ <span class="toggle-slider"></span>
178
+ </label>
179
+ <label class="settings-toggle">
180
+ <span>Rotate gesture</span>
181
+ <input type="checkbox" id="setting-rotate" checked>
182
+ <span class="toggle-slider"></span>
183
+ </label>
184
+ </div>
185
+ <div class="settings-section">
186
+ <h3>Appearance</h3>
187
+ <div class="settings-bg-options">
188
+ <span class="settings-label">Active Background</span>
189
+ <div class="bg-option-group">
190
+ <label class="bg-option">
191
+ <input type="radio" name="bg-mode" value="transparent" checked>
192
+ <span class="bg-option-box transparent"></span>
193
+ <span>Clear</span>
194
+ </label>
195
+ <label class="bg-option">
196
+ <input type="radio" name="bg-mode" value="blur">
197
+ <span class="bg-option-box blur"></span>
198
+ <span>Blur</span>
199
+ </label>
200
+ <label class="bg-option">
201
+ <input type="radio" name="bg-mode" value="dark">
202
+ <span class="bg-option-box dark"></span>
203
+ <span>Dark</span>
204
+ </label>
205
+ </div>
206
+ </div>
207
+ <div class="settings-slider">
208
+ <span class="settings-label">Active Opacity</span>
209
+ <input type="range" id="setting-active-opacity" min="0" max="100" value="100">
210
+ <span class="slider-value" id="active-opacity-value">100%</span>
211
+ </div>
212
+ <div class="settings-bg-options">
213
+ <span class="settings-label">Inactive Background</span>
214
+ <div class="bg-option-group">
215
+ <label class="bg-option">
216
+ <input type="radio" name="inactive-bg-mode" value="transparent" checked>
217
+ <span class="bg-option-box transparent"></span>
218
+ <span>Clear</span>
219
+ </label>
220
+ <label class="bg-option">
221
+ <input type="radio" name="inactive-bg-mode" value="blur">
222
+ <span class="bg-option-box blur"></span>
223
+ <span>Blur</span>
224
+ </label>
225
+ <label class="bg-option">
226
+ <input type="radio" name="inactive-bg-mode" value="dark">
227
+ <span class="bg-option-box dark"></span>
228
+ <span>Dark</span>
229
+ </label>
230
+ </div>
231
+ </div>
232
+ <div class="settings-slider">
233
+ <span class="settings-label">Inactive Opacity</span>
234
+ <input type="range" id="setting-inactive-opacity" min="0" max="100" value="50">
235
+ <span class="slider-value" id="inactive-opacity-value">50%</span>
236
+ </div>
237
+ <label class="settings-toggle">
238
+ <span>Show zoom controls</span>
239
+ <input type="checkbox" id="setting-zoom-controls" checked>
240
+ <span class="toggle-slider"></span>
241
+ </label>
242
+ </div>
243
+ <div class="settings-section">
244
+ <h3>Behavior</h3>
245
+ <label class="settings-toggle">
246
+ <span>Always open with clean slate</span>
247
+ <input type="checkbox" id="setting-clean-slate">
248
+ <span class="toggle-slider"></span>
249
+ </label>
250
+ </div>
251
+ <div class="settings-section">
252
+ <h3>Storage</h3>
253
+ <label class="settings-toggle">
254
+ <span>Auto-save notes to ~/.floatnote</span>
255
+ <input type="checkbox" id="setting-auto-save-folder">
256
+ <span class="toggle-slider"></span>
257
+ </label>
258
+ <button id="open-folder-btn" class="settings-btn">
259
+ Open Notes Folder
260
+ </button>
261
+ </div>
262
+ <div class="settings-section">
263
+ <h3>Keyboard Shortcuts</h3>
264
+ <div class="shortcuts-list">
265
+ <div class="shortcut-item"><span>Toggle Floatnote</span><kbd>⌘⇧G</kbd></div>
266
+ <div class="shortcut-item"><span>Quick Toggle</span><kbd>⌥Space</kbd></div>
267
+ <div class="shortcut-item"><span>Settings</span><kbd>⌘,</kbd></div>
268
+ <div class="shortcut-item"><span>Toggle pin</span><kbd>⌘P</kbd></div>
269
+ <div class="shortcut-item"><span>Undo</span><kbd>⌘Z</kbd></div>
270
+ <div class="shortcut-item"><span>Redo</span><kbd>⌘⇧Z</kbd></div>
271
+ <div class="shortcut-item"><span>Select all</span><kbd>⌘A</kbd></div>
272
+ <div class="shortcut-item"><span>Select mode</span><kbd>V</kbd></div>
273
+ <div class="shortcut-item"><span>Draw mode</span><kbd>B</kbd></div>
274
+ <div class="shortcut-item"><span>Text mode</span><kbd>T</kbd></div>
275
+ <div class="shortcut-item"><span>Copy</span><kbd>⌘C</kbd></div>
276
+ <div class="shortcut-item"><span>Paste</span><kbd>⌘V</kbd></div>
277
+ <div class="shortcut-item"><span>Delete</span><kbd>D</kbd></div>
278
+ <div class="shortcut-item"><span>Export PNG</span><kbd>⌘S</kbd></div>
279
+ <div class="shortcut-item"><span>Zoom in</span><kbd>⌘+</kbd></div>
280
+ <div class="shortcut-item"><span>Zoom out</span><kbd>⌘-</kbd></div>
281
+ <div class="shortcut-item"><span>Reset view</span><kbd>⌘0</kbd></div>
282
+ <div class="shortcut-item"><span>Previous note</span><kbd>← or [</kbd></div>
283
+ <div class="shortcut-item"><span>Next note</span><kbd>→ or ]</kbd></div>
284
+ <div class="shortcut-item"><span>New note</span><kbd>N</kbd></div>
285
+ <div class="shortcut-item"><span>Small size</span><kbd>1</kbd></div>
286
+ <div class="shortcut-item"><span>Medium size</span><kbd>2</kbd></div>
287
+ <div class="shortcut-item"><span>Large size</span><kbd>3</kbd></div>
288
+ </div>
289
+ </div>
290
+ </div>
291
+ </div>
292
+ </div>
293
+
294
+ <script src="renderer.js"></script>
295
+ </body>
296
+ </html>