npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adapttable/element-plus

v0.3.1

Published

Element Plus data table controls for the AdaptTable Vue binding.

Readme

@adapttable/element-plus

Requires Node.js 22.12.0 or newer; packed releases are tested on Node 22.12 and Node 24.

AdaptTable's Vue data table with Element Plus controls and card surfaces.

<script setup lang="ts">
import { ref } from "vue";
import { DataTable, type ColumnDef } from "@adapttable/element-plus";
import "element-plus/dist/index.css";
import "@adapttable/element-plus/styles.css";

interface Person {
  id: string;
  name: string;
  score: number;
}

const rows: Person[] = [
  { id: "ada", name: "Ada", score: 92 },
  { id: "bea", name: "Bea", score: 87 },
];
const columns: ColumnDef<Person>[] = [
  { key: "name", header: "Name", sortable: true },
  { key: "score", header: "Score", sortable: true },
];
const selectedIds = ref<string[]>([]);
const rowKey = (row: Person) => row.id;
</script>

<template>
  <DataTable
    v-model:selected-ids="selectedIds"
    :data="rows"
    :columns="columns"
    :row-key="rowKey"
    :url-sync="false"
    selectable
  />
</template>

Combined feature imports

Use @adapttable/element-plus/features to compose the kit's native factories from one optional entry. Individual feature subpaths remain available; the base DataTable import does not load this barrel.

import { editing, filters } from "@adapttable/element-plus/features";

The factories retain their individual signatures, native controls and host-owned callbacks. See the Vue feature guide for composition and provider requirements.

Features

  • Feature composition with 41 canonical factories and focused, opt-in imports.
  • Sorting, multi-sort, pagination, global search, selection and selection statistics, with host-controlled state.
  • Filtering, custom filter types, the AND/OR filter tree and header filters.
  • Cell editing, row and batch editing, dirty indicators, undo/redo and host-owned save callbacks.
  • Column management, column groups, resizing and fit-to-width.
  • Grouping and aggregation, tree data, row expansion and nested tables.
  • Row reordering, row pinning, pinned summary rows, row and column spanning, full-width separator rows, row styling and virtualization.
  • Keyboard navigation, cell ranges, Find, saved views, row actions, bulk actions, a command palette, context menus and side-panel view controls.
  • Optional assistant and approval surfaces with host-owned transport and decisions.
  • CSV export and host-owned print layout; PDF export and XLSX use optional writers supplied to the export feature.
  • Pivot data, a spreadsheet formula engine and sparklines through the shared Vue binding's opt-in entries.
  • Mobile card layouts, localized labels, RTL and server-side rendering (SSR) with the host setup described below.

Import pdfWriter from @adapttable/vue/pdf or xlsxWriter from @adapttable/vue/xlsx and pass it as the writer option to this adapter's exportCsv factory. The adapter retains its own export controls.

For pivot data, import pivot and pivotTableModel from @adapttable/vue/pivot and render the prepared rows and columns with this adapter; the pivot entry's PivotPanel edits the axes and measures with Element Plus controls. Formula columns come from buildFormulaColumns in @adapttable/vue/formula, and SVG sparkline columns from sparklineColumn in @adapttable/vue/sparkline.

Rendering and styling

The desktop renderer places a semantic HTML table inside ElCard. The mobile renderer uses an ElCard for each prepared row. Sorting, selection, search and paging controls use Element Plus components; AdaptTable's Vue binding owns the data model, query state and host-write callbacks.

Native table rows and cells retain their semantic attributes, spans and focus references. The table surface uses one scroll owner. Its colors and spacing use Element Plus theme variables. Load Element Plus's dark-theme CSS variables when using its dark theme.

classNames styles the named part. Compound controls follow their kit's public attribute API:

  • ElCheckbox: the label host owns the part and styling class. Its associated native input owns checked, mixed and disabled state, and receives focus.
  • ElInput: the native input owns data attributes and its accessible name; the Element Plus field host owns the styling class.
  • ElSelect: the kit host owns the styling class; its native combobox owns the accessible name and focus behavior.

Filtering

import { filters } from "@adapttable/element-plus/filters";

const features = [
  filters<Person>([{ key: "name", type: "text" }], { tree: true }),
];

Pass features to DataTable. Use { mode: "drawer" } for an Element Plus modal drawer. FilterField, ChecklistFilter and FilterTreeBuilder are also available from the filtering entry point for custom layouts over the same binding models.

The nonmodal popup uses ElPopover for positioning and dialog semantics, with an ElCard content body. The filters-popover part and classNames.filtersPopover belong to that body. The drawer's filters-panel part and class belong to the actual ElDrawer dialog root. ElDrawer renders its modal mask internally and exposes only modalClass, so classNames.filtersBackdrop styles the mask and no filters-backdrop part is written to it.

Column header filters

Add headerFilters() alongside filters(...) to place an Element Plus filter button in each configured column header:

import { filters } from "@adapttable/element-plus/filters";
import { headerFilters } from "@adapttable/element-plus/header-filters";

const features = [
  filters<Person>([{ key: "name", type: "text" }]),
  headerFilters(),
];

The header popup uses ElPopover and the same binding-owned filter fields. FilterHeaderControl, FilterHeaderRow and ElementHeaderFilter are available from the header-filter entry point for custom layouts. Compact text and range fields use ElInput; single and Boolean choices use ElSelect; multiple choices use ElCheckbox inside an ElPopover. Their menus portal outside the scrolling viewport and stay inside the table root during fullscreen. Popup stacking follows ElConfigProvider's zIndex setting.

Pass dir="rtl" or dir="ltr" to a standalone FilterHeaderControl or FilterHeaderRow to keep its open popup synchronized with your reactive layout. When dir is omitted, the multiselect menu reads its native trigger's computed direction each time it opens. Inherited CSS direction is not observed while the menu stays open.

Optional view controls

Add density and fullscreen controls only where they are needed:

import { densityChooser } from "@adapttable/element-plus/density";
import { fullscreen } from "@adapttable/element-plus/fullscreen";

const features = [densityChooser(), fullscreen()];

Pass features to DataTable. Density uses two visible Element Plus radio buttons, Comfortable and Compact, with native radio-group keyboard behavior. Their labels follow the table locale. Use v-model:density to keep density in host state; a rejected request leaves the accepted choice checked. The same toggle is available in desktop tables and mobile cards, including RTL layouts. The fullscreen button appears only when the browser supports fullscreen; it promotes the existing table root.

Grouped, tree and detail rows

import { grouping } from "@adapttable/element-plus/grouping";
import { rowDetail } from "@adapttable/element-plus/row-detail";

const features = [
  grouping("score", { groupFooters: true }),
  rowDetail<Person>((person) => `Details for ${person.name}`),
];

Group expansion, paging and selection use Element Plus buttons and checkboxes in both desktop and mobile layouts. Group aggregates receive the original host rows. The tree entry point exports tree, useTreeExpansion and useLazyChildren; expansion and loading remain in the Vue binding.

rowDetail, nestedTable, nestedTableDetail and useRowExpansion are exported from row-detail. The nested-table entry point also exports nestedTable. Supply this kit's DataTable in a nested renderer to keep its controls and inherited density consistent with the parent.

Server rendering

Use Element Plus's documented per-request ID_INJECTION_KEY and ZINDEX_INJECTION_KEY setup, with the same seeds on the server and client. Also inject the actual ssrContext.teleports payload into its reported targets before hydration, as described in the Element Plus SSR guide. Internal select anchors can be present in that payload even when teleported is false.

Element Plus 2.14.7 assigns supplied form-control IDs after mounting. Checkbox labels therefore use their native nested-label association during server rendering. Input accessible names remain available through aria-label. Applications that use external label[for] associations should account for those IDs becoming available after hydration.

Element Plus SSR documentation

npm 10 co-installation with Popper

The packed Node harness uses npm's --legacy-peer-deps consumer profile. With npm 10.9.8, Element Plus 2.14.7's declared @popperjs/core: npm:@sxzz/popperjs-es@^2.11.8 dependency can be collapsed onto a co-installed real @popperjs/core, causing an ESM placements error. For that specific resolver profile, preserve the declared vendor identity with this consumer package.json override:

{
  "overrides": {
    "[email protected]": {
      "@popperjs/core": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz"
    }
  }
}

This is the official @sxzz/popperjs-es tarball required by Element Plus; it does not change vendor files or replace another kit's real Popper. The selector applies only to Element Plus 2.14.7, leaving future releases on their own declared dependency graph.

Row actions

import { rowActions } from "@adapttable/element-plus/row-actions";

const features = [
  rowActions<Person>([
    {
      key: "remove",
      label: "Remove",
      onClick: (person) => removePerson(person.id),
      confirm: {
        title: "Remove person?",
        message: () => "This cannot be undone.",
        confirmLabel: "Remove",
      },
    },
  ]),
];

Row-action controls activate after client mount, following the Vue binding's server-rendering lifecycle. Actions receive the original host row. Element Plus buttons request the action; the host performs the change. Confirmation uses ElMessageBox, stays inside the fullscreen table and uses the owning Vue app's providers. Dismissal, table deactivation and unmount cancel that table's pending dialogs. Supply confirm on DataTable to use your own confirmation handler.

Pinned, summary and supplementary rows

import {
  extraRows,
  pinnedSummaryRows,
  rowAppearance,
  rowPinning,
} from "@adapttable/element-plus/rows";

const features = [
  rowPinning(),
  pinnedSummaryRows<Person>({
    bottom: [{ id: "total", name: "Total", score: 179 }],
  }),
  extraRows([
    { key: "note", kind: "fullWidth", render: () => "Latest scores" },
  ]),
  rowAppearance<Person>({
    rowClassName: (person) => (person.score >= 90 ? "high-score" : undefined),
  }),
];

Data-row pin controls use Element Plus row actions. Pass a ref or getter through pinnedRowIds and handle onPinnedRowIdsChange to control their state. A rejected request leaves the rendered pin order unchanged. Grouped and tree tables do not support data-row pinning. Independent summary rows remain outside selection, sorting and filtering.

Desktop summaries and extras retain native table geometry, including spans. Mobile summaries and supplementary content use ElCard; their data rows keep all fields visible. Host row classes, styles and heights apply to the actual row or card. Individual optional entries are also available at /row-pinning, /pinned-summary-rows, /extra-rows and /row-appearance.

Column controls

import { type ColumnInput } from "@adapttable/element-plus";
import {
  collapsibleColumnGroups,
  fitColumns,
  multiSort,
  resizableColumns,
} from "@adapttable/element-plus/columns";

const columns: ColumnInput<Person>[] = [
  {
    header: "Scorecard",
    collapsedKey: "name",
    children: [
      { key: "name", sortable: true },
      { key: "score", sortable: true },
    ],
  },
];
const features = [
  collapsibleColumnGroups(),
  fitColumns(),
  multiSort(),
  resizableColumns(),
];

Column-group toggles, sort actions and resize handles use ElButton. Shift-click a desktop sort heading to add another priority. Resize handles support native pointer interaction and direction-aware Arrow keys through the shared binding. Use v-model:column-layout to accept layout requests; a supplied layout remains authoritative until the host updates it.

Mobile cards follow the accepted column layout and sort order. They omit the desktop group and resize controls. Header groups keep their native table spans and their localized toggle names during server rendering and hydration.

Find in table

import { findInTable } from "@adapttable/element-plus/find-in-table";

const features = [findInTable({ button: true })];

Find searches the prepared rows without filtering them. Its optional toolbar button opens an ElInput search field with ElButton previous, next and close controls. Ctrl/Cmd+F is scoped to the active table. Enter and Shift+Enter move between matches; Escape closes the bar and restores the preceding focus target. The same controls and match markers work with mobile cards.

The field's find-input part and accessible name belong to its native input; classNames.findInput styles the Element Plus host. Its focus target uses the documented native input/textarea exposures and the binding's ref lifecycle. findBar and findButton customize the remaining controls. Labels come from the shared table labels. With URL synchronization enabled, the shared find query restores the open bar and its value during server rendering and hydration.

Cell navigation and status

import {
  cellNavigation,
  columnSelectionCheckbox,
} from "@adapttable/element-plus/cell-navigation";
import { selectionStats, statusBar } from "@adapttable/element-plus/status-bar";

const features = [
  cellNavigation(),
  columnSelectionCheckbox(),
  statusBar(),
  selectionStats(),
];

Desktop cells use the binding's direction-aware keyboard navigation and range selection. Column selection uses ElCheckbox; selecting a column moves focus into its first grid cell. Status figures use ElText, with selection statistics inside a polite native output live region. Both status features share one strip. Standalone aliases are available at /column-selection and /selection-stats.

Fill requires onCellFill and editable columns. The host receives cell edit requests and decides whether to apply them. The pointer-only fill square uses Element Plus theme variables; keyboard fill remains in the shared grid model. The handle is hidden from assistive technology and does not add a tab stop.

Mobile cards show the status figures and Find controls while omitting desktop grid selection and fill handles. classNames.statusBar, statusItem, selectionStats, and fillHandle style their corresponding semantic parts.

Columns menu and renaming

import { columnMenu } from "@adapttable/element-plus/column-menu";

const features = [columnMenu()];

The Columns button opens an Element Plus popover containing a named ElCard dialog, real search and action buttons, and ElSelect plugin choices. Use it to show, hide, pin, reorder, resize or rename supported columns. Columns marked renameable: true also receive a direct header rename action. Menu and header renaming share the binding's validation, announcements and host callbacks.

Use v-model:column-layout to accept controlled layout changes. Until the host updates the supplied layout, rejected pin, visibility and rename requests leave the rendered columns unchanged. Renaming changes the display name, not the row field key. The same Columns menu is available with mobile cards.

The real card content owns the panel part, id, accessible dialog name and native ref. A documented virtual positioning reference lets the binding retain the actual trigger's ARIA relationship and events. Nested choice popups attach beside the scrolling card body, retaining its direction and dismissal boundary. The managed panel follows its supplied container, including fullscreen containers. The generic ColumnMenu component and ColumnMenuSlotProps are also exported for headless compositions.

Windowed rows and individual feature entries

import { virtualize } from "@adapttable/element-plus/virtualize";

const features = [
  virtualize({ maxHeight: 360, estimateRowSize: 48, estimateCardSize: 160 }),
];

Windowing belongs to the Vue binding. The Element Plus renderer retains its single native scroll viewport, semantic table spacer rows and kit mobile cards. It does not run a second table or virtualization engine. Omit the feature to render every row in the current source scope.

Column features are available individually at /column-groups, /fit-columns, /multi-sort and /resizable-columns, as well as through /columns. FilterHeaderControl and FilterHeaderRow are available from the package root and /header-filters; both routes retain the same component identities and row-generic contracts.

Bulk actions and print

import { bulkActions } from "@adapttable/element-plus/bulk-actions";
import { print } from "@adapttable/element-plus/print";

const features = [
  bulkActions([{ key: "archive", label: "Archive", onClick: archiveRows }]),
  print(printTable, true),
];

Bulk selection, matching-row scope, confirmation, pending state and errors are owned by the Vue binding. Element Plus supplies the real action buttons; the table's confirmation handler is used when an action requests confirmation. Controlled selection changes take effect when the host updates selected IDs. The same action bar works with desktop tables and mobile cards.

Print calls the supplied host callback. Pass true as the second argument to show the Element Plus print button; the default registers the capability without adding a toolbar button. Importing the package root does not load either feature.

Cell, row and batch editing

import {
  editing,
  editHistory,
  undoRedoButtons,
} from "@adapttable/element-plus/editing";
import { batchEditing } from "@adapttable/element-plus/batch-editing";

const features = [editing(saveCell), editHistory(), undoRedoButtons()];
const stagedFeatures = [batchEditing(saveRows)];

Mark a column editable: true and choose its editor: text, number, date, datetime, time, boolean, select, multi-select, or a host custom editor. Element Plus supplies ElInput, ElSelect, ElCheckbox and ElButton; the binding owns drafts, validation, parsing, save state, conflicts and host callbacks. The table never mutates host rows.

Double-click a cell or press F2 to edit. Enter commits a cell; Escape cancels and returns focus to its activation button. An open select consumes its own first Escape, preserving the outer edit. Moving focus within a select does not save the cell. The native input or the kit's supported focus method receives focus.

rowEditing(saveRow) provides row Save and Cancel buttons. batchEditing(saveRows) keeps changes staged until the batch Save action. Both modes also work in mobile cards. Failed host saves retain the shared error and retry/rollback behavior. Custom editors receive the binding's guarded draft, keyboard and focus contract. Compose editing with editHistory when row or batch history needs cell replay; undoRedoButtons adds genuine Element Plus history controls.

Editors retain server-rendered structure for hydration and retire open kit popups and stale callbacks when their table is cached or unmounted. Importing the package root does not activate or load editing controls.

Commands, saved views, grouping, and row moves

The canonical command-palette, context-menu, export, grouping-panel, row-reorder, saved-views, and side-panel entries fill the shared Vue feature contracts with Element Plus controls. Import the factories from those subpaths and pass them to DataTable through features.

import { commandPalette } from "@adapttable/element-plus/command-palette";
import { contextMenu } from "@adapttable/element-plus/context-menu";
import { exportCsv } from "@adapttable/element-plus/export";
import { groupingPanel } from "@adapttable/element-plus/grouping-panel";
import { rowReorder } from "@adapttable/element-plus/row-reorder";
import { savedViews } from "@adapttable/element-plus/saved-views";
import { sidePanel } from "@adapttable/element-plus/side-panel";

Command search and active items remain in the shared command model; ElDialog owns the palette's modal interaction. Context menus use ElDropdown and ElDropdownItem for native menu navigation. Both surfaces honor their table's fullscreen container. ElButton, ElInput, ElSelect, ElCheckbox, ElTag, ElCard, ElProgress, and ElLink render the other controls without introducing another feature store.

Grouping chips forward drag and keyboard interactions to the shared grouping controller. Aggregation changes use the same shared operations and host notifications. Row reorder requests preserve host row ownership; cross-group and tree moves use the shared confirmation model rendered through ElDialog.

The saved-views entry also exports SavedViewsPanel and SavedViewsPanelProps for management surfaces. Rename drafts, read-only/default rules, ordering, URL state, and storage remain owned by the shared saved-view models. sidePanel retains controlled panel selection, with native buttons and a native card frame.

Optional assistant and pivot controls

The assistant entry provides TableAssistant, AgentApproval, tableAssistant(), and agentApproval() using the binding's conversation and approval contracts. Its sheet is an ElDrawer, examples use ElDropdown, the composer is an ElInput textarea, and speech language choices use ElSelect. It does not import an AI transport or own approval decisions. The pivot entry provides a controlled PivotPanel with ElSelect and ElButton controls.