feat(ext/popup): + New picker with all 7 item types (Document disabled)
This commit is contained in:
@@ -67,7 +67,10 @@ export function renderItemList(app: HTMLElement): void {
|
||||
setState({ searchQuery: searchInput.value, selectedIndex: 0 });
|
||||
});
|
||||
|
||||
document.getElementById('new-btn')?.addEventListener('click', () => navigate('add'));
|
||||
document.getElementById('new-btn')?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
showNewTypePicker(e.currentTarget as HTMLElement);
|
||||
});
|
||||
|
||||
document.getElementById('sync-btn')?.addEventListener('click', async () => {
|
||||
setState({ loading: true, error: null });
|
||||
@@ -215,3 +218,92 @@ function handleListKeydown(e: KeyboardEvent): void {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// New-item type picker popover
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const NEW_TYPE_OPTIONS: Array<{ type: ItemType; icon: string; label: string; disabled?: boolean; tooltip?: string }> = [
|
||||
{ type: 'login', icon: '🔑', label: 'login' },
|
||||
{ type: 'secure_note', icon: '📝', label: 'secure note' },
|
||||
{ type: 'identity', icon: '🪪', label: 'identity' },
|
||||
{ type: 'card', icon: '💳', label: 'card' },
|
||||
{ type: 'key', icon: '🗝', label: 'key' },
|
||||
{ type: 'totp', icon: '⏱', label: 'totp' },
|
||||
{ type: 'document', icon: '📄', label: 'document', disabled: true, tooltip: 'coming in γ — needs attachment upload' },
|
||||
];
|
||||
|
||||
function showNewTypePicker(anchor: HTMLElement): void {
|
||||
document.querySelectorAll('.new-type-picker').forEach((el) => el.remove());
|
||||
|
||||
const picker = document.createElement('div');
|
||||
picker.className = 'new-type-picker';
|
||||
Object.assign(picker.style, {
|
||||
position: 'absolute',
|
||||
background: '#161b22',
|
||||
border: '1px solid #30363d',
|
||||
borderRadius: '6px',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.4)',
|
||||
padding: '4px',
|
||||
minWidth: '160px',
|
||||
zIndex: '999999',
|
||||
fontSize: '12px',
|
||||
});
|
||||
|
||||
const rect = anchor.getBoundingClientRect();
|
||||
picker.style.top = `${rect.bottom + 4}px`;
|
||||
picker.style.left = `${rect.left}px`;
|
||||
|
||||
for (const opt of NEW_TYPE_OPTIONS) {
|
||||
const row = document.createElement('div');
|
||||
Object.assign(row.style, {
|
||||
padding: '6px 10px',
|
||||
cursor: opt.disabled ? 'not-allowed' : 'pointer',
|
||||
color: opt.disabled ? '#484f58' : '#c9d1d9',
|
||||
borderRadius: '4px',
|
||||
display: 'flex', alignItems: 'center', gap: '8px',
|
||||
});
|
||||
if (opt.tooltip) row.title = opt.tooltip;
|
||||
const iconSpan = document.createElement('span');
|
||||
Object.assign(iconSpan.style, { fontSize: '14px', width: '16px', display: 'inline-block', textAlign: 'center' });
|
||||
iconSpan.textContent = opt.icon;
|
||||
const labelSpan = document.createElement('span');
|
||||
labelSpan.textContent = opt.label;
|
||||
row.appendChild(iconSpan);
|
||||
row.appendChild(labelSpan);
|
||||
if (!opt.disabled) {
|
||||
row.addEventListener('mouseenter', () => { row.style.background = '#21262d'; });
|
||||
row.addEventListener('mouseleave', () => { row.style.background = 'transparent'; });
|
||||
row.addEventListener('click', (ev) => {
|
||||
ev.stopPropagation();
|
||||
picker.remove();
|
||||
document.removeEventListener('click', closeOnOutside);
|
||||
document.removeEventListener('keydown', closeOnEsc);
|
||||
setState({ newType: opt.type });
|
||||
navigate('add');
|
||||
});
|
||||
}
|
||||
picker.appendChild(row);
|
||||
}
|
||||
|
||||
document.body.appendChild(picker);
|
||||
|
||||
const closeOnOutside = (ev: MouseEvent) => {
|
||||
if (!picker.contains(ev.target as Node)) {
|
||||
picker.remove();
|
||||
document.removeEventListener('click', closeOnOutside);
|
||||
document.removeEventListener('keydown', closeOnEsc);
|
||||
}
|
||||
};
|
||||
const closeOnEsc = (ev: KeyboardEvent) => {
|
||||
if (ev.key === 'Escape') {
|
||||
picker.remove();
|
||||
document.removeEventListener('click', closeOnOutside);
|
||||
document.removeEventListener('keydown', closeOnEsc);
|
||||
}
|
||||
};
|
||||
setTimeout(() => {
|
||||
document.addEventListener('click', closeOnOutside);
|
||||
document.addEventListener('keydown', closeOnEsc);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user