ext(affordances): wireNotesMonoToggle with chrome.storage.local persistence
This commit is contained in:
@@ -1449,3 +1449,11 @@ textarea {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: var(--danger, #c75a4f);
|
color: var(--danger, #c75a4f);
|
||||||
}
|
}
|
||||||
|
.notes-with-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.f-notes--mono {
|
||||||
|
font-family: ui-monospace, "JetBrains Mono", "SF Mono", monospace !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||||
|
import { wireNotesMonoToggle } from '../notes-tools';
|
||||||
|
|
||||||
|
describe('wireNotesMonoToggle', () => {
|
||||||
|
let form: HTMLElement;
|
||||||
|
let storage: { get: ReturnType<typeof vi.fn>; set: ReturnType<typeof vi.fn> };
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
form = document.createElement('div');
|
||||||
|
form.innerHTML = `
|
||||||
|
<button id="notes-mono-btn" class="glyph-btn" type="button" title="monospace">≡</button>
|
||||||
|
<textarea id="f-notes"></textarea>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(form);
|
||||||
|
storage = {
|
||||||
|
get: vi.fn().mockImplementation((_keys, cb) => cb({})),
|
||||||
|
set: vi.fn().mockImplementation((_obj, cb) => cb && cb()),
|
||||||
|
};
|
||||||
|
(globalThis as any).chrome = { storage: { local: storage } };
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toggles class on click and persists', async () => {
|
||||||
|
await wireNotesMonoToggle(form, { itemId: 'abc123' });
|
||||||
|
const btn = form.querySelector('#notes-mono-btn') as HTMLButtonElement;
|
||||||
|
const ta = form.querySelector('#f-notes') as HTMLTextAreaElement;
|
||||||
|
expect(ta.classList.contains('f-notes--mono')).toBe(false);
|
||||||
|
btn.click();
|
||||||
|
expect(ta.classList.contains('f-notes--mono')).toBe(true);
|
||||||
|
expect(storage.set).toHaveBeenCalledWith({ 'notesMono.abc123': true }, expect.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('restores prior state on mount', async () => {
|
||||||
|
storage.get.mockImplementation((_keys, cb) => cb({ 'notesMono.abc123': true }));
|
||||||
|
await wireNotesMonoToggle(form, { itemId: 'abc123' });
|
||||||
|
const ta = form.querySelector('#f-notes') as HTMLTextAreaElement;
|
||||||
|
expect(ta.classList.contains('f-notes--mono')).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
23
extension/src/shared/form-affordances/notes-tools.ts
Normal file
23
extension/src/shared/form-affordances/notes-tools.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export interface NotesMonoOpts {
|
||||||
|
/// Item ID for persistence — pass empty string for "add new" forms (state
|
||||||
|
/// is then session-scoped under the key 'notesMono.__new__').
|
||||||
|
itemId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function wireNotesMonoToggle(form: HTMLElement, opts: NotesMonoOpts): Promise<void> {
|
||||||
|
const btn = form.querySelector<HTMLButtonElement>('#notes-mono-btn');
|
||||||
|
const ta = form.querySelector<HTMLTextAreaElement>('#f-notes');
|
||||||
|
if (!btn || !ta) return;
|
||||||
|
|
||||||
|
const key = `notesMono.${opts.itemId || '__new__'}`;
|
||||||
|
const stored = await new Promise<boolean>((resolve) => {
|
||||||
|
chrome.storage.local.get([key], (result) => resolve(!!result[key]));
|
||||||
|
});
|
||||||
|
if (stored) ta.classList.add('f-notes--mono');
|
||||||
|
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const next = !ta.classList.contains('f-notes--mono');
|
||||||
|
ta.classList.toggle('f-notes--mono', next);
|
||||||
|
chrome.storage.local.set({ [key]: next }, () => { /* fire and forget */ });
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1479,3 +1479,11 @@ textarea {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: var(--danger, #c75a4f);
|
color: var(--danger, #c75a4f);
|
||||||
}
|
}
|
||||||
|
.notes-with-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.f-notes--mono {
|
||||||
|
font-family: ui-monospace, "JetBrains Mono", "SF Mono", monospace !important;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user