@tobq/boardclip 0.0.0-stage → 2.1.108

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 (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -2
  3. package/assets/boardclip-icon.png +0 -0
  4. package/bin/boardclip.js +43 -0
  5. package/editor-preload.js +71 -0
  6. package/editor.html +220 -0
  7. package/icon.png +0 -0
  8. package/icon@2x.png +0 -0
  9. package/iconTemplate.png +0 -0
  10. package/iconTemplate@2x.png +0 -0
  11. package/index.html +1339 -0
  12. package/lib/appearance.js +183 -0
  13. package/lib/auto-update.js +306 -0
  14. package/lib/backup-worker.js +46 -0
  15. package/lib/backup.js +275 -0
  16. package/lib/blob-field-store.js +275 -0
  17. package/lib/blob-store.js +68 -0
  18. package/lib/build-info.js +89 -0
  19. package/lib/clip-blob-store.js +161 -0
  20. package/lib/clip-revision.js +81 -0
  21. package/lib/clipboard-capture.js +95 -0
  22. package/lib/clipboard-follow.js +98 -0
  23. package/lib/clipboard-model.js +1235 -0
  24. package/lib/cloud-accounts.js +250 -0
  25. package/lib/conflict-model.js +186 -0
  26. package/lib/control-client.js +87 -0
  27. package/lib/control-server.js +149 -0
  28. package/lib/diagnostics.js +121 -0
  29. package/lib/drag-files.js +48 -0
  30. package/lib/ensure-directory.js +56 -0
  31. package/lib/fork-names.js +35 -0
  32. package/lib/fs-probe.js +132 -0
  33. package/lib/history-feed.js +48 -0
  34. package/lib/hmac-auth.js +78 -0
  35. package/lib/macos-hotkey.js +297 -0
  36. package/lib/macos-paste.js +112 -0
  37. package/lib/mcp-core.js +270 -0
  38. package/lib/mcp-installers.js +284 -0
  39. package/lib/mcp-paths.js +99 -0
  40. package/lib/p2p-crypto.js +54 -0
  41. package/lib/p2p-discovery.js +191 -0
  42. package/lib/quick-paste.js +187 -0
  43. package/lib/retention.js +43 -0
  44. package/lib/sync-delta.js +227 -0
  45. package/lib/sync-journal.js +181 -0
  46. package/lib/sync-paths.js +73 -0
  47. package/lib/tailscale.js +80 -0
  48. package/lib/text-blob-store.js +38 -0
  49. package/lib/windows-clipboard.js +213 -0
  50. package/lib/windows-console.js +63 -0
  51. package/lib/windows-dwm.js +183 -0
  52. package/lib/windows-hook-worker.js +236 -0
  53. package/lib/windows-hook.js +91 -0
  54. package/lib/windows-paste.js +185 -0
  55. package/main.js +7540 -0
  56. package/mcp/boardclip-mcp.js +255 -0
  57. package/mcp-approval-preload.js +22 -0
  58. package/mcp-approval.html +218 -0
  59. package/package.json +55 -4
  60. package/preload.js +106 -0
  61. package/site/index.html +1624 -0
  62. package/site/shared/clip-search.js +2330 -0
  63. package/site/shared/clipboard-popup.css +1046 -0
  64. package/site/shared/clipboard-tokens.css +326 -0
  65. package/site/shared/clipboard-ui-core.js +6921 -0
  66. package/site/shared/clipboard-window.css +36 -0
  67. package/site/shared/vendor/cm5/README.md +52 -0
  68. package/site/shared/vendor/cm5/codemirror.css +344 -0
  69. package/site/shared/vendor/cm5/codemirror.js +9884 -0
  70. package/site/shared/vendor/cm5/diff-match-patch.js +2228 -0
  71. package/site/shared/vendor/cm5/merge.css +119 -0
  72. package/site/shared/vendor/cm5/merge.js +1182 -0
  73. package/site/shared/vendor/fonts/README.md +19 -0
  74. package/site/shared/vendor/fonts/material-symbols-rounded.woff2 +0 -0
  75. package/viewer-preload.js +51 -0
  76. package/viewer.html +129 -0
@@ -0,0 +1,326 @@
1
+ /* ============================================================
2
+ BoardClip design tokens - the single source of truth for the
3
+ whole product (app popup, editor, conflict view, AI-approval
4
+ modal, and the marketing site). Imported first by
5
+ clipboard-popup.css (@import) and by site/styles.css so every
6
+ surface renders from ONE palette/scale and cannot drift.
7
+
8
+ Three tiers:
9
+ (a) PRIMITIVES + ROLES on :root - raw scales plus the role
10
+ tokens components size with
11
+ (type, weight, control height,
12
+ radius, gutter, bar height)
13
+ (b) SEMANTIC on [data-theme] - the colour names components
14
+ reference
15
+ (c) VARIANT overrides - data-surface/-accent/-density/
16
+ -corners/-borders swap a small,
17
+ disjoint set of tokens
18
+ Components size text, controls and corners with the ROLE tokens
19
+ (--fs-meta/--fs-ui/--fs-text, --fw-*, --lh-*, --ctl-*, --r-ctl/
20
+ --r-chip/--r-panel, --gutter); the raw --sp-* and --r-1..4 scales
21
+ stay for spacing and inset corners. Density and corners remap the
22
+ role tokens directly (a role token resolved on :root would not see
23
+ a .bc-popup variant override of the primitive it points at).
24
+ Cascade (later wins on equal specificity):
25
+ primitives -> theme -> surface -> accent -> density -> corners/borders
26
+ All variant attributes ride on the SAME element that carries
27
+ data-theme (:root on <html> for the app/editor/modal, .bc-popup
28
+ on the demo window), mirrored in every selector below.
29
+ ============================================================ */
30
+
31
+ /* (a) PRIMITIVES - raw scales, identical in every theme */
32
+ :root {
33
+ /* Graphite ramp (cool-tinted neutral), dark -> light */
34
+ --g-950: #0b0d10;
35
+ --g-900: #0f1216;
36
+ --g-850: #14171b;
37
+ --g-800: #1b1f24;
38
+ --g-750: #23272e;
39
+ --g-700: #2d323a;
40
+ --g-600: #3f4650;
41
+ --g-500: #6b7280;
42
+ --g-400: #868d97;
43
+ --g-300: #a8afb8;
44
+ --g-200: #cdd2d8;
45
+ --g-100: #e6e8eb;
46
+ --g-050: #f4f5f7;
47
+ --white: #ffffff;
48
+
49
+ /* Brand accent (cool blue) + audition accents */
50
+ --blue-700: #1d4ed8;
51
+ --blue-600: #2563eb;
52
+ --blue-500: #3b82f6;
53
+ --blue-400: #60a5fa;
54
+ --blue-300: #93c5fd;
55
+ --teal-800: #115e59;
56
+ --teal-600: #0d9488;
57
+ --teal-500: #14b8a6;
58
+ --teal-400: #2dd4bf;
59
+
60
+ /* Functional status colours - never used as the brand accent.
61
+ 500 = dark theme, 600 = light theme. */
62
+ --green-500: #34d399;
63
+ --green-600: #059669;
64
+ --amber-500: #f59e0b;
65
+ --amber-600: #d97706;
66
+ --red-500: #f87171;
67
+ --red-600: #dc2626;
68
+
69
+ /* The OS's own window-control colours, for the windows a page draws (the
70
+ website demo, Core.attachWebWindow): macOS traffic lights and their
71
+ glyph ink, the Windows close button's red. Never a UI accent. */
72
+ --os-mac-close: #ff5f57;
73
+ --os-mac-min: #febc2e;
74
+ --os-mac-max: #28c840;
75
+ --os-mac-ink: #00000099;
76
+ --os-win-close: #c42b1c;
77
+
78
+ /* Spacing scale (4/8-based) */
79
+ --sp-1: 2px; --sp-2: 4px; --sp-3: 6px; --sp-4: 8px; --sp-5: 10px;
80
+ --sp-6: 12px; --sp-7: 14px; --sp-8: 16px; --sp-10: 20px; --sp-12: 24px;
81
+ /* Left/right padding of every bar and content area, in every window */
82
+ --gutter: 14px;
83
+ --bar-h: 32px;
84
+
85
+ /* Radius scale + roles: controls, chips, floating surfaces */
86
+ --r-1: 4px; --r-2: 6px; --r-3: 8px; --r-4: 10px; --r-pill: 999px;
87
+ --r-ctl: 6px; --r-chip: 999px; --r-panel: 8px;
88
+
89
+ /* Type roles. meta = row meta, chips, overlines, foot/status text, counts;
90
+ ui = every label, menu item, button, input value, clip title/preview,
91
+ dialog body; text = anything you type into (search, editor, find, title,
92
+ merge panes); display = site hero only. Nothing smaller than 11px. */
93
+ --fs-meta: 11px; --fs-ui: 12px; --fs-text: 13px; --fs-display: 18px;
94
+ --lh-ui: 1.35; --lh-text: 1.5;
95
+ /* Two weights only */
96
+ --fw-regular: 400; --fw-strong: 600;
97
+ --font-sans: system-ui, "Segoe UI", -apple-system, sans-serif;
98
+ --font-mono: "Cascadia Code", "Consolas", ui-monospace, monospace;
99
+
100
+ /* Control heights: chips/keys/foot buttons, icon buttons/menu rows,
101
+ inputs/segmented/.btn. Height + horizontal padding, no vertical padding. */
102
+ --ctl-sm: 20px; --ctl-md: 24px; --ctl-lg: 28px;
103
+
104
+ /* Icon sizes (Material Symbols): md in a --ctl-md box, sm in a --ctl-sm box */
105
+ --icon-sm: 14px; --icon-md: 16px; --icon-lg: 18px;
106
+
107
+ /* Motion: the one duration + curve for every state transition */
108
+ --dur: 130ms;
109
+ --ease: cubic-bezier(.2, .7, .2, 1);
110
+
111
+ /* Glass blur (theme-independent) */
112
+ --glass-blur: blur(14px) saturate(1.3);
113
+ }
114
+
115
+ /* Theme-agnostic derived vars (reference semantic tokens set below, so they
116
+ resolve per element, accent and theme variants included) */
117
+ :root[data-theme], .bc-popup[data-theme] {
118
+ /* The one scrollbar: an inset thumb (2px transparent border + padding-box
119
+ clip in the shared rule), so it works on any surface, glass included. */
120
+ --scrollbar-size: 8px;
121
+ --scrollbar-thumb: var(--line-strong);
122
+ --scrollbar-thumb-hover: var(--text-dim);
123
+ /* The one keyboard focus ring (box-shadow: no outline, no layout shift) */
124
+ --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
125
+ /* Resting fill of a .btn: a tint of the text colour, so it reads on any
126
+ surface (popup, settings, an opaque dialog, glass). */
127
+ --ctl-fill: color-mix(in srgb, var(--text) 9%, transparent);
128
+ --ctl-fill-hover: color-mix(in srgb, var(--text) 15%, transparent);
129
+ /* A trailing control's edge: an icon button at the end of a bar or field
130
+ sits this far in, so its GLYPH (not its hover box) lands on the gutter
131
+ with the text above and below it. Here (not on :root) so it follows a
132
+ .bc-popup density override of --gutter / --ctl-md. */
133
+ --edge-ctl: calc(var(--gutter) - (var(--ctl-md) - var(--icon-md)) / 2);
134
+ }
135
+
136
+ /* (b) SEMANTIC - the ONLY colour names components reference. Keep names
137
+ stable across the redesign; only the mapped VALUES change.
138
+ Lines: --line = section/bar/pane dividers, --line-faint = list row
139
+ separators, --menu-edge = the 1px ring of floating surfaces. --line-strong
140
+ is a fill (scrollbar thumb, switch track), never a 1px line.
141
+ Hovers: --hover on in-surface transparent things, --menu-hover in menus. */
142
+ :root[data-theme="dark"], .bc-popup[data-theme="dark"] {
143
+ color-scheme: dark;
144
+ --bg: var(--g-950);
145
+ --surface-solid: var(--g-850);
146
+ --surface2-solid: var(--g-800);
147
+ --input-solid: color-mix(in srgb, var(--g-100) 7%, transparent); /* a wash: lifts the band, the canvas and menus alike */
148
+ --surface: var(--surface-solid);
149
+ --surface2: var(--surface2-solid);
150
+ --input: var(--input-solid);
151
+ --menu: var(--g-800); /* floating menus/dialogs - stays OPAQUE under glass */
152
+ --menu-hover: var(--g-700); /* menu-item hover - a step lighter than --menu so it reads */
153
+ --menu-edge: rgba(255, 255, 255, .15); /* soft 1px ring so menus separate from the backdrop */
154
+ --text: var(--g-100);
155
+ --text-dim: var(--g-400);
156
+ --line: var(--g-750);
157
+ --line-strong: var(--g-700);
158
+ --line-faint: color-mix(in srgb, var(--g-050) 7%, transparent);
159
+ --hover: color-mix(in srgb, var(--g-100) 6%, transparent);
160
+ --similar-mix: 60%; /* a similar row's wash, as a share of --hover (.item.similar) */
161
+ --accent: var(--blue-500);
162
+ --accent-hover: var(--blue-400);
163
+ --accent-text: var(--blue-400); /* accent AS TEXT: 4.5:1 on the surface and on --accent-bg */
164
+ --accent-bg: color-mix(in srgb, var(--accent) 16%, transparent);
165
+ --accent-bg-strong: color-mix(in srgb, var(--accent) 26%, transparent);
166
+ --active-fg: var(--g-950); /* dark ink on blue = 5.7:1, beats white */
167
+ --shadow: rgba(0, 0, 0, .5);
168
+ --scrim: rgba(0, 0, 0, .5); /* backdrop behind a modal dialog */
169
+ --green: var(--green-500);
170
+ --green-bg: color-mix(in srgb, var(--green) 16%, transparent);
171
+ --red: var(--red-500);
172
+ --red-bg: color-mix(in srgb, var(--red) 14%, transparent);
173
+ --danger-fg: var(--g-950); /* ink on --red (a danger button); accent variants never touch it */
174
+ --pin: var(--amber-500);
175
+ --mark-bg: color-mix(in srgb, var(--accent) 22%, transparent);
176
+ --mark-bg-current: color-mix(in srgb, var(--accent) 50%, transparent);
177
+ --mark-fg: var(--blue-300);
178
+ --glass-tint: rgba(15, 18, 22, .62);
179
+ --canvas: var(--bg);
180
+ }
181
+ :root[data-theme="light"], .bc-popup[data-theme="light"] {
182
+ color-scheme: light;
183
+ --bg: var(--g-050);
184
+ --surface-solid: var(--white);
185
+ --surface2-solid: var(--g-050);
186
+ --input-solid: color-mix(in srgb, var(--g-900) 6%, transparent); /* a wash: reads on white and on the grey canvas */
187
+ --surface: var(--surface-solid);
188
+ --surface2: var(--surface2-solid);
189
+ --input: var(--input-solid);
190
+ --menu: var(--white); /* floating menus/dialogs - stays OPAQUE under glass */
191
+ --menu-hover: var(--g-100); /* menu-item hover - light grey on the white menu */
192
+ --menu-edge: rgba(24, 27, 31, .16); /* soft 1px ring (dark, since white is invisible on white) */
193
+ --text: var(--g-900);
194
+ --text-dim: var(--g-500);
195
+ --line: var(--g-100);
196
+ --line-strong: var(--g-200);
197
+ --line-faint: color-mix(in srgb, var(--g-900) 8%, transparent); /* was invisible on white */
198
+ --hover: color-mix(in srgb, var(--g-900) 7%, transparent); /* reads on white (the popup list, settings) */
199
+ --similar-mix: 35%; /* on white 60% sat too close to hover; hover stays the strongest neutral row state */
200
+ --accent: var(--blue-600);
201
+ --accent-hover: var(--blue-500);
202
+ --accent-text: var(--blue-700); /* blue-600 is 4.0:1 on its own tint */
203
+ --accent-bg: color-mix(in srgb, var(--accent) 12%, transparent);
204
+ --accent-bg-strong: color-mix(in srgb, var(--accent) 20%, transparent);
205
+ --active-fg: var(--white); /* white on blue-600 = 5.1:1, beats black */
206
+ --shadow: rgba(24, 24, 27, .14);
207
+ --scrim: rgba(15, 18, 22, .28);
208
+ --green: var(--green-600);
209
+ --green-bg: color-mix(in srgb, var(--green) 16%, transparent);
210
+ --red: var(--red-600);
211
+ --red-bg: color-mix(in srgb, var(--red) 12%, transparent);
212
+ --danger-fg: var(--white); /* white on red-600 = 4.8:1 */
213
+ --pin: var(--amber-600);
214
+ --mark-bg: color-mix(in srgb, var(--accent) 16%, transparent);
215
+ --mark-bg-current: color-mix(in srgb, var(--accent) 40%, transparent);
216
+ --mark-fg: var(--blue-600);
217
+ --glass-tint: rgba(255, 255, 255, .84); /* light stays light over a dark desktop / dark system acrylic (.5 went mid-grey) */
218
+ --canvas: var(--bg);
219
+ }
220
+
221
+ /* (c) VARIANT OVERRIDES - small, disjoint sets, authored after the
222
+ theme blocks so they win by source order at equal specificity. */
223
+
224
+ /* Surface: under glass the OS acrylic / vibrancy shows through. The
225
+ content (--canvas) is the one scrim; the chrome band (--surface) is a
226
+ LIFT over it, lighter than the content whatever the desktop is (two
227
+ tones, as on solid); a field is a wash over either. color-mix can't
228
+ read the token it is redefining, so these are authored per-theme
229
+ (higher specificity than the plain theme block, so they also win
230
+ cleanly). "solid" is a no-op that exists so the switcher can force
231
+ glass off. */
232
+ :root[data-theme="dark"][data-surface="glass"], .bc-popup[data-theme="dark"][data-surface="glass"] {
233
+ --canvas: var(--glass-tint);
234
+ --surface: color-mix(in srgb, var(--white) 6%, transparent);
235
+ --surface2: color-mix(in srgb, var(--g-800) 58%, transparent);
236
+ --input: color-mix(in srgb, var(--g-100) 8%, transparent);
237
+ }
238
+ :root[data-theme="light"][data-surface="glass"], .bc-popup[data-theme="light"][data-surface="glass"] {
239
+ --canvas: var(--glass-tint);
240
+ --surface: color-mix(in srgb, var(--white) 70%, transparent); /* the band: a white lift over the scrim, the blur still shows */
241
+ --surface2: color-mix(in srgb, var(--white) 72%, transparent); /* WHITE, not grey - brighter frost for hover/selected */
242
+ /* A field is a dark WASH, as on solid light (a white one vanished on any
243
+ light frost and on the opaque white menu: dialogs, the demo page). */
244
+ --input: color-mix(in srgb, var(--g-900) 6%, transparent);
245
+ /* What shows through can still darken the frost: dim text one step darker keeps it readable. */
246
+ --text-dim: var(--g-600);
247
+ }
248
+
249
+ /* Accent: blue is the default (no block). accent-bg / mark-bg / focus ring
250
+ re-derive automatically because they are color-mix over --accent. */
251
+ :root[data-accent="teal"], .bc-popup[data-accent="teal"] {
252
+ --accent: var(--teal-500);
253
+ --accent-hover: var(--teal-400);
254
+ --accent-text: var(--teal-400);
255
+ --mark-fg: var(--teal-400);
256
+ }
257
+ :root[data-accent="mono"], .bc-popup[data-accent="mono"] {
258
+ --accent: var(--g-300);
259
+ --accent-hover: var(--g-200);
260
+ --accent-text: var(--g-200);
261
+ --active-fg: var(--g-950);
262
+ --mark-fg: var(--g-100);
263
+ }
264
+ /* The light theme needs a darker step of both presets: teal-500 and g-300
265
+ read under 3:1 on white (check glyphs, focus ring, switch), and white ink
266
+ on teal-500 is 2.5:1. Each pair passes the same rule as a System / Custom
267
+ colour (ui-tokens.test.js checks it); teal as TEXT needs teal-800 (teal-600
268
+ is 3.4:1 on --g-050). */
269
+ :root[data-theme="light"][data-accent="teal"], .bc-popup[data-theme="light"][data-accent="teal"] {
270
+ --accent: var(--teal-600);
271
+ --accent-hover: var(--teal-500);
272
+ --accent-text: var(--teal-800);
273
+ --active-fg: var(--g-950);
274
+ --mark-fg: var(--teal-600);
275
+ }
276
+ :root[data-theme="light"][data-accent="mono"], .bc-popup[data-theme="light"][data-accent="mono"] {
277
+ --accent: var(--g-700);
278
+ --accent-hover: var(--g-600);
279
+ --accent-text: var(--g-700);
280
+ --active-fg: var(--white);
281
+ --mark-fg: var(--g-900);
282
+ }
283
+ /* A System or Custom colour (Core.applyAppearance): data-accent="custom" plus
284
+ six inline vars, the colour's shade for each theme, the ink on it and its
285
+ text shade, already contrast-checked (Core.accentShades). The theme picks
286
+ its set, so a theme flip needs no script; hover and find-match text derive
287
+ here. */
288
+ :root[data-theme="dark"][data-accent="custom"], .bc-popup[data-theme="dark"][data-accent="custom"] {
289
+ --accent: var(--accent-custom-dark);
290
+ --active-fg: var(--accent-ink-dark);
291
+ --accent-text: var(--accent-text-dark);
292
+ }
293
+ :root[data-theme="light"][data-accent="custom"], .bc-popup[data-theme="light"][data-accent="custom"] {
294
+ --accent: var(--accent-custom-light);
295
+ --active-fg: var(--accent-ink-light);
296
+ --accent-text: var(--accent-text-light);
297
+ }
298
+ :root[data-accent="custom"], .bc-popup[data-accent="custom"] {
299
+ --accent-hover: color-mix(in srgb, var(--accent) 82%, var(--text));
300
+ --mark-fg: color-mix(in srgb, var(--accent) 70%, var(--text));
301
+ }
302
+
303
+ /* Density: compact tightens spacing, the gutter and control heights. The type
304
+ roles stay put (meta 11 / ui 12 / text 13 are already one step apart, so a
305
+ smaller ui or text would merge with its neighbour), and every spacing and
306
+ control step stays distinct. ui-tokens.test.js checks both under each
307
+ density. */
308
+ :root[data-density="compact"], .bc-popup[data-density="compact"] {
309
+ --sp-3: 5px; --sp-4: 6px; --sp-5: 8px; --sp-6: 10px; --sp-7: 12px; --sp-8: 14px;
310
+ --gutter: 12px;
311
+ --ctl-sm: 18px; --ctl-md: 22px; --ctl-lg: 26px;
312
+ }
313
+
314
+ /* Corners: sharp tightens the radius scale and the control/panel roles
315
+ (chips stay pills). */
316
+ :root[data-corners="sharp"], .bc-popup[data-corners="sharp"] {
317
+ --r-1: 2px; --r-2: 3px; --r-3: 4px; --r-4: 4px;
318
+ --r-ctl: 3px; --r-panel: 4px;
319
+ }
320
+
321
+ /* Borders: borderless dissolves divider lines (keeps a faint strong fill). */
322
+ :root[data-borders="borderless"], .bc-popup[data-borders="borderless"] {
323
+ --line: transparent;
324
+ --line-faint: transparent;
325
+ --line-strong: color-mix(in srgb, var(--text) 8%, transparent);
326
+ }