obsidian-formfire/src/ui/form-sidebar.ts
tolvitty 5eb79fbf08 feat: add sidebar view with form list
ItemView that displays all forms with mode badges (C/U), click to open,
settings gear button, and empty state. Uses SidebarPluginRef interface
to avoid circular dependency with main.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:22:11 +01:00

94 lines
2.4 KiB
TypeScript

import { ItemView, WorkspaceLeaf, setIcon } from 'obsidian';
import { FormStore } from '../core/form-store';
export const VIEW_TYPE_FORMFIRE_SIDEBAR = 'formfire-sidebar';
/**
* Interface for the subset of FormfirePlugin that the sidebar needs.
* Avoids circular dependency with main.ts.
*/
export interface SidebarPluginRef {
store: FormStore;
openForm: (id: string) => void;
}
export class FormfireSidebarView extends ItemView {
private pluginRef: SidebarPluginRef;
constructor(leaf: WorkspaceLeaf, pluginRef: SidebarPluginRef) {
super(leaf);
this.pluginRef = pluginRef;
}
getViewType(): string {
return VIEW_TYPE_FORMFIRE_SIDEBAR;
}
getDisplayText(): string {
return 'Formfire';
}
getIcon(): string {
return 'file-input';
}
async onOpen(): Promise<void> {
this.render();
}
async onClose(): Promise<void> {
this.contentEl.empty();
}
public render(): void {
const { contentEl } = this;
contentEl.empty();
const container = contentEl.createDiv({ cls: 'ff-sidebar' });
// Header
const header = container.createDiv({ cls: 'ff-sidebar-header' });
header.createSpan({ text: 'Forms', cls: 'ff-sidebar-title' });
const settingsBtn = header.createDiv({ cls: 'ff-sidebar-settings' });
setIcon(settingsBtn, 'settings');
settingsBtn.setAttribute('aria-label', 'Formfire settings');
settingsBtn.addEventListener('click', () => {
// Open Obsidian settings and navigate to the Formfire tab
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const appAny = this.app as any;
appAny.setting.open();
appAny.setting.openTabById('formfire');
});
// Form list
const forms = this.pluginRef.store.getAll();
if (forms.length === 0) {
container.createDiv({
cls: 'ff-sidebar-empty',
text: 'No forms yet. Open settings to create one.',
});
return;
}
const listEl = container.createDiv({ cls: 'ff-sidebar-list' });
for (const form of forms) {
const item = listEl.createDiv({ cls: 'ff-sidebar-item' });
const badgeCls =
form.mode === 'create' ? 'ff-badge-create' : 'ff-badge-update';
item.createSpan({
cls: `ff-sidebar-badge ${badgeCls}`,
text: form.mode === 'create' ? 'C' : 'U',
});
item.createSpan({ cls: 'ff-sidebar-name', text: form.name });
item.addEventListener('click', () => {
this.pluginRef.openForm(form.id);
});
}
}
}