diff --git a/src/public/app/services/keyboard_actions.ts b/src/public/app/services/keyboard_actions.ts index 630ec03a9..bf5403706 100644 --- a/src/public/app/services/keyboard_actions.ts +++ b/src/public/app/services/keyboard_actions.ts @@ -6,7 +6,7 @@ import Component from "../components/component.js"; const keyboardActionRepo: Record = {}; // TODO: Deduplicate with server. -interface Action { +export interface Action { actionName: CommandNames; effectiveShortcuts: string[]; scope: string; diff --git a/src/public/app/widgets/buttons/abstract_button.ts b/src/public/app/widgets/buttons/abstract_button.ts index 3d6c49743..9b26c392e 100644 --- a/src/public/app/widgets/buttons/abstract_button.ts +++ b/src/public/app/widgets/buttons/abstract_button.ts @@ -5,36 +5,25 @@ const TPL = ``; type TitlePlacement = "top" | "bottom" | "left" | "right"; -type StringOrCallback = (() => string); +type StringOrCallback = string | (() => string); type ContextMenuHandler = (e: JQuery.ContextMenuEvent | null) => void; -interface Settings { +export interface AbstractButtonWidgetSettings { titlePlacement: TitlePlacement; - title: string | StringOrCallback | null; - icon: string | StringOrCallback | null; + title: StringOrCallback | null; + icon: StringOrCallback | null; onContextMenu: ContextMenuHandler | null; } -export default class AbstractButtonWidget extends NoteContextAwareWidget { +export default class AbstractButtonWidget extends NoteContextAwareWidget { - private settings: Settings; - private tooltip!: bootstrap.Tooltip; + protected settings!: SettingsT; + protected tooltip!: bootstrap.Tooltip; isEnabled() { return true; } - constructor() { - super(); - - this.settings = { - titlePlacement: 'right', - title: null, - icon: null, - onContextMenu: null - }; - } - doRender() { this.$widget = $(TPL); // Fix once bootstrap is available as non-UMD diff --git a/src/public/app/widgets/buttons/command_button.js b/src/public/app/widgets/buttons/command_button.ts similarity index 51% rename from src/public/app/widgets/buttons/command_button.js rename to src/public/app/widgets/buttons/command_button.ts index 2c28bd21b..affe737c1 100644 --- a/src/public/app/widgets/buttons/command_button.js +++ b/src/public/app/widgets/buttons/command_button.ts @@ -1,11 +1,32 @@ -import keyboardActionsService from "../../services/keyboard_actions.js"; -import AbstractButtonWidget from "./abstract_button.js"; +import { CommandNames } from "../../components/app_context.js"; +import keyboardActionsService, { Action } from "../../services/keyboard_actions.js"; +import AbstractButtonWidget, { AbstractButtonWidgetSettings } from "./abstract_button.js"; -let actions; +let actions: Action[]; keyboardActionsService.getActions().then(as => actions = as); -export default class CommandButtonWidget extends AbstractButtonWidget { +// TODO: Is this actually used? +export type ClickHandler = (widget: CommandButtonWidget, e: JQuery.ClickEvent) => void; +type CommandOrCallback = (CommandNames | (() => CommandNames)); + +interface CommandButtonWidgetSettings extends AbstractButtonWidgetSettings { + command?: CommandOrCallback; + onClick?: ClickHandler; +} + +export default class CommandButtonWidget extends AbstractButtonWidget { + + constructor() { + super(); + this.settings = { + titlePlacement: 'right', + title: null, + icon: null, + onContextMenu: null + }; + } + doRender() { super.doRender(); @@ -13,7 +34,9 @@ export default class CommandButtonWidget extends AbstractButtonWidget { this.$widget.on("click", () => { this.tooltip.hide(); - this.triggerCommand(this._command); + if (this._command) { + this.triggerCommand(this._command); + } }); } else { console.warn(`Button widget '${this.componentId}' has no defined command`, this.settings); @@ -32,16 +55,12 @@ export default class CommandButtonWidget extends AbstractButtonWidget { } } - onClick(handler) { + onClick(handler: ClickHandler) { this.settings.onClick = handler; return this; } - /** - * @param {function|string} command - * @returns {this} - */ - command(command) { + command(command: CommandOrCallback) { this.settings.command = command; return this; } diff --git a/src/public/app/widgets/buttons/onclick_button.js b/src/public/app/widgets/buttons/onclick_button.js deleted file mode 100644 index c20e3d884..000000000 --- a/src/public/app/widgets/buttons/onclick_button.js +++ /dev/null @@ -1,36 +0,0 @@ -import AbstractButtonWidget from "./abstract_button.js"; -import { t } from "../../services/i18n.js"; - -export default class OnClickButtonWidget extends AbstractButtonWidget { - doRender() { - super.doRender(); - - if (this.settings.onClick) { - this.$widget.on("click", e => { - this.$widget.tooltip("hide"); - - this.settings.onClick(this, e); - }); - } else { - console.warn(t("onclick_button.no_click_handler", { componentId: this.componentId }), this.settings); - } - - if (this.settings.onAuxClick) { - this.$widget.on("auxclick", e => { - this.$widget.tooltip("hide"); - - this.settings.onAuxClick(this, e); - }); - } - } - - onClick(handler) { - this.settings.onClick = handler; - return this; - } - - onAuxClick(handler) { - this.settings.onAuxClick = handler; - return this; - } -} diff --git a/src/public/app/widgets/buttons/onclick_button.ts b/src/public/app/widgets/buttons/onclick_button.ts new file mode 100644 index 000000000..62c448812 --- /dev/null +++ b/src/public/app/widgets/buttons/onclick_button.ts @@ -0,0 +1,59 @@ +import AbstractButtonWidget, { AbstractButtonWidgetSettings, type AuxClickHandler, type ClickHandler } from "./abstract_button.js"; +import { t } from "../../services/i18n.js"; + +export type ClickHandler = (widget: OnClickButtonWidget, e: JQuery.ClickEvent) => void; +export type AuxClickHandler = (widget: OnClickButtonWidget, e: JQuery.TriggeredEvent) => void; + +interface OnClickButtonWidgetSettings extends AbstractButtonWidgetSettings { + onClick?: ClickHandler; + onAuxClick?: AuxClickHandler; +} + +export default class OnClickButtonWidget extends AbstractButtonWidget { + + constructor() { + super(); + this.settings = { + titlePlacement: 'right', + title: null, + icon: null, + onContextMenu: null + }; + } + + doRender() { + super.doRender(); + + if (this.settings.onClick) { + this.$widget.on("click", e => { + this.$widget.tooltip("hide"); + + if (this.settings.onClick) { + this.settings.onClick(this, e); + } + }); + } else { + console.warn(t("onclick_button.no_click_handler", { componentId: this.componentId }), this.settings); + } + + if (this.settings.onAuxClick) { + this.$widget.on("auxclick", e => { + this.$widget.tooltip("hide"); + + if (this.settings.onAuxClick) { + this.settings.onAuxClick(this, e); + } + }); + } + } + + onClick(handler: ClickHandler) { + this.settings.onClick = handler; + return this; + } + + onAuxClick(handler: AuxClickHandler) { + this.settings.onAuxClick = handler; + return this; + } +} diff --git a/src/public/app/widgets/right_panel_widget.ts b/src/public/app/widgets/right_panel_widget.ts index ff9498cbf..0f2d11377 100644 --- a/src/public/app/widgets/right_panel_widget.ts +++ b/src/public/app/widgets/right_panel_widget.ts @@ -1,4 +1,5 @@ import BasicWidget from "./basic_widget.js"; +import AbstractButtonWidget from "./buttons/abstract_button.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; const WIDGET_TPL = ` @@ -26,7 +27,7 @@ class RightPanelWidget extends NoteContextAwareWidget { /** Title to show in the panel. */ get widgetTitle() { return "Untitled widget"; } - get widgetButtons() { return []; } + get widgetButtons(): AbstractButtonWidget[] { return []; } get help() { return {}; }