quill-table-better

repository·main·Indexed 40 days ago

https://github.com/attoae/quill-table-better

An enhancement module for Quill (v2.0.0+) that provides advanced table manipulation capabilities, including multi-cell operations, custom menus, and improved undo/redo support. It includes a specialized API for structural modifications via TableContainer and support for localized UI strings.

Tokens
7.9K
Snippets
21
Records
28
Agent score
50%

What's inside quill-table-better

  1. Quickstart: Initialize quill-table-better in a project

    main

    To use quill-table-better, register the module with Quill, import the necessary CSS, and configure the table-better module within the Quill options.

    Important: When initializing data from HTML, do not use setContents as it causes display issues. Instead, use updateContents as shown in the example below.

    import Quill from 'quill';
    import QuillTableBetter from 'quill-table-better';
    import 'quill/dist/quill.snow.css';
    import 'quill-table-better/dist/quill-table-better.css';
    
    Quill.register({
      'modules/table-better': QuillTableBetter
    }, true);
    
    const toolbarOptions = [
      ['bold', 'italic', 'underline', 'strike'],
      ['table-better']
    ];
    
    const options = {
      theme: 'snow',
      modules: {
        table: false, // Disable standard Quill table module
        toolbar: toolbarOptions,
        'table-better': {
          language: 'en_US',
          menus: ['column', 'row', 'merge', 'table', 'cell', 'wrap', 'copy', 'delete'],
          toolbarTable: true
        },
        keyboard: {
          bindings: QuillTableBetter.keyboardBindings
        }
      }
    };
    
    const quill = new Quill('#root', options);
  2. Initialize data using updateContents

    main

    When loading existing content (e.g., from a database), use updateContents instead of setContents to ensure tables render correctly.

    const delta = quill.clipboard.convert({ html });
    const [range] = quill.selection.getRange();
    quill.updateContents(delta, Quill.sources.USER);
    quill.setSelection(
      delta.length() - (range?.length || 0),
      Quill.sources.SILENT
    );
    quill.scrollSelectionIntoView();
  3. How table resizing and moving works via OperateLine

    main

    The OperateLine class manages the UI interactions for resizing table columns/rows and moving the entire table within the Quill editor. It handles three main interaction modes based on mouse position relative to table cells:

    1. Column Resizing (Level): When the mouse is near the vertical edge of a cell, a vertical line (ql-operate-line-container) appears. Dragging this line adjusts the width of the column.
    2. Row Resizing (Vertical): When the mouse is near the horizontal edge of a cell, a horizontal line appears. Dragging this line adjusts the height of the row.
    3. Table Moving (Drag Block): A small block (ql-operate-block) appears at the bottom-right corner of the table. Dragging this block allows the user to resize or reposition the entire table.

    These interactions use internal logic to calculate new dimensions, supporting both fixed pixel widths and percentage-based widths (via isPercent check).

  4. How TableToolbar handles cell selection vs standard text

    main

    The TableToolbar module implements a dual-mode interaction pattern based on the current selection state:

    1. Cell Selection Mode: If cellSelection.selectedTds.length > 1, the toolbar acts on the entire selected cell range. For <select> elements, it uses cellSelection.getCorrectValue to resolve the value and applies it via cellSelection.setSelectedTdsFormat. For buttons, it applies the format to the selected cells and prevents default browser behavior.

    2. Standard Mode: If no cells are selected, the toolbar behaves like a standard Quill toolbar, applying formats to the current text range using this.quill.format or custom handlers.

    This allows users to format entire table structures (like turning a row into a header) or just format text within a single cell using the same toolbar UI.

  5. Configure the table-better module

    main

    The table-better module can be customized via the following configuration keys:

    • language: A string representing the language code (e.g., en_US, zh_CN, fr_FR). Defaults to en_US.
    • menus: An array of strings or objects defining which action bar items are displayed.
      • Available menu keys: column, row, merge, table, cell, wrap, delete, copy.
      • You can customize icons using objects: { name: 'column', icon: '<span class="icon"></span>' }.
    • toolbarTable: A boolean. If true, adds a button to the Quill toolbar to insert a table. Requires adding ['table-better'] to your toolbarOptions.
    • toolbarButtons: Configures which formatting buttons are enabled when a table cell is focused.
      • whiteList: Formats allowed for simultaneous operations on multiple cells. Defaults to WHITE_LIST.
      • singleWhiteList: Formats allowed for a single cell. Defaults to SINGLE_WHITE_LIST.
      • Note: singleWhiteList must be a subset of whiteList.
    'table-better': {
      language: 'en_US',
      menus: ['column', 'row', 'merge', 'table', 'cell', 'wrap', 'copy', 'delete'],
      toolbarButtons: {
        whiteList: ['link', 'image'],
        singleWhiteList: ['link', 'image']
      },
      toolbarTable: true
    }
  6. Understand the Quill Table structure and hierarchy

    main

    The quill-table-better plugin uses a nested hierarchy of Parchment blots to represent tables. Understanding this hierarchy is essential for manipulating table elements via the API.

    Hierarchy Overview:

    • TableContainer (the <table> element)
      • TableThead (<thead>)
        • TableThRow (<tr> for headers)
          • TableTh (<th>)
            • TableCellBlock (the content block inside a cell)
      • TableBody (<tbody>)
        • TableRow (<tr>)
          • TableCell (<td>)
            • TableCellBlock (the content block inside a cell)
      • TableColgroup (<colgroup>)
        • TableCol (<col>)

    Cell Content: Every cell (TableCell or TableTh) contains a block-level element (typically TableCellBlock, which renders as a <P> tag) to hold text or other content. This ensures valid HTML structure where text is not direct children of <td> or <th>.

  7. Use the table-better module API

    main

    Access the module instance using quill.getModule('table-better'). Once accessed, you can use the following methods:

    • deleteTable(): Deletes the current table.
    • hideTools(): Use this before submitting data (Delta or HTML) to the server to ensure table UI elements don't interfere with the output.
    • deleteTableTemporary(): Similar to hideTools, used when extracting HTML to ensure a clean state.
    • getTable(): Returns [table, row, cell, offset] for the current selection.
    • insertTable(rows, columns): Inserts a new table with the specified dimensions.
    const module = quill.getModule('table-better');
    
    module.deleteTable();
    module.insertTable(3, 3);
    const [table, row, cell, offset] = module.getTable();
    
    // When submitting data to a server:
    module.hideTools();
    const delta = quill.getContents();
    
    module.deleteTableTemporary();
    const html = quill.getSemanticHTML();
  8. Configure the Table module options

    main

    When initializing the Table module in Quill, you can provide an Options object to customize its behavior.

    Available options:

    • language: A string identifier or an object { name: string, content: Props } to localize the table UI.
    • menus: An array of strings specifying which menus to enable.
    • toolbarButtons: Configuration for the table toolbar buttons:
      • whiteList: An array of allowed button names.
      • singleWhiteList: An array of allowed button names for single-mode selection.
    • toolbarTable: A boolean. If set to true, it enables the ToolbarTable module and integrates a table selection UI into the existing Quill toolbar.
    // Example configuration object
    const options = {
      language: 'en',
      menus: ['row', 'col'],
      toolbarButtons: {
        whiteList: ['insert-row', 'delete-row'],
        singleWhiteList: ['insert-col']
      },
      toolbarTable: true
    };
  9. Configure toolbar button white lists

    main

    You can control which formatting buttons are enabled or disabled during cell selection by configuring whiteList and singleWhiteList within the toolbarButtons option of quill-table-better.

    • whiteList: A list of formats that are allowed when multiple cells are selected. If a toolbar button's format is not in this list, it will be disabled when multiple cells are selected.
    • singleWhiteList: A list of formats that are only allowed when a single cell is selected. If a format is in this list, the button will be disabled if more than one cell is selected.

    By default, the plugin uses internal defaults for these lists.

  10. Reference: Supported table formats

    main

    The following formats are supported for simultaneous operations on multiple cells (WHITE_LIST):

    const WHITE_LIST = [
      'bold',
      'italic',
      'underline',
      'strike',
      'size',
      'color',
      'background',
      'font',
      'list',
      'header',
      'align',
      'link',
      'image'
    ];

    Only the following formats are supported for single-cell formatting (SINGLE_WHITE_LIST):

    const SINGLE_WHITE_LIST = ['link', 'image'];
    const WHITE_LIST = [
      'bold',
      'italic',
      'underline',
      'strike',
      'size',
      'color',
      'background',
      'font',
      'list',
      'header',
      'align',
      'link',
      'image'
    ];
    
    const SINGLE_WHITE_LIST = ['link', 'image'];