feat(ext): shared state host — decouple components from popup.ts
Introduce shared/state.ts as a service-locator so popup components (item-detail, item-form, trash, devices, settings, etc.) work in both the popup and vault tab bundles. Both entry points register themselves as the host; components import from shared/state instead of popup.ts. Vault.ts now delegates to the real popup components, removing ~300 lines of placeholder renderers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../popup', async () => {
|
||||
vi.mock('../../../shared/state', async () => {
|
||||
const sendMessage = vi.fn();
|
||||
const escapeHtml = (s: string): string => s.replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]!));
|
||||
return { sendMessage, escapeHtml };
|
||||
return { sendMessage, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderAttachmentsDisclosure, wireAttachmentsDisclosure } from '../attachments-disclosure';
|
||||
import { sendMessage } from '../../popup';
|
||||
import { sendMessage } from '../../../shared/state';
|
||||
import type { AttachmentRef } from '../../../shared/types';
|
||||
|
||||
const REF1: AttachmentRef = { id: 'a1', filename: 'doc.pdf', mime_type: 'application/pdf', size: 12345, created: 1700000000 };
|
||||
|
||||
@@ -12,14 +12,17 @@ globalThis.chrome = {
|
||||
};
|
||||
|
||||
// Mock popup module
|
||||
vi.mock('../../popup', () => ({
|
||||
vi.mock('../../../shared/state', () => ({
|
||||
setState: vi.fn(),
|
||||
sendMessage: vi.fn(),
|
||||
navigate: vi.fn(),
|
||||
escapeHtml: (s: string) => s,
|
||||
popOutToTab: vi.fn(),
|
||||
isInTab: vi.fn(() => false),
|
||||
openVaultTab: vi.fn(),
|
||||
}));
|
||||
|
||||
import { sendMessage, navigate } from '../../popup';
|
||||
import { sendMessage, navigate } from '../../../shared/state';
|
||||
|
||||
describe('devices view', () => {
|
||||
let app: HTMLElement;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { renderFieldHistory, teardown } from '../field-history';
|
||||
|
||||
// Mock popup module
|
||||
vi.mock('../../popup', () => ({
|
||||
vi.mock('../../../shared/state', () => ({
|
||||
getState: vi.fn(() => ({
|
||||
historyItemId: 'item123',
|
||||
selectedItem: { id: 'item123', title: 'Test Item', modified: 1000 },
|
||||
@@ -11,9 +11,12 @@ vi.mock('../../popup', () => ({
|
||||
sendMessage: vi.fn(),
|
||||
navigate: vi.fn(),
|
||||
escapeHtml: (s: string) => s,
|
||||
popOutToTab: vi.fn(),
|
||||
isInTab: vi.fn(() => false),
|
||||
openVaultTab: vi.fn(),
|
||||
}));
|
||||
|
||||
import { sendMessage, navigate } from '../../popup';
|
||||
import { sendMessage, navigate } from '../../../shared/state';
|
||||
|
||||
describe('field-history view', () => {
|
||||
let app: HTMLElement;
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../shared/state', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import {
|
||||
renderRow,
|
||||
renderConcealedRow,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../popup', async () => {
|
||||
vi.mock('../../../shared/state', async () => {
|
||||
const sendMessage = vi.fn();
|
||||
return { sendMessage };
|
||||
return { sendMessage, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { openGeneratorPanel, closeGeneratorPanel, isGeneratorPanelOpen } from '../generator-panel';
|
||||
import { sendMessage } from '../../popup';
|
||||
import { sendMessage } from '../../../shared/state';
|
||||
import type { GeneratorRequest } from '../../../shared/types';
|
||||
|
||||
const DEFAULT_REQ: GeneratorRequest = {
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../shared/state', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderSectionsEditor, generateFieldId, wireSectionsEditor } from '../fields';
|
||||
import type { Section } from '../../../shared/types';
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../shared/state', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderSections } from '../fields';
|
||||
import type { Item } from '../../../shared/types';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../popup', async () => {
|
||||
vi.mock('../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -25,7 +25,7 @@ vi.mock('../../popup', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
vi.mock('../generator-panel', () => ({
|
||||
@@ -34,7 +34,7 @@ vi.mock('../generator-panel', () => ({
|
||||
}));
|
||||
|
||||
import { renderVaultSettings } from '../settings-vault';
|
||||
import { sendMessage } from '../../popup';
|
||||
import { sendMessage } from '../../../shared/state';
|
||||
|
||||
describe('settings-vault', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { renderTrash } from '../trash';
|
||||
|
||||
// Mock popup module
|
||||
vi.mock('../../popup', () => ({
|
||||
vi.mock('../../../shared/state', () => ({
|
||||
getState: vi.fn(() => ({
|
||||
vaultSettings: { trash_retention: { kind: 'days', value: 30 } },
|
||||
})),
|
||||
@@ -10,9 +10,12 @@ vi.mock('../../popup', () => ({
|
||||
sendMessage: vi.fn(),
|
||||
navigate: vi.fn(),
|
||||
escapeHtml: (s: string) => s,
|
||||
popOutToTab: vi.fn(),
|
||||
isInTab: vi.fn(() => false),
|
||||
openVaultTab: vi.fn(),
|
||||
}));
|
||||
|
||||
import { sendMessage, navigate } from '../../popup';
|
||||
import { sendMessage, navigate } from '../../../shared/state';
|
||||
|
||||
describe('trash view', () => {
|
||||
let app: HTMLElement;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/// Image-mime rows lazy-load 16×16 thumbnails via object URLs;
|
||||
/// teardownAttachmentsDisclosure() revokes them on view exit.
|
||||
|
||||
import { sendMessage, escapeHtml } from '../popup';
|
||||
import { sendMessage, escapeHtml } from '../../shared/state';
|
||||
import type { AttachmentRef, VaultSettings } from '../../shared/types';
|
||||
|
||||
export type DisclosureMode = 'edit' | 'view';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Device management view — list devices with revoke actions.
|
||||
|
||||
import { setState, sendMessage, navigate, escapeHtml } from '../popup';
|
||||
import { setState, sendMessage, navigate, escapeHtml } from '../../shared/state';
|
||||
import type { Device } from '../../shared/types';
|
||||
|
||||
function relativeTime(unixSec: number): string {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Field history view — shows password/concealed field history for an item.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml } from '../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml } from '../../shared/state';
|
||||
import type { FieldHistoryView } from '../../shared/types';
|
||||
|
||||
function relativeTime(unixSec: number): string {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/// After mounting, call `wireFieldHandlers(scope)` once to bind reveal +
|
||||
/// copy click handlers on any rendered rows.
|
||||
|
||||
import { escapeHtml } from '../popup';
|
||||
import { escapeHtml } from '../../shared/state';
|
||||
import type { Item, Section, Field, FieldValue } from '../../shared/types';
|
||||
|
||||
export interface RowOpts {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/// between Random + BIP39 knob sets. Action row varies by context:
|
||||
/// fill-field shows cancel+use; configure-defaults shows only save-default.
|
||||
|
||||
import { sendMessage } from '../popup';
|
||||
import { sendMessage } from '../../shared/state';
|
||||
import type { GeneratorRequest, VaultSettings } from '../../shared/types';
|
||||
|
||||
interface UiKnobs {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/// Typed-item detail view dispatcher. Each type's renderDetail lives in
|
||||
/// its own module under ./types/. Document stays "coming soon" until γ.
|
||||
|
||||
import { navigate } from '../popup';
|
||||
import { navigate, getState } from '../../shared/state';
|
||||
import type { Item } from '../../shared/types';
|
||||
import { getState } from '../popup';
|
||||
import * as login from './types/login';
|
||||
import * as secureNote from './types/secure-note';
|
||||
import * as identity from './types/identity';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// Typed-item add/edit form dispatcher. Each type's renderForm lives in
|
||||
/// its own module under ./types/. Document stays "coming soon" until γ.
|
||||
|
||||
import { navigate, getState, setState, escapeHtml, popOutToTab } from '../popup';
|
||||
import { navigate, getState, setState, escapeHtml, popOutToTab } from '../../shared/state';
|
||||
import type { Item, ItemType } from '../../shared/types';
|
||||
|
||||
const TYPE_OPTIONS: Array<{ type: ItemType; icon: string; label: string }> = [
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// type-iconed rows. Clicking a row fetches the full Item and navigates
|
||||
/// to the detail view.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, openVaultTab } from '../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, openVaultTab } from '../../shared/state';
|
||||
import type { ItemId, ItemType, ManifestEntry, Item } from '../../shared/types';
|
||||
|
||||
/// Extract the display hostname from an icon_hint or fallback to the first tag.
|
||||
@@ -148,8 +148,9 @@ async function openItem(id: ItemId): Promise<void> {
|
||||
/// Compute the visible (filtered) entry list from current state.
|
||||
function getFilteredEntries(): Array<[ItemId, ManifestEntry]> {
|
||||
const state = getState();
|
||||
const entries: Array<[ItemId, ManifestEntry]> = state.entries;
|
||||
// Hide trashed items from the main list.
|
||||
let filtered = state.entries.filter(([, e]) => e.trashed_at === undefined || e.trashed_at === null);
|
||||
let filtered = entries.filter(([, e]) => e.trashed_at === undefined || e.trashed_at === null);
|
||||
if (state.searchQuery) {
|
||||
const q = state.searchQuery.toLowerCase();
|
||||
filtered = filtered.filter(([, e]) => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// generator defaults (preview + "configure" → opens popover), and
|
||||
/// autofill origin-ack revocation.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml } from '../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml } from '../../shared/state';
|
||||
import type {
|
||||
VaultSettings, TrashRetention, HistoryRetention, GeneratorRequest,
|
||||
} from '../../shared/types';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Settings view — capture toggle, prompt style, and blacklist management.
|
||||
|
||||
import { sendMessage, navigate, escapeHtml } from '../popup';
|
||||
import { sendMessage, navigate, escapeHtml } from '../../shared/state';
|
||||
import type { DeviceSettings } from '../../shared/types';
|
||||
|
||||
export async function renderSettings(app: HTMLElement): Promise<void> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Trash view — lists soft-deleted items with restore/purge actions.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml } from '../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml } from '../../shared/state';
|
||||
import type { ItemId, ManifestEntry, VaultSettings } from '../../shared/types';
|
||||
|
||||
const TYPE_ICONS: Record<string, string> = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -11,11 +11,11 @@ vi.mock('../../../popup', async () => {
|
||||
}));
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../card';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
|
||||
describe('Card save shape', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -12,11 +12,11 @@ vi.mock('../../../popup', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../document';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
import type { Item, AttachmentRef } from '../../../../shared/types';
|
||||
|
||||
const PRIMARY: AttachmentRef = {
|
||||
@@ -43,7 +43,7 @@ describe('Document form save', () => {
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
expect(alertSpy).not.toHaveBeenCalled();
|
||||
// setState called with the error
|
||||
const { setState } = await import('../../../popup');
|
||||
const { setState } = await import('../../../../shared/state');
|
||||
expect(vi.mocked(setState)).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ error: expect.stringContaining('primary attachment') }),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -12,11 +12,11 @@ vi.mock('../../../popup', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../identity';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
|
||||
describe('Identity save shape', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -11,11 +11,11 @@ vi.mock('../../../popup', async () => {
|
||||
}));
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../key';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
|
||||
describe('Key save shape', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -13,11 +13,11 @@ vi.mock('../../../popup', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../login';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
|
||||
describe('Login form packs sectionsDraft into Item.sections', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -12,11 +12,11 @@ vi.mock('../../../popup', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../secure-note';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
|
||||
describe('SecureNote save shape', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../../popup', async () => {
|
||||
vi.mock('../../../../shared/state', async () => {
|
||||
const navigate = vi.fn();
|
||||
const setState = vi.fn();
|
||||
const sendMessage = vi.fn();
|
||||
@@ -12,11 +12,11 @@ vi.mock('../../../popup', async () => {
|
||||
const escapeHtml = (s: string) => s
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''');
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml };
|
||||
return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
|
||||
});
|
||||
|
||||
import { renderForm } from '../totp';
|
||||
import { sendMessage } from '../../../popup';
|
||||
import { sendMessage } from '../../../../shared/state';
|
||||
import { base32Decode } from '../../../../shared/base32';
|
||||
|
||||
describe('Totp save shape', () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// Card: number / holder / expiry MonthYear / cvv / pin / kind.
|
||||
/// Detail view has a styled card-silhouette signature block.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, ManifestEntry, CardKind, Section, AttachmentRef } from '../../../shared/types';
|
||||
import {
|
||||
renderConcealedRow, renderSignatureBlock, wireFieldHandlers, renderSections,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// notes/tags + optional supplementary attachments.
|
||||
/// Primary attachment is referenced by ID from the item's attachments array.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, ManifestEntry, Section, AttachmentRef } from '../../../shared/types';
|
||||
import {
|
||||
renderSectionsEditor, wireSectionsEditor,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// Identity: full_name, address (multiline), phone, email, date_of_birth.
|
||||
/// Detail view shows a "profile card" signature block + plain rows.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, ManifestEntry, Section, AttachmentRef } from '../../../shared/types';
|
||||
import {
|
||||
renderRow, renderSignatureBlock, wireFieldHandlers, renderSections,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// Form's key_material textarea uses CSS text-security to mask characters
|
||||
/// since <textarea type="password"> isn't a thing.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, ManifestEntry, Section, AttachmentRef } from '../../../shared/types';
|
||||
import {
|
||||
renderRow, renderConcealedRow, renderSignatureBlock, wireFieldHandlers, renderSections,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// Login type detail + form. Reference implementation for the shared
|
||||
/// field helpers introduced in Slice 2.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, LoginCore, ManifestEntry, Section, TotpConfig, AttachmentRef } from '../../../shared/types';
|
||||
import { DEFAULT_PASSWORD_REQUEST } from '../../../shared/types';
|
||||
import { base32Decode, base32Encode } from '../../../shared/base32';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// SecureNote: a single multiline body field. Concealed by default in the
|
||||
/// detail view; the form is just a big <textarea>.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab, isInTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, ManifestEntry, Section, AttachmentRef } from '../../../shared/types';
|
||||
import {
|
||||
renderConcealedRow, renderSignatureBlock, wireFieldHandlers, renderSections,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// signature block with a thin SVG countdown ring; form has a kind toggle
|
||||
/// (TOTP vs Steam Guard) and a single secret input.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, popOutToTab } from '../../../shared/state';
|
||||
import type { Item, ItemId, ManifestEntry, Section, TotpKind, AttachmentRef } from '../../../shared/types';
|
||||
import { base32Decode, base32Encode } from '../../../shared/base32';
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Unlock view — passphrase input with ENTER to submit.
|
||||
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, openVaultTab } from '../popup';
|
||||
import { getState, setState, sendMessage, navigate, escapeHtml, openVaultTab } from '../../shared/state';
|
||||
import type { ItemId, ManifestEntry } from '../../shared/types';
|
||||
|
||||
export function renderUnlock(app: HTMLElement): void {
|
||||
|
||||
Reference in New Issue
Block a user