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

@rfjs/table-builder

v0.1.0

Published

Config-driven read-only data table engine over @rfjs/data-schema: TableConfig, derive from resource metadata, sorting/formatting/pagination pure functions

Downloads

89

Readme

@rfjs/table-builder

English → README.md

建立在 @rfjs/data-schema 之上的設定驅動、唯讀的資料表格引擎。 它把資源的欄位中繼資料編譯成可編輯的 TableConfig(欄位、分頁、預設排序),並提供 用於前端排序、儲存格格式化、頁碼計算的純函式。它本身不做任何渲染 —— @rfjs/table-builder-ui 才是消費 TableConfig 並把它畫出來的 React 層。


安裝

npm i @rfjs/table-builder

@rfjs/data-schema 是相依套件 —— 它的核心型別(ScalarTypeLocalizedLabelDataResourceMeta 等)以及 resolveLabel/getByPath 都會從本套件的根重新匯出, 因此大多數消費者不需要直接 import @rfjs/data-schema

快速開始

import { deriveTableConfig, sortRows, formatCell, pageCount, pageToOffset } from '@rfjs/table-builder';
import type { DataResourceMeta } from '@rfjs/data-schema';

const meta: DataResourceMeta = {
  fields: [
    { key: 'name', label: 'Name', dataType: 'string', sortable: true },
    { key: 'price', label: 'Price', dataType: 'numeric', format: 'currency', sortable: true },
    {
      key: 'status',
      label: 'Status',
      dataType: 'string',
      options: [
        { value: 'active', label: 'Active' },
        { value: 'inactive', label: 'Inactive' },
      ],
    },
  ],
};

// 1. 把欄位中繼資料編譯成可編輯的表格設定(pageSize 預設為 10)
const config = deriveTableConfig(meta);
// → { columns: [{ key: 'name', ... }, { key: 'price', ... }, { key: 'status', ... }], pagination: { pageSize: 10 } }

// 從這裡開始 config 可自由再編輯 —— 重新排序 config.columns、
// 切換 column.visible、設定 column.pin 等,它不再與 `meta` 同步。

const rows = [
  { name: 'Widget', price: 9.99, status: 'active' },
  { name: 'Gadget', price: 19.5, status: 'inactive' },
];

// 2. 前端排序(穩定排序;不論方向為何,null 值一律沉到最底)
const sorted = sortRows(rows, { key: 'price', direction: 'desc' }, config.columns);

// 3. 將每個儲存格格式化為顯示用字串(options 對照優先於 format;locale 感知的 Intl 格式化)
const cell = formatCell(sorted[0].price, config.columns[1], 'en');
// → '$19.50'
const statusCell = formatCell(sorted[0].status, config.columns[2], 'en');
// → 'Inactive'

// 4. 伺服端分頁資源的頁碼運算
const totalPages = pageCount(87, config.pagination.pageSize); // → 9
const offset = pageToOffset(3, config.pagination.pageSize); // → 20(第 3 頁,1 起始,pageSize 10)

驗證 TableConfig

來自儲存層或使用者輸入的設定(例如已儲存的表格版面)應該經過解析,而不是直接信任:

import { parseTableConfig } from '@rfjs/table-builder';

const config = parseTableConfig(rawJson); // 形狀或 format 不符時拋出 ZodError

@rfjs/data-schemadataFieldMetaSchema 相同的 formatdataType 交叉檢查 (例如 'percent' 只在 dataType: 'numeric' 時合法)。

API

編譯 / 排序 / 格式化 / 分頁

| 匯出 | 簽章 | 說明 | | --- | --- | --- | | deriveTableConfig(meta) | (DataResourceMeta) => TableConfig | 單向編譯:把 fields 映射為 columns(捨棄 filterable),pagination.pageSize 預設為 10;深拷貝 label/options,結果絕不與 meta 共用參照 | | sortRows(rows, sort, columns) | (Record<string, unknown>[], SortState, TableColumnConfig[]) => Record<string, unknown>[] | 前端穩定排序;比較器依對應欄位的 dataType 選擇;null/undefined 值一律沉到最底;不會修改輸入陣列 | | formatCell(value, column, locale?) | (unknown, TableColumnConfig, string) => string | null/undefined'';column.options 的 value→label 對照優先於 format;其次依 column.formatIntl 數字/日期格式化;都沒有則回傳 String(value);locale 預設為 'en' | | pageCount(total, pageSize) | (number, number) => number | 總頁數,至少為 1 | | pageToOffset(page, pageSize, firstPage?) | (number, number, 0 \| 1) => number | 頁碼 → 0 起始的資料列 offset;firstPage 預設為 1 | | offsetToPage(offset, pageSize, firstPage?) | (number, number, 0 \| 1) => number | pageToOffset 的反函式 | | hasNextCursor(cursor) | (string \| undefined) => boolean | 當 cursor 有定義且非空字串時回傳 true |

驗證(zod)

| 匯出 | 驗證對象 | | --- | --- | | parseTableConfig(input) | TableConfig;形狀不合法時拋出例外 | | tableConfigSchema | 完整設定(columns(至少 1 筆)+ pagination + 選用的 defaultSort/emptyText) | | tableColumnConfigSchema | 單一欄位;交叉檢查 formatdataType | | tablePaginationConfigSchematableDefaultSortSchema | 分頁 / 預設排序子形狀 |

@rfjs/data-schema 重新匯出

resolveLabelgetByPath,以及型別 ScalarTypeLocalizedLabelFieldFormatFieldOptionDataResourceMetaDataFieldMetaSortState —— 讓 table-builder 的 消費者不需要為了這些直接相依 @rfjs/data-schema

TableConfig / TableColumnConfig

interface TableColumnConfig {
  key: string;
  label: LocalizedLabel;
  dataType: ScalarType;
  format?: FieldFormat;
  options?: FieldOption[];
  sortable?: boolean; // 預設 false
  visible?: boolean; // 預設 true —— 編輯器的顯示/隱藏切換
  pin?: 'left' | 'right';
  align?: 'left' | 'center' | 'right'; // 未設定 -> 由渲染器依 dataType 決定預設(numeric -> right,其餘 -> left)
}

interface TableConfig {
  columns: TableColumnConfig[]; // 陣列順序 = 欄位順序(拖曳排序即編輯此陣列)
  pagination: { pageSize: number; pageSizeOptions?: number[] };
  defaultSort?: { key: string; direction: 'asc' | 'desc' };
  emptyText?: LocalizedLabel; // 選用,UI 有英文預設值
}

TableConfig/TableColumnConfig凍結命名:@rfjs/form-builder 的 result item 將會內嵌 { mode: 'table', table: TableConfig },所以這些型別是共享契約, 不是本套件的實作細節。

家族關係

 @rfjs/data-schema
 欄位 / 請求 / 回應中繼資料契約
              ▼
 @rfjs/table-builder                 ← 你在這裡
 deriveTableConfig(meta) → TableConfig,
 並提供 sortRows / formatCell / paginate 等純函式
              ▼
 @rfjs/table-builder-ui              @rfjs/form-builder(result item)
 TableConfig 的 React 渲染器            mode: 'table' 內嵌一個 TableConfig

本套件是邏輯層:沒有 React、也不做渲染。如果你需要在頁面上畫出實際的 <table>, 請安裝 @rfjs/table-builder-ui,把本套件產出的 TableConfig 交給它 —— 不要在原始 config 上自行重新實作渲染邏輯。

授權

ISC