Anki/ts/editor-toolbar/index.ts

139 lines
4.5 KiB
TypeScript

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { ToolbarItem, IterableToolbarItem } from "./types";
import type { Identifier } from "./identifiable";
import { writable } from "svelte/store";
import EditorToolbarSvelte from "./EditorToolbar.svelte";
import "./bootstrap.css";
import { add, insert, updateRecursive } from "./identifiable";
import { showComponent, hideComponent, toggleComponent } from "./hideable";
export interface EditorToolbarAPI {
// Button API
updateButton(
update: (component: ToolbarItem) => ToolbarItem,
...identifiers: Identifier[]
): void;
showButton(...identifiers: Identifier[]): void;
hideButton(...identifiers: Identifier[]): void;
toggleButton(...identifiers: Identifier[]): void;
insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void;
addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void;
// Menu API
updateMenu(
update: (component: ToolbarItem) => ToolbarItem,
...identifiers: Identifier[]
): void;
addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void;
}
export function editorToolbar(
target: HTMLElement,
initialButtons: IterableToolbarItem[] = [],
initialMenus: ToolbarItem[] = []
): EditorToolbarAPI {
const buttons = writable(initialButtons);
const menus = writable(initialMenus);
new EditorToolbarSvelte({
target,
props: {
buttons,
menus,
nightMode: document.documentElement.classList.contains("night-mode"),
},
});
function updateButton(
update: (component: ToolbarItem) => ToolbarItem,
...identifiers: Identifier[]
): void {
buttons.update(
(items: IterableToolbarItem[]): IterableToolbarItem[] =>
updateRecursive(
update,
({ items } as unknown) as ToolbarItem,
...identifiers
).items as IterableToolbarItem[]
);
}
function showButton(...identifiers: Identifier[]): void {
updateButton(showComponent, ...identifiers);
}
function hideButton(...identifiers: Identifier[]): void {
updateButton(hideComponent, ...identifiers);
}
function toggleButton(...identifiers: Identifier[]): void {
updateButton(toggleComponent, ...identifiers);
}
function insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void {
const initIdentifiers = identifiers.slice(0, -1);
const lastIdentifier = identifiers[identifiers.length - 1];
updateButton(
(component: ToolbarItem) =>
insert(component as IterableToolbarItem, newButton, lastIdentifier),
...initIdentifiers
);
}
function addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void {
const initIdentifiers = identifiers.slice(0, -1);
const lastIdentifier = identifiers[identifiers.length - 1];
updateButton(
(component: ToolbarItem) =>
add(component as IterableToolbarItem, newButton, lastIdentifier),
...initIdentifiers
);
}
function updateMenu(
update: (component: ToolbarItem) => ToolbarItem,
...identifiers: Identifier[]
): void {
menus.update(
(items: ToolbarItem[]): ToolbarItem[] =>
updateRecursive(
update,
({ items } as unknown) as ToolbarItem,
...identifiers
).items as ToolbarItem[]
);
}
function addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void {
const initIdentifiers = identifiers.slice(0, -1);
const lastIdentifier = identifiers[identifiers.length - 1];
updateMenu(
(component: ToolbarItem) =>
add(component as IterableToolbarItem, newMenu, lastIdentifier),
...initIdentifiers
);
}
return {
updateButton,
showButton,
hideButton,
toggleButton,
insertButton,
addButton,
updateMenu,
addMenu,
};
}
/* Exports for editor */
// @ts-expect-error insufficient typing of svelte modules
export { updateActiveButtons, clearActiveButtons } from "./CommandIconButton.svelte";
// @ts-expect-error insufficient typing of svelte modules
export { enableButtons, disableButtons } from "./EditorToolbar.svelte";