129 lines
3.1 KiB
TypeScript
Raw Normal View History

/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
/**
* @module admonition/admonitionui
*/
import { Plugin, addListToDropdown, createDropdown, ListDropdownItemDefinition, SplitButtonView, ViewModel } from 'ckeditor5';
import '../theme/blockquote.css';
2025-03-13 19:10:07 +02:00
import admonitionIcon from '../theme/icons/admonition.svg';
import { AdmonitionType } from './admonitioncommand.js';
import { Collection } from 'ckeditor5';
2025-03-13 20:07:55 +02:00
interface AdmonitionDefinition {
title: string;
}
export const ADMONITION_TYPES: Record<AdmonitionType, AdmonitionDefinition> = {
note: {
2025-03-13 20:07:55 +02:00
title: "Note"
},
tip: {
2025-03-13 20:07:55 +02:00
title: "Tip"
},
important: {
2025-03-13 20:07:55 +02:00
title: "Important"
},
caution: {
2025-03-13 20:07:55 +02:00
title: "Caution"
},
warning: {
2025-03-13 20:07:55 +02:00
title: "Warning"
}
};
/**
* The block quote UI plugin.
*
* It introduces the `'admonition'` button.
*
* @extends module:core/plugin~Plugin
*/
2025-03-13 18:33:39 +02:00
export default class AdmonitionUI extends Plugin {
/**
* @inheritDoc
*/
public static get pluginName() {
return 'AdmonitionUI' as const;
}
/**
* @inheritDoc
*/
public init(): void {
const editor = this.editor;
editor.ui.componentFactory.add( 'admonition', () => {
2025-03-13 20:07:55 +02:00
const buttonView = this._createButton();
return buttonView;
} );
}
/**
* Creates a button for admonition command to use either in toolbar or in menu bar.
*/
2025-03-13 20:07:55 +02:00
private _createButton() {
const editor = this.editor;
const locale = editor.locale;
const command = editor.commands.get( 'admonition' )!;
const dropdownView = createDropdown(locale, SplitButtonView);
const splitButtonView = dropdownView.buttonView;
const t = locale.t;
addListToDropdown(dropdownView, this._getDropdownItems())
2025-03-13 20:07:55 +02:00
// Button configuration.
splitButtonView.set( {
label: t( 'Admonition' ),
2025-03-13 19:10:07 +02:00
icon: admonitionIcon,
2025-03-13 20:07:55 +02:00
isToggleable: true,
tooltip: true
} );
splitButtonView.on("execute", () => {
editor.execute("admonition", { usePreviousChoice: true });
editor.editing.view.focus();
});
splitButtonView.bind( 'isOn' ).to( command, 'value', value => (!!value) as boolean);
// Dropdown configuration
dropdownView.bind( 'isEnabled' ).to( command, 'isEnabled' );
dropdownView.on("execute", evt => {
editor.execute("admonition", { forceValue: ( evt.source as any ).commandParam } );
editor.editing.view.focus();
});
return dropdownView;
}
2025-03-13 20:07:55 +02:00
private _getDropdownItems() {
const itemDefinitions = new Collection<ListDropdownItemDefinition>();
const command = this.editor.commands.get("admonition");
if (!command) {
return itemDefinitions;
}
2025-03-13 20:07:55 +02:00
for (const [ type, admonition ] of Object.entries(ADMONITION_TYPES)) {
const definition: ListDropdownItemDefinition = {
2025-03-13 20:07:55 +02:00
type: "button",
model: new ViewModel({
commandParam: type,
label: admonition.title,
class: `ck-tn-admonition-option ck-tn-admonition-${type}`,
role: 'menuitemradio',
2025-03-13 20:07:55 +02:00
withText: true
})
}
definition.model.bind("isOn").to(command, "value", currentType => currentType === type);
2025-03-13 20:07:55 +02:00
itemDefinitions.add(definition);
}
return itemDefinitions;
}
}