generated from tpl/obsidian-sample-plugin
			Add svelte modal helper
This commit is contained in:
		
							parent
							
								
									8ebed95fda
								
							
						
					
					
						commit
						6ffad2b5d1
					
				| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
import GoodreadsSearch from "@components/GoodreadsSearch.svelte";
 | 
			
		||||
import { type SearchResult } from "@data-sources/goodreads";
 | 
			
		||||
import { Event, EventEmitter } from "@utils/event";
 | 
			
		||||
import { App, Modal, Notice } from "obsidian";
 | 
			
		||||
import { mount, unmount } from "svelte";
 | 
			
		||||
import { App } from "obsidian";
 | 
			
		||||
import { SvelteModal } from "./svelte-modal";
 | 
			
		||||
 | 
			
		||||
export class SearchEvent extends Event {
 | 
			
		||||
	constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -26,13 +26,10 @@ interface GoodreadsSearchModalEventMap {
 | 
			
		|||
 | 
			
		||||
export class GoodreadsSearchModal extends EventEmitter<
 | 
			
		||||
	GoodreadsSearchModalEventMap,
 | 
			
		||||
	typeof Modal
 | 
			
		||||
>(Modal) {
 | 
			
		||||
	private component: ReturnType<typeof GoodreadsSearch> | undefined;
 | 
			
		||||
 | 
			
		||||
	onOpen() {
 | 
			
		||||
		this.component = mount(GoodreadsSearch, {
 | 
			
		||||
			target: this.contentEl,
 | 
			
		||||
	typeof SvelteModal<typeof GoodreadsSearch>
 | 
			
		||||
>(SvelteModal) {
 | 
			
		||||
	constructor(app: App) {
 | 
			
		||||
		super(app, GoodreadsSearch, {
 | 
			
		||||
			props: {
 | 
			
		||||
				onError: (error: Error) => {
 | 
			
		||||
					this.emit("error", new ErrorEvent(error));
 | 
			
		||||
| 
						 | 
				
			
			@ -44,13 +41,6 @@ export class GoodreadsSearchModal extends EventEmitter<
 | 
			
		|||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onClose() {
 | 
			
		||||
		if (this.component) {
 | 
			
		||||
			unmount(this.component);
 | 
			
		||||
			this.component = undefined;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static createAndOpen(app: App): Promise<SearchResult[]> {
 | 
			
		||||
		return new Promise((resolve, reject) => {
 | 
			
		||||
			const modal = new GoodreadsSearchModal(app);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
import Rating from "@components/Rating.svelte";
 | 
			
		||||
import { Event, EventEmitter } from "@utils/event";
 | 
			
		||||
import { App, Modal } from "obsidian";
 | 
			
		||||
import { mount, unmount } from "svelte";
 | 
			
		||||
import { App } from "obsidian";
 | 
			
		||||
import { SvelteModal } from "./svelte-modal";
 | 
			
		||||
 | 
			
		||||
class SubmitEvent extends Event {
 | 
			
		||||
	constructor(public readonly rating: number) {
 | 
			
		||||
| 
						 | 
				
			
			@ -15,13 +15,10 @@ interface RatingModalEventMap {
 | 
			
		|||
 | 
			
		||||
export class RatingModal extends EventEmitter<
 | 
			
		||||
	RatingModalEventMap,
 | 
			
		||||
	typeof Modal
 | 
			
		||||
>(Modal) {
 | 
			
		||||
	private component: ReturnType<typeof Rating> | undefined;
 | 
			
		||||
 | 
			
		||||
	onOpen(): void {
 | 
			
		||||
		this.component = mount(Rating, {
 | 
			
		||||
			target: this.contentEl,
 | 
			
		||||
	typeof SvelteModal<typeof Rating>
 | 
			
		||||
>(SvelteModal) {
 | 
			
		||||
	constructor(app: App) {
 | 
			
		||||
		super(app, Rating, {
 | 
			
		||||
			props: {
 | 
			
		||||
				onSubmit: (rating: number) =>
 | 
			
		||||
					this.emit("submit", new SubmitEvent(rating)),
 | 
			
		||||
| 
						 | 
				
			
			@ -29,13 +26,6 @@ export class RatingModal extends EventEmitter<
 | 
			
		|||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onClose(): void {
 | 
			
		||||
		if (this.component) {
 | 
			
		||||
			unmount(this.component);
 | 
			
		||||
			this.component = undefined;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static createAndOpen(app: App): Promise<number> {
 | 
			
		||||
		return new Promise((resolve) => {
 | 
			
		||||
			const modal = new RatingModal(app);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
import ReadingLogEntryEditor from "@components/ReadingLogEntryEditor.svelte";
 | 
			
		||||
import type { ReadingLogEntry } from "@src/types";
 | 
			
		||||
import { Event, EventEmitter } from "@utils/event";
 | 
			
		||||
import { App, Modal } from "obsidian";
 | 
			
		||||
import { mount, unmount } from "svelte";
 | 
			
		||||
import { App } from "obsidian";
 | 
			
		||||
import { SvelteModal } from "./svelte-modal";
 | 
			
		||||
 | 
			
		||||
class SubmitEvent extends Event {
 | 
			
		||||
export class SubmitEvent extends Event {
 | 
			
		||||
	constructor(public readonly entry: ReadingLogEntry) {
 | 
			
		||||
		super();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -16,29 +16,15 @@ interface ReadingLogEntryEditModalEventMap {
 | 
			
		|||
 | 
			
		||||
export class ReadingLogEntryEditModal extends EventEmitter<
 | 
			
		||||
	ReadingLogEntryEditModalEventMap,
 | 
			
		||||
	typeof Modal
 | 
			
		||||
>(Modal) {
 | 
			
		||||
	private component: ReturnType<typeof ReadingLogEntryEditor> | undefined;
 | 
			
		||||
 | 
			
		||||
	constructor(app: App, private readonly entry: ReadingLogEntry) {
 | 
			
		||||
		super(app);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onOpen(): void {
 | 
			
		||||
		this.component = mount(ReadingLogEntryEditor, {
 | 
			
		||||
			target: this.contentEl,
 | 
			
		||||
	typeof SvelteModal<typeof ReadingLogEntryEditor>
 | 
			
		||||
>(SvelteModal) {
 | 
			
		||||
	constructor(app: App, entry: ReadingLogEntry) {
 | 
			
		||||
		super(app, ReadingLogEntryEditor, {
 | 
			
		||||
			props: {
 | 
			
		||||
				entry: this.entry,
 | 
			
		||||
				entry,
 | 
			
		||||
				onSubmit: (entry: ReadingLogEntry) =>
 | 
			
		||||
					this.emit("submit", new SubmitEvent(entry)),
 | 
			
		||||
			},
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onClose(): void {
 | 
			
		||||
		if (this.component) {
 | 
			
		||||
			unmount(this.component);
 | 
			
		||||
			this.component = undefined;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
import ReadingProgress from "@components/ReadingProgress.svelte";
 | 
			
		||||
import { Event, EventEmitter } from "@utils/event";
 | 
			
		||||
import { App, Modal } from "obsidian";
 | 
			
		||||
import { mount, unmount } from "svelte";
 | 
			
		||||
import { App } from "obsidian";
 | 
			
		||||
import { SvelteModal } from "./svelte-modal";
 | 
			
		||||
 | 
			
		||||
class SubmitEvent extends Event {
 | 
			
		||||
export class SubmitEvent extends Event {
 | 
			
		||||
	constructor(public readonly pageNumber: number) {
 | 
			
		||||
		super();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -15,19 +15,12 @@ interface ReadingProgressModalEventMap {
 | 
			
		|||
 | 
			
		||||
export class ReadingProgressModal extends EventEmitter<
 | 
			
		||||
	ReadingProgressModalEventMap,
 | 
			
		||||
	typeof Modal
 | 
			
		||||
>(Modal) {
 | 
			
		||||
	private component: ReturnType<typeof ReadingProgress> | undefined;
 | 
			
		||||
 | 
			
		||||
	constructor(app: App, private readonly pageLength: number) {
 | 
			
		||||
		super(app);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onOpen(): void {
 | 
			
		||||
		this.component = mount(ReadingProgress, {
 | 
			
		||||
			target: this.contentEl,
 | 
			
		||||
	typeof SvelteModal<typeof ReadingProgress>
 | 
			
		||||
>(SvelteModal) {
 | 
			
		||||
	constructor(app: App, pageLength: number) {
 | 
			
		||||
		super(app, ReadingProgress, {
 | 
			
		||||
			props: {
 | 
			
		||||
				pageLength: this.pageLength,
 | 
			
		||||
				pageLength,
 | 
			
		||||
				onSubmit: (pageNumber: number) => {
 | 
			
		||||
					this.emit("submit", new SubmitEvent(pageNumber));
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -35,13 +28,6 @@ export class ReadingProgressModal extends EventEmitter<
 | 
			
		|||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onClose(): void {
 | 
			
		||||
		if (this.component) {
 | 
			
		||||
			unmount(this.component);
 | 
			
		||||
			this.component = undefined;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static createAndOpen(app: App, pageLength: number): Promise<number> {
 | 
			
		||||
		return new Promise((resolve) => {
 | 
			
		||||
			const modal = new ReadingProgressModal(app, pageLength);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
import { App, Modal } from "obsidian";
 | 
			
		||||
import { mount, unmount, type Component, type MountOptions } from "svelte";
 | 
			
		||||
 | 
			
		||||
export class SvelteModal<
 | 
			
		||||
	TComponent extends Component<TProps, TExports, TBindings>,
 | 
			
		||||
	TProps extends Record<string, any> = {},
 | 
			
		||||
	TExports extends Record<string, any> = {},
 | 
			
		||||
	TBindings extends keyof TProps | "" = string
 | 
			
		||||
> extends Modal {
 | 
			
		||||
	protected component: TExports | undefined;
 | 
			
		||||
 | 
			
		||||
	constructor(
 | 
			
		||||
		app: App,
 | 
			
		||||
		private readonly componentCtor: TComponent,
 | 
			
		||||
		private readonly mountOpts: Omit<MountOptions<TProps>, "target">
 | 
			
		||||
	) {
 | 
			
		||||
		super(app);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onOpen(): void {
 | 
			
		||||
		this.component = mount(this.componentCtor, {
 | 
			
		||||
			...this.mountOpts,
 | 
			
		||||
			target: this.contentEl,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onClose(): void {
 | 
			
		||||
		if (this.component) {
 | 
			
		||||
			unmount(this.component);
 | 
			
		||||
			this.component = undefined;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue