anki/ts/editor-toolbar/index.ts

222 lines
6.9 KiB
TypeScript
Raw Normal View History

2021-04-15 15:59:52 +02:00
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { SvelteComponentDev } from "svelte/internal";
import type { ToolbarItem } from "./types";
import ButtonGroup from "./ButtonGroup.svelte";
import type { ButtonGroupProps } from "./ButtonGroup";
import { dynamicComponent } from "sveltelib/dynamicComponent";
import { Writable, writable } from "svelte/store";
2021-03-25 21:11:40 +01:00
import EditorToolbarSvelte from "./EditorToolbar.svelte";
2021-04-01 02:26:56 +02:00
import { setupI18n, ModuleName } from "anki/i18n";
2021-04-14 14:37:14 +02:00
import "./bootstrap.css";
import { getNotetypeGroup } from "./notetype";
import { getFormatInlineGroup } from "./formatInline";
import { getFormatBlockGroup, getFormatBlockMenus } from "./formatBlock";
import { getColorGroup } from "./color";
import { getTemplateGroup, getTemplateMenus } from "./template";
import { Identifiable, search, add, insert } from "./identifiable";
interface Hideable {
hidden?: boolean;
}
2021-04-15 02:49:46 +02:00
function showComponent(component: Hideable): void {
component.hidden = false;
}
2021-04-15 02:49:46 +02:00
function hideComponent(component: Hideable): void {
component.hidden = true;
}
2021-04-15 02:49:46 +02:00
function toggleComponent(component: Hideable): void {
component.hidden = !component.hidden;
}
const buttonGroup = dynamicComponent<typeof ButtonGroup, ButtonGroupProps>(ButtonGroup);
let buttonsResolve: (
value: Writable<(ToolbarItem<typeof ButtonGroup> & ButtonGroupProps)[]>
) => void;
let menusResolve: (value: Writable<ToolbarItem[]>) => void;
2021-03-25 21:11:40 +01:00
class EditorToolbar extends HTMLElement {
component?: SvelteComponentDev;
2021-03-25 21:11:40 +01:00
buttonsPromise: Promise<
Writable<(ToolbarItem<typeof ButtonGroup> & ButtonGroupProps)[]>
> = new Promise((resolve) => {
buttonsResolve = resolve;
});
menusPromise: Promise<Writable<ToolbarItem[]>> = new Promise((resolve): void => {
menusResolve = resolve;
});
connectedCallback(): void {
globalThis.$editorToolbar = this;
2021-03-31 22:05:24 +02:00
setupI18n({ modules: [ModuleName.EDITING] }).then(() => {
const buttons = writable([
getNotetypeGroup(),
getFormatInlineGroup(),
getFormatBlockGroup(),
getColorGroup(),
getTemplateGroup(),
]);
const menus = writable([...getTemplateMenus(), ...getFormatBlockMenus()]);
2021-03-31 22:05:24 +02:00
this.component = new EditorToolbarSvelte({
target: this,
props: {
buttons,
menus,
nightMode: document.documentElement.classList.contains(
"night-mode"
),
2021-03-31 22:05:24 +02:00
},
});
buttonsResolve(buttons);
menusResolve(menus);
2021-03-31 22:05:24 +02:00
});
}
updateButtonGroup<T>(
update: (
component: ToolbarItem<typeof ButtonGroup> & ButtonGroupProps & T
) => void,
group: string | number
): void {
this.buttonsPromise.then((buttons) => {
buttons.update((buttonGroups) => {
const foundGroup = search(buttonGroups, group);
if (foundGroup) {
update(
foundGroup as ToolbarItem<typeof ButtonGroup> &
ButtonGroupProps &
T
);
}
return buttonGroups;
});
return buttons;
});
}
showButtonGroup(group: string | number): void {
this.updateButtonGroup<Hideable>(showComponent, group);
}
hideButtonGroup(group: string | number): void {
this.updateButtonGroup<Hideable>(hideComponent, group);
}
toggleButtonGroup(group: string | number): void {
this.updateButtonGroup<Hideable>(toggleComponent, group);
}
2021-04-15 02:49:46 +02:00
insertButtonGroup(newGroup: ButtonGroupProps, group: string | number = 0): void {
this.buttonsPromise.then((buttons) => {
buttons.update((buttonGroups) => {
const newButtonGroup = buttonGroup(newGroup);
return insert(buttonGroups, newButtonGroup, group);
});
return buttons;
});
}
2021-04-15 02:49:46 +02:00
addButtonGroup(newGroup: ButtonGroupProps, group: string | number = -1): void {
this.buttonsPromise.then((buttons) => {
buttons.update((buttonGroups) => {
const newButtonGroup = buttonGroup(newGroup);
return add(buttonGroups, newButtonGroup, group);
});
return buttons;
});
}
updateButton(
update: (component: ToolbarItem) => void,
group: string | number,
button: string | number
): void {
this.updateButtonGroup((foundGroup) => {
const foundButton = search(foundGroup.buttons, button);
if (foundButton) {
update(foundButton);
}
}, group);
}
showButton(group: string | number, button: string | number): void {
this.updateButton(showComponent, group, button);
}
hideButton(group: string | number, button: string | number): void {
this.updateButton(hideComponent, group, button);
}
toggleButton(group: string | number, button: string | number): void {
this.updateButton(toggleComponent, group, button);
}
insertButton(
newButton: ToolbarItem & Identifiable,
group: string | number,
button: string | number = 0
2021-04-15 02:49:46 +02:00
): void {
this.updateButtonGroup((component) => {
component.buttons = insert(
component.buttons as (ToolbarItem & Identifiable)[],
newButton,
button
);
}, group);
}
addButton(
newButton: ToolbarItem & Identifiable,
group: string | number,
button: string | number = -1
2021-04-15 02:49:46 +02:00
): void {
this.updateButtonGroup((component) => {
component.buttons = add(
component.buttons as (ToolbarItem & Identifiable)[],
newButton,
button
);
}, group);
}
2021-03-25 21:11:40 +01:00
}
customElements.define("anki-editor-toolbar", EditorToolbar);
2021-04-01 02:26:56 +02:00
/* Exports for editor/
/* @ts-expect-error */
export { updateActiveButtons, clearActiveButtons } from "./CommandIconButton.svelte";
/* @ts-expect-error */
export { enableButtons, disableButtons } from "./EditorToolbar.svelte";
2021-04-01 02:26:56 +02:00
/* Exports for add-ons */
export { default as RawButton } from "./RawButton.svelte";
2021-04-01 02:26:56 +02:00
export { default as LabelButton } from "./LabelButton.svelte";
export { default as IconButton } from "./IconButton.svelte";
export { default as CommandIconButton } from "./CommandIconButton.svelte";
export { default as SelectButton } from "./SelectButton.svelte";
export { default as DropdownMenu } from "./DropdownMenu.svelte";
export { default as DropdownItem } from "./DropdownItem.svelte";
export { default as ButtonDropdown } from "./DropdownMenu.svelte";
2021-04-01 02:26:56 +02:00
export { default as WithDropdownMenu } from "./WithDropdownMenu.svelte";