UNPKG

@ckeditor/ckeditor5-table

Version:

Table feature for CKEditor 5.

190 lines (189 loc) • 7.36 kB
/** * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options */ /** * @module table/tablelayout/tablelayoutui */ import { Plugin } from 'ckeditor5/src/core.js'; import { IconTableLayout, IconTableProperties } from 'ckeditor5/src/icons.js'; import { createDropdown, addListToDropdown, MenuBarMenuView, SplitButtonView, DropdownButtonView, ViewModel } from 'ckeditor5/src/ui.js'; import { Collection } from 'ckeditor5/src/utils.js'; import InsertTableView from '../ui/inserttableview.js'; /** * The table layout UI plugin. It introduces: * * * The `'insertTableLayout'` dropdown, * * The `'menuBar:insertTableLayout'` menu bar menu. */ export default class TableLayoutUI extends Plugin { /** * @inheritDoc */ static get pluginName() { return 'TableLayoutUI'; } /** * @inheritDoc */ static get isOfficialPlugin() { return true; } /** * @inheritDoc */ init() { const editor = this.editor; const t = this.editor.t; editor.ui.componentFactory.add('insertTableLayout', locale => { const command = editor.commands.get('insertTableLayout'); const dropdownView = createDropdown(locale); dropdownView.bind('isEnabled').to(command); // Decorate dropdown's button. dropdownView.buttonView.set({ icon: IconTableLayout, label: t('Insert table layout'), tooltip: true }); let insertTableLayoutView; dropdownView.on('change:isOpen', () => { if (insertTableLayoutView) { return; } // Prepare custom view for dropdown's panel. insertTableLayoutView = new InsertTableView(locale); dropdownView.panelView.children.add(insertTableLayoutView); insertTableLayoutView.delegate('execute').to(dropdownView); dropdownView.on('execute', () => { editor.execute('insertTableLayout', { rows: insertTableLayoutView.rows, columns: insertTableLayoutView.columns }); editor.editing.view.focus(); }); }); return dropdownView; }); editor.ui.componentFactory.add('menuBar:insertTableLayout', locale => { const command = editor.commands.get('insertTableLayout'); const menuView = new MenuBarMenuView(locale); const insertTableLayoutView = new InsertTableView(locale); insertTableLayoutView.delegate('execute').to(menuView); menuView.on('change:isOpen', (event, name, isOpen) => { if (!isOpen) { insertTableLayoutView.reset(); } }); insertTableLayoutView.on('execute', () => { editor.execute('insertTableLayout', { rows: insertTableLayoutView.rows, columns: insertTableLayoutView.columns }); editor.editing.view.focus(); }); menuView.buttonView.set({ label: t('Table layout'), icon: IconTableLayout }); menuView.panelView.children.add(insertTableLayoutView); menuView.bind('isEnabled').to(command); return menuView; }); // Create table type dropdown button. editor.ui.componentFactory.add('tableType', () => { const editor = this.editor; const t = editor.t; const button = new DropdownButtonView(editor.locale); button.set({ label: t('Table type'), icon: IconTableProperties, tooltip: true }); return createTableTypeDropdown(editor, button); }); } /** * @inheritDoc */ afterInit() { const editor = this.editor; if (!editor.plugins.has('TablePropertiesUI')) { return; } const tablePropertiesUI = editor.plugins.get('TablePropertiesUI'); // Override the default table properties button to include the table type dropdown. // It needs to be done in `afterInit()` to make sure that `tableProperties` button is // registered after the initialization of the `TablePropertiesUI`. Otherwise, the // button will be overridden by the default one if the `TablePropertiesUI` is // initialized after the `TableLayoutUI`. editor.ui.componentFactory.add('tableProperties', locale => { const baseButton = tablePropertiesUI._createTablePropertiesButton(); const splitButtonView = new SplitButtonView(locale, baseButton); return createTableTypeDropdown(editor, splitButtonView); }); } } /** * Creates a dropdown for the table type selection. * * @param editor The editor instance. * @param dropdownButton The button view that will be used as the dropdown trigger. * @returns A dropdown view containing table type options. */ function createTableTypeDropdown(editor, dropdownButton) { const t = editor.t; const locale = editor.locale; const tableTypeCommand = editor.commands.get('tableType'); // Wrap the original button in a SplitButtonView. const dropdownView = createDropdown(locale, dropdownButton); const itemsDefinitions = createTableLayoutTypeDropdownItems(editor); // Add table types to the dropdown. addListToDropdown(dropdownView, itemsDefinitions, { ariaLabel: t('Table type options'), role: 'menu' }); dropdownButton.tooltip = t('Choose table type'); dropdownView.on('execute', evt => { const tableType = evt.source.tableType; if (tableType) { tableTypeCommand.execute(tableType); } }); return dropdownView; } /** * Creates dropdown items for table type selection. * * @param editor The editor instance. * @returns A collection of dropdown items for the table type dropdown. */ function createTableLayoutTypeDropdownItems(editor) { const t = editor.t; const tableTypeCommand = editor.commands.get('tableType'); const itemDefinitions = new Collection(); itemDefinitions.add(createTableTypeDropdownItem(tableTypeCommand, 'layout', t('Layout table'))); itemDefinitions.add(createTableTypeDropdownItem(tableTypeCommand, 'content', t('Content table'))); return itemDefinitions; } /** * Creates a dropdown item for a specific table type. * * @param tableTypeCommand The table type command. * @param type The table type value ('layout' or 'content'). * @param label The localized label for the dropdown item. * @returns The dropdown item definition. */ function createTableTypeDropdownItem(tableTypeCommand, type, label) { const model = new ViewModel({ label, role: 'menuitemradio', withText: true, tableType: type }); model.bind('isEnabled').to(tableTypeCommand, 'isEnabled'); model.bind('isOn').to(tableTypeCommand, 'value', value => value === type); return { type: 'button', model }; }