@webmcp-auto-ui/agent 2.5.27 → 2.5.28
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.
- package/package.json +10 -2
- package/src/autoui-server.ts +63 -75
- package/src/index.ts +7 -2
- package/src/loop.ts +48 -21
- package/src/providers/factory.ts +15 -1
- package/src/providers/hawk-models.ts +22 -0
- package/src/providers/hawk.ts +181 -0
- package/src/providers/transformers.worker.ts +5 -32
- package/src/recipes/_generated.ts +81 -17
- package/src/recipes/notebook-playbook.md +81 -17
- package/src/server/hawkProxy.ts +54 -0
- package/src/server/index.ts +2 -0
- package/src/util/opfs-cache.ts +101 -2
- package/src/util/storage-inventory.ts +195 -0
- package/src/notebook-widgets/compact.ts +0 -312
- package/src/notebook-widgets/document.ts +0 -372
- package/src/notebook-widgets/editorial.ts +0 -348
- package/src/notebook-widgets/recipes/compact.md +0 -104
- package/src/notebook-widgets/recipes/document.md +0 -100
- package/src/notebook-widgets/recipes/editorial.md +0 -104
- package/src/notebook-widgets/recipes/workspace.md +0 -94
- package/src/notebook-widgets/shared.ts +0 -1064
- package/src/notebook-widgets/workspace.ts +0 -328
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// ---------------------------------------------------------------------------
|
|
3
|
-
// notebook-document — collaborative doc layout (deepnote-like)
|
|
4
|
-
// Title + avatars, inline highlights, margin comments, minimal cell chrome.
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
createState, injectStyles, mountRunControls, mountHistoryPanel,
|
|
9
|
-
setupDnD, deleteCellWithConfirm, restoreCellFromSnapshot, addCell,
|
|
10
|
-
autosize, openShareModal, registerHistoryObserver,
|
|
11
|
-
buildServersButton,
|
|
12
|
-
type NotebookState, type NotebookCell,
|
|
13
|
-
} from './shared.js';
|
|
14
|
-
|
|
15
|
-
export async function render(container: HTMLElement, data: Record<string, unknown>): Promise<() => void> {
|
|
16
|
-
injectStyles();
|
|
17
|
-
injectLayoutStyles();
|
|
18
|
-
|
|
19
|
-
const state: NotebookState = createState({
|
|
20
|
-
id: data.id as string,
|
|
21
|
-
title: data.title as string ?? 'Untitled notebook',
|
|
22
|
-
mode: (data.mode as any) ?? 'edit',
|
|
23
|
-
cells: data.cells as any,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
container.classList.add('nb-root');
|
|
27
|
-
container.classList.toggle('nb-view-mode', state.mode === 'view');
|
|
28
|
-
|
|
29
|
-
container.innerHTML = `
|
|
30
|
-
<div class="nbd-shell">
|
|
31
|
-
<div class="nbd-presence">
|
|
32
|
-
<div class="nbd-avatars">
|
|
33
|
-
<div class="nbd-av nbd-av1">A</div>
|
|
34
|
-
<div class="nbd-av nbd-av2">B</div>
|
|
35
|
-
<div class="nbd-av nbd-av3">+1</div>
|
|
36
|
-
</div>
|
|
37
|
-
<span class="nbd-label">3 editors online</span>
|
|
38
|
-
<div class="nb-mode-switch" style="margin-left:auto;">
|
|
39
|
-
<button class="nb-mode-edit nb-on">edit</button>
|
|
40
|
-
<button class="nb-mode-view">view</button>
|
|
41
|
-
</div>
|
|
42
|
-
<button class="nb-btn nbd-history-btn">⟲ history</button>
|
|
43
|
-
<span class="nbd-servers-slot"></span>
|
|
44
|
-
</div>
|
|
45
|
-
<input class="nbd-title nb-doc-title" value="${escapeAttr(state.title)}">
|
|
46
|
-
<div class="nbd-meta">edited just now · saved ✓</div>
|
|
47
|
-
<div class="nb-history-panel nbd-history-panel"></div>
|
|
48
|
-
<div class="nbd-cells"></div>
|
|
49
|
-
<div class="nbd-footer">
|
|
50
|
-
<button class="nb-btn nb-add-cell" data-add="md">+ text</button>
|
|
51
|
-
<button class="nb-btn nb-add-cell" data-add="sql">+ sql</button>
|
|
52
|
-
<button class="nb-btn nb-add-cell" data-add="js">+ code</button>
|
|
53
|
-
<div class="nbd-spacer">
|
|
54
|
-
<span class="nbd-share-link nbd-share-btn">invite · share</span>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</div>`;
|
|
58
|
-
|
|
59
|
-
const shell = container.querySelector('.nbd-shell') as HTMLElement;
|
|
60
|
-
const cellsEl = shell.querySelector('.nbd-cells') as HTMLElement;
|
|
61
|
-
const historyPanel = shell.querySelector('.nbd-history-panel') as HTMLElement;
|
|
62
|
-
|
|
63
|
-
function renderCells() {
|
|
64
|
-
cellsEl.innerHTML = '';
|
|
65
|
-
state.cells.forEach((cell) => cellsEl.appendChild(renderCell(cell, state, rerender)));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function rerender() {
|
|
69
|
-
mountHistoryPanel(historyPanel, state, (snap) => { restoreCellFromSnapshot(state, snap); rerender(); });
|
|
70
|
-
renderCells();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
shell.querySelectorAll<HTMLElement>('[data-add]').forEach((btn) => {
|
|
74
|
-
btn.addEventListener('click', () => {
|
|
75
|
-
const type = btn.dataset.add as any;
|
|
76
|
-
addCell(state, type);
|
|
77
|
-
rerender();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
(shell.querySelector('.nbd-history-btn') as HTMLElement).addEventListener('click', () => {
|
|
81
|
-
historyPanel.classList.toggle('nb-open');
|
|
82
|
-
});
|
|
83
|
-
(shell.querySelector('.nbd-share-btn') as HTMLElement).addEventListener('click', () => {
|
|
84
|
-
openShareModal(state, (fmt) => console.log('[notebook-document] share as', fmt, state));
|
|
85
|
-
});
|
|
86
|
-
(shell.querySelector('.nbd-title') as HTMLInputElement).addEventListener('input', (e) => {
|
|
87
|
-
state.title = (e.target as HTMLInputElement).value;
|
|
88
|
-
});
|
|
89
|
-
const editBtn = shell.querySelector('.nb-mode-edit') as HTMLElement;
|
|
90
|
-
const viewBtn = shell.querySelector('.nb-mode-view') as HTMLElement;
|
|
91
|
-
editBtn.addEventListener('click', () => {
|
|
92
|
-
state.mode = 'edit';
|
|
93
|
-
container.classList.remove('nb-view-mode');
|
|
94
|
-
editBtn.classList.add('nb-on'); viewBtn.classList.remove('nb-on');
|
|
95
|
-
});
|
|
96
|
-
viewBtn.addEventListener('click', () => {
|
|
97
|
-
state.mode = 'view';
|
|
98
|
-
container.classList.add('nb-view-mode');
|
|
99
|
-
viewBtn.classList.add('nb-on'); editBtn.classList.remove('nb-on');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
buildServersButton(state, shell.querySelector('.nbd-servers-slot') as HTMLElement, data, rerender);
|
|
103
|
-
|
|
104
|
-
setupDnD(cellsEl, state, rerender);
|
|
105
|
-
const unsubHistory = registerHistoryObserver(() => mountHistoryPanel(historyPanel, state, (snap) => { restoreCellFromSnapshot(state, snap); rerender(); }));
|
|
106
|
-
|
|
107
|
-
rerender();
|
|
108
|
-
return () => { unsubHistory(); };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function renderCell(cell: NotebookCell, state: NotebookState, rerender: () => void): HTMLElement {
|
|
112
|
-
const wrap = document.createElement('div');
|
|
113
|
-
wrap.className = 'nb-cell-wrapper nbd-cell';
|
|
114
|
-
wrap.dataset.id = cell.id;
|
|
115
|
-
|
|
116
|
-
if (cell.type === 'md') {
|
|
117
|
-
const handle = document.createElement('span');
|
|
118
|
-
handle.className = 'nb-drag-handle nbd-md-handle';
|
|
119
|
-
handle.draggable = true;
|
|
120
|
-
handle.textContent = '⋮⋮';
|
|
121
|
-
wrap.appendChild(handle);
|
|
122
|
-
|
|
123
|
-
const p = document.createElement('div');
|
|
124
|
-
p.className = 'nbd-prose';
|
|
125
|
-
p.contentEditable = 'true';
|
|
126
|
-
p.innerHTML = cell.content;
|
|
127
|
-
p.addEventListener('input', () => { cell.content = p.innerHTML; });
|
|
128
|
-
wrap.appendChild(p);
|
|
129
|
-
|
|
130
|
-
const del = document.createElement('button');
|
|
131
|
-
del.className = 'nb-icon-btn nb-danger nbd-del-abs';
|
|
132
|
-
del.textContent = '✕';
|
|
133
|
-
del.addEventListener('click', () =>
|
|
134
|
-
deleteCellWithConfirm(state, cell, () => 'markdown block', rerender)
|
|
135
|
-
);
|
|
136
|
-
wrap.appendChild(del);
|
|
137
|
-
return wrap;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const row = document.createElement('div');
|
|
141
|
-
row.className = 'nbd-row' + (cell.comment ? '' : ' nbd-no-comment');
|
|
142
|
-
|
|
143
|
-
const codeCell = document.createElement('div');
|
|
144
|
-
codeCell.className = 'nb-code-cell nbd-code-cell';
|
|
145
|
-
|
|
146
|
-
const head = document.createElement('div');
|
|
147
|
-
head.className = 'nbd-cell-head';
|
|
148
|
-
head.innerHTML = `
|
|
149
|
-
<span class="nb-drag-handle" draggable="true" title="drag">⋮⋮</span>
|
|
150
|
-
<span class="nbd-run-controls"></span>
|
|
151
|
-
<span class="${cell.type === 'sql' ? 'nbd-type-sql' : 'nbd-type-js'}">${cell.type}</span>
|
|
152
|
-
<span class="nbd-meta-info">${cell.lastMs != null ? cell.lastMs + 'ms' : ''}</span>
|
|
153
|
-
<div class="nbd-actions">
|
|
154
|
-
<button class="nb-icon-btn nb-toggle-src">${cell.hideSource ? '▸ src' : '◂ src'}</button>
|
|
155
|
-
<button class="nb-icon-btn nb-toggle-res">${cell.hideResult ? '▸ res' : '◂ res'}</button>
|
|
156
|
-
<button class="nb-icon-btn nb-danger nbd-del">✕</button>
|
|
157
|
-
</div>`;
|
|
158
|
-
codeCell.appendChild(head);
|
|
159
|
-
mountRunControls(head.querySelector('.nbd-run-controls') as HTMLElement, cell, wrap, rerender);
|
|
160
|
-
|
|
161
|
-
const body = document.createElement('div');
|
|
162
|
-
body.className = 'nbd-code-body' + (cell.hideSource ? ' nbd-hidden' : '');
|
|
163
|
-
const ta = document.createElement('textarea');
|
|
164
|
-
ta.className = 'nb-code-edit';
|
|
165
|
-
ta.value = cell.content;
|
|
166
|
-
ta.rows = 1;
|
|
167
|
-
ta.spellcheck = false;
|
|
168
|
-
ta.addEventListener('input', () => { cell.content = ta.value; autosize(ta); cell.status = 'stale'; });
|
|
169
|
-
body.appendChild(ta);
|
|
170
|
-
codeCell.appendChild(body);
|
|
171
|
-
setTimeout(() => autosize(ta), 0);
|
|
172
|
-
|
|
173
|
-
if (cell.type === 'sql' && !cell.hideResult) {
|
|
174
|
-
const res = document.createElement('div');
|
|
175
|
-
res.className = 'nbd-result-inline';
|
|
176
|
-
res.innerHTML = `
|
|
177
|
-
<table>
|
|
178
|
-
<tr><td>row_1</td><td>42</td></tr>
|
|
179
|
-
<tr><td>row_2</td><td>29</td></tr>
|
|
180
|
-
<tr><td>row_3</td><td>22</td></tr>
|
|
181
|
-
<tr><td>row_4</td><td>9</td></tr>
|
|
182
|
-
</table>`;
|
|
183
|
-
codeCell.appendChild(res);
|
|
184
|
-
} else if (cell.type === 'js' && !cell.hideResult) {
|
|
185
|
-
const chart = document.createElement('div');
|
|
186
|
-
chart.className = 'nbd-chart';
|
|
187
|
-
chart.innerHTML = `
|
|
188
|
-
<div class="nbd-bar" style="height:100%"></div>
|
|
189
|
-
<div class="nbd-bar" style="height:68%"></div>
|
|
190
|
-
<div class="nbd-bar" style="height:52%"></div>
|
|
191
|
-
<div class="nbd-bar" style="height:22%"></div>`;
|
|
192
|
-
codeCell.appendChild(chart);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
row.appendChild(codeCell);
|
|
196
|
-
|
|
197
|
-
if (cell.comment) {
|
|
198
|
-
const c = document.createElement('div');
|
|
199
|
-
c.className = 'nbd-comment';
|
|
200
|
-
c.innerHTML = `
|
|
201
|
-
<div class="nbd-comment-who">
|
|
202
|
-
<div class="nbd-av-small">${escapeHtml(cell.comment.who.slice(0, 2).toUpperCase())}</div>
|
|
203
|
-
<span class="nbd-who-name">${escapeHtml(cell.comment.who)}</span>
|
|
204
|
-
<span class="nbd-when">${escapeHtml(cell.comment.when)}</span>
|
|
205
|
-
</div>
|
|
206
|
-
<div class="nbd-comment-body">${escapeHtml(cell.comment.body)}</div>`;
|
|
207
|
-
row.appendChild(c);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
(head.querySelector('.nb-toggle-src') as HTMLElement).addEventListener('click', () => { cell.hideSource = !cell.hideSource; rerender(); });
|
|
211
|
-
(head.querySelector('.nb-toggle-res') as HTMLElement).addEventListener('click', () => { cell.hideResult = !cell.hideResult; rerender(); });
|
|
212
|
-
(head.querySelector('.nbd-del') as HTMLElement).addEventListener('click', () =>
|
|
213
|
-
deleteCellWithConfirm(state, cell, (c) => `${c.type} cell`, rerender)
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
wrap.appendChild(row);
|
|
217
|
-
return wrap;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function escapeHtml(s: string): string {
|
|
221
|
-
return (s ?? '').replace(/[&<>"']/g, (c) => ({ '&':'&','<':'<','>':'>','"':'"',"'":''' }[c]!));
|
|
222
|
-
}
|
|
223
|
-
function escapeAttr(s: string): string {
|
|
224
|
-
return (s ?? '').replace(/"/g, '"');
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function injectLayoutStyles(): void {
|
|
228
|
-
if (document.getElementById('nbd-styles')) return;
|
|
229
|
-
const style = document.createElement('style');
|
|
230
|
-
style.id = 'nbd-styles';
|
|
231
|
-
style.textContent = `
|
|
232
|
-
.nbd-shell {
|
|
233
|
-
background: var(--color-surface);
|
|
234
|
-
border: 1px solid var(--color-border);
|
|
235
|
-
border-radius: 12px;
|
|
236
|
-
padding: 28px 32px;
|
|
237
|
-
}
|
|
238
|
-
.nbd-presence { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
|
|
239
|
-
.nbd-avatars { display: flex; }
|
|
240
|
-
.nbd-av {
|
|
241
|
-
width: 22px; height: 22px; border-radius: 50%;
|
|
242
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
243
|
-
font-size: 9px; font-weight: 600;
|
|
244
|
-
display: flex; align-items: center; justify-content: center;
|
|
245
|
-
border: 2px solid var(--color-surface);
|
|
246
|
-
}
|
|
247
|
-
.nbd-av + .nbd-av { margin-left: -6px; }
|
|
248
|
-
.nbd-av1 { background: rgba(124,109,250,0.25); color: var(--color-accent); }
|
|
249
|
-
.nbd-av2 { background: rgba(62,207,178,0.22); color: var(--color-teal); }
|
|
250
|
-
.nbd-av3 { background: rgba(240,160,80,0.22); color: var(--color-amber); }
|
|
251
|
-
.nbd-label {
|
|
252
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
253
|
-
font-size: 11px; color: var(--color-text2);
|
|
254
|
-
}
|
|
255
|
-
.nbd-title {
|
|
256
|
-
font-family: var(--font-sans, 'Syne', sans-serif);
|
|
257
|
-
font-size: 24px; font-weight: 600;
|
|
258
|
-
letter-spacing: -0.02em; margin: 6px 0 2px;
|
|
259
|
-
background: transparent; border: none; outline: none;
|
|
260
|
-
color: var(--color-text1);
|
|
261
|
-
width: 100%; padding: 2px 4px; border-radius: 3px;
|
|
262
|
-
}
|
|
263
|
-
.nbd-title:focus { background: var(--color-bg); }
|
|
264
|
-
.nbd-meta {
|
|
265
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
266
|
-
font-size: 11px; color: var(--color-text2);
|
|
267
|
-
margin-bottom: 20px;
|
|
268
|
-
}
|
|
269
|
-
.nbd-history-panel { margin-bottom: 12px; }
|
|
270
|
-
|
|
271
|
-
.nbd-cell { position: relative; margin-bottom: 18px; }
|
|
272
|
-
.nbd-prose {
|
|
273
|
-
font-size: 15px; line-height: 1.7;
|
|
274
|
-
color: var(--color-text1);
|
|
275
|
-
outline: none;
|
|
276
|
-
padding: 4px 6px;
|
|
277
|
-
border-radius: 3px;
|
|
278
|
-
border: 1px dashed transparent;
|
|
279
|
-
}
|
|
280
|
-
.nbd-prose:focus { border-color: var(--color-border); background: var(--color-bg); }
|
|
281
|
-
.nbd-prose mark {
|
|
282
|
-
background: rgba(240,160,80,0.18);
|
|
283
|
-
color: var(--color-amber);
|
|
284
|
-
padding: 0 4px; border-radius: 2px;
|
|
285
|
-
}
|
|
286
|
-
.nbd-md-handle { position: absolute; left: -20px; top: 6px; }
|
|
287
|
-
.nbd-del-abs {
|
|
288
|
-
position: absolute; top: 4px; right: 4px;
|
|
289
|
-
opacity: 0; transition: opacity 0.15s;
|
|
290
|
-
}
|
|
291
|
-
.nbd-cell:hover .nbd-del-abs { opacity: 0.5; }
|
|
292
|
-
.nbd-del-abs:hover { opacity: 1 !important; }
|
|
293
|
-
|
|
294
|
-
.nbd-row {
|
|
295
|
-
display: grid;
|
|
296
|
-
grid-template-columns: 1fr 150px;
|
|
297
|
-
gap: 16px; align-items: start;
|
|
298
|
-
}
|
|
299
|
-
.nbd-row.nbd-no-comment { grid-template-columns: 1fr; }
|
|
300
|
-
|
|
301
|
-
.nbd-code-cell {
|
|
302
|
-
border: 1px solid var(--color-border);
|
|
303
|
-
border-radius: 8px; overflow: hidden;
|
|
304
|
-
background: var(--color-bg);
|
|
305
|
-
}
|
|
306
|
-
.nbd-cell-head {
|
|
307
|
-
padding: 7px 12px;
|
|
308
|
-
display: flex; align-items: center; gap: 8px;
|
|
309
|
-
border-bottom: 1px solid var(--color-border);
|
|
310
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
311
|
-
font-size: 10.5px; color: var(--color-text2);
|
|
312
|
-
}
|
|
313
|
-
.nbd-type-sql { color: var(--color-accent); text-transform: uppercase; letter-spacing: 0.08em; font-size: 9.5px; }
|
|
314
|
-
.nbd-type-js { color: var(--color-teal); text-transform: uppercase; letter-spacing: 0.08em; font-size: 9.5px; }
|
|
315
|
-
.nbd-actions { margin-left: auto; display: flex; gap: 6px; }
|
|
316
|
-
.nbd-code-body { padding: 11px 12px; }
|
|
317
|
-
.nbd-hidden { display: none !important; }
|
|
318
|
-
.nbd-result-inline {
|
|
319
|
-
background: var(--color-surface2);
|
|
320
|
-
padding: 10px 12px;
|
|
321
|
-
border-top: 1px solid var(--color-border);
|
|
322
|
-
}
|
|
323
|
-
.nbd-result-inline table { width: 100%; border-collapse: collapse; font-size: 11.5px; font-variant-numeric: tabular-nums; }
|
|
324
|
-
.nbd-result-inline table td { padding: 3px 0; color: var(--color-text1); }
|
|
325
|
-
.nbd-result-inline table td:first-child { color: var(--color-text2); font-variant-numeric: normal; }
|
|
326
|
-
.nbd-result-inline table td:last-child { text-align: right; }
|
|
327
|
-
|
|
328
|
-
.nbd-comment {
|
|
329
|
-
background: rgba(240,160,80,0.08);
|
|
330
|
-
border-left: 2px solid var(--color-amber);
|
|
331
|
-
border-radius: 0 6px 6px 0;
|
|
332
|
-
padding: 10px 12px;
|
|
333
|
-
font-size: 11.5px;
|
|
334
|
-
}
|
|
335
|
-
.nbd-comment-who { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
|
|
336
|
-
.nbd-av-small {
|
|
337
|
-
width: 15px; height: 15px; border-radius: 50%;
|
|
338
|
-
background: rgba(240,160,80,0.25); color: var(--color-amber);
|
|
339
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
340
|
-
font-size: 8px; font-weight: 600;
|
|
341
|
-
display: flex; align-items: center; justify-content: center;
|
|
342
|
-
}
|
|
343
|
-
.nbd-who-name {
|
|
344
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
345
|
-
font-size: 10.5px; color: var(--color-amber); font-weight: 500;
|
|
346
|
-
}
|
|
347
|
-
.nbd-when {
|
|
348
|
-
margin-left: auto;
|
|
349
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
350
|
-
font-size: 10px; color: var(--color-text2);
|
|
351
|
-
}
|
|
352
|
-
.nbd-comment-body { color: var(--color-text1); line-height: 1.5; }
|
|
353
|
-
|
|
354
|
-
.nbd-chart { padding: 16px; display: flex; align-items: flex-end; gap: 10px; height: 95px; }
|
|
355
|
-
.nbd-bar { flex: 1; background: var(--color-accent); border-radius: 2px 2px 0 0; }
|
|
356
|
-
|
|
357
|
-
.nbd-footer {
|
|
358
|
-
display: flex; gap: 8px;
|
|
359
|
-
padding-top: 14px; margin-top: 20px;
|
|
360
|
-
border-top: 1px solid var(--color-border);
|
|
361
|
-
align-items: center;
|
|
362
|
-
}
|
|
363
|
-
.nbd-spacer { margin-left: auto; }
|
|
364
|
-
.nbd-share-link {
|
|
365
|
-
font-family: var(--font-mono, 'IBM Plex Mono', monospace);
|
|
366
|
-
font-size: 11px; color: var(--color-text2);
|
|
367
|
-
cursor: pointer;
|
|
368
|
-
}
|
|
369
|
-
.nbd-share-link:hover { color: var(--color-text1); }
|
|
370
|
-
`;
|
|
371
|
-
document.head.appendChild(style);
|
|
372
|
-
}
|