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

@libs-ui/components-spreadsheet

v0.2.357-4

Published

> Bảng tính nhúng cho Angular (bọc [Univer](https://univer.ai)) — xem/chỉnh dữ liệu dạng lưới, định dạng số/ngày kiểu Excel, highlight cột đã map và bắt sự kiện cấu trúc cột.

Readme

@libs-ui/components-spreadsheet

Bảng tính nhúng cho Angular (bọc Univer) — xem/chỉnh dữ liệu dạng lưới, định dạng số/ngày kiểu Excel, highlight cột đã map và bắt sự kiện cấu trúc cột.

Giới thiệu

LibsUiComponentsSpreadsheetComponent là một Angular standalone component (OnPush + Signals) bọc thư viện Univer để hiển thị một bảng tính giống Excel/Google Sheets thu gọn. Component giao tiếp với bên ngoài qua getter FunctionControl (lấy bằng viewChild), KHÔNG gọi method private trực tiếp.

⚠️ Component thao tác trực tiếp DOM nội bộ (React/canvas) của Univer cho các tính năng tuỳ biến (panel numfmt, toolbar overflow…). Xem BUSINESS.md để biết các hành vi không được làm vỡ + bộ test hồi quy thủ công.

Tính năng

  • ✅ Nạp / lưu workbook dạng JSON snapshot (loadData, saveData, reset)
  • ✅ Định dạng số/ngày tuỳ biến kiểu Excel (~21 mẫu Ngày / Ngày+Giờ / Giờ), label là preview giá trị thật
  • ✅ Highlight cột đã map (style + prefix + auto-resize) qua luồng auto mappingIndicatorConfig + mappingTargets
  • ✅ Tự gỡ indicator khi saveData() để snapshot gửi server sạch
  • ✅ Bắt sự kiện double-click header cột (outColumnDblClick)
  • ✅ Bắt insert / remove / move cột — kể cả undo/redo (outColumnStructureChange) + helper remapColumnIndexes
  • ✅ Đổi ngôn ngữ runtime (vi / en), ẩn/hiện toolbar & sheet tabs, cấu hình ẩn toolbar item
  • ✅ Standalone, OnPush, Angular Signals — không cần NgModule

Khi nào sử dụng

  • Hiển thị / chỉnh sửa dữ liệu dạng bảng tính ngay trong app
  • Cho người dùng map cột dữ liệu sang field nghiệp vụ (highlight cột đã map)
  • Cần định dạng số / ngày tuỳ biến kiểu Excel trên dữ liệu nhập
  • Nạp workbook từ JSON và xuất lại snapshot để lưu server

Cài đặt

npm install @libs-ui/components-spreadsheet

Các package @univerjs/* đã khai báo là peerDependencies trong package.json của lib nên trình quản lý gói sẽ tự cài kèm — không cần cài thủ công.

⚠️ Nạp CSS của Univer (BẮT BUỘC — nếu thiếu, toolbar/panel/canvas sẽ vỡ giao diện)

Univer ship style riêng, KHÔNG đi kèm trong bundle của component. Consumer PHẢI tự nạp 5 file CSS sau, nếu không bảng tính sẽ hiển thị sai (mất toolbar, panel numfmt/menu trắng, layout lệch).

Khai báo trong angular.json / project.json:

// architect.build.options.styles  (Angular CLI)  HOẶC  targets.build.options.styles (Nx)
"styles": [
  "src/styles.scss",
  "./node_modules/@univerjs/design/lib/index.css",
  "./node_modules/@univerjs/ui/lib/index.css",
  "./node_modules/@univerjs/sheets-ui/lib/index.css",
  "./node_modules/@univerjs/sheets-formula-ui/lib/index.css",
  "./node_modules/@univerjs/sheets-numfmt/lib/index.css"
]

🔴 Thứ tự không bắt buộc, nhưng phải đủ cả 5 file. Thiếu @univerjs/ui hoặc @univerjs/sheets-ui là nguyên nhân phổ biến nhất khiến toolbar/panel không hiển thị.

Import

import {
  LibsUiComponentsSpreadsheetComponent,
  defaultMappingIndicatorConfig,
  remapColumnIndexes,
  toColumnLetter,
  applyMappingIndicators,
  stripMappingIndicators,
} from '@libs-ui/components-spreadsheet';
import type {
  T_indicatorTarget,
  T_indicatorStyle,
  T_mappingIndicatorConfig,
  T_columnStructureChange,
  T_cellFormatResult,
  T_toolbar_menu_config,
  T_toolbar_item_id,
} from '@libs-ui/components-spreadsheet';

Ví dụ sử dụng

Basic — bảng tính cơ bản

Component có :host { height: 100% } nên BẮT BUỘC bọc trong khung cố định chiều cao để canvas render đúng.

import { AfterViewInit, Component, viewChild } from '@angular/core';
import { LibsUiComponentsSpreadsheetComponent } from '@libs-ui/components-spreadsheet';

@Component({
  selector: 'app-basic-example',
  standalone: true,
  imports: [LibsUiComponentsSpreadsheetComponent],
  template: `
    <div class="h-[480px]">
      <libs_ui-components-spreadsheet #sheet [locale]="'vi'" />
    </div>
  `,
})
export class BasicExampleComponent implements AfterViewInit {
  private sheet = viewChild<LibsUiComponentsSpreadsheetComponent>('sheet');

  ngAfterViewInit(): void {
    this.sheet()?.FunctionControl.loadData({
      id: 'wb',
      sheetOrder: ['sheet1'],
      sheets: { sheet1: { id: 'sheet1', name: 'Sheet1', rowCount: 30, columnCount: 26, cellData: {} } },
    });
  }
}

Mapping Indicator — highlight cột đã map

import { Component, signal } from '@angular/core';
import { LibsUiComponentsSpreadsheetComponent, defaultMappingIndicatorConfig, type T_indicatorTarget } from '@libs-ui/components-spreadsheet';

@Component({
  selector: 'app-mapping-example',
  standalone: true,
  imports: [LibsUiComponentsSpreadsheetComponent],
  template: `
    <div class="h-[480px]">
      <libs_ui-components-spreadsheet
        [mappingIndicatorConfig]="indicatorConfig"
        [mappingTargets]="mappingTargets()"
        (outColumnDblClick)="onColumnDblClick($event)"
      />
    </div>
  `,
})
export class MappingExampleComponent {
  // Truyền config = "bật" luồng auto: tự apply khi load, tự strip khi save, tự vẽ lại khi targets đổi.
  protected readonly indicatorConfig = defaultMappingIndicatorConfig();
  protected mappingTargets = signal<T_indicatorTarget[]>([
    { sheetId: 'sheet1', colIndex: 0 },
    { sheetId: 'sheet1', colIndex: 3 },
  ]);

  // Double-click header → mở modal map cột, rồi cập nhật mappingTargets (component tự vẽ lại).
  onColumnDblClick(colIndex: number): void {
    this.mappingTargets.update((list) => [...list, { sheetId: 'sheet1', colIndex }]);
  }
}

Column Events — bắt insert/remove/move cột

import { Component, signal } from '@angular/core';
import { LibsUiComponentsSpreadsheetComponent, remapColumnIndexes, type T_columnStructureChange } from '@libs-ui/components-spreadsheet';

@Component({
  selector: 'app-events-example',
  standalone: true,
  imports: [LibsUiComponentsSpreadsheetComponent],
  template: `
    <div class="h-[480px]">
      <libs_ui-components-spreadsheet
        (outColumnDblClick)="onDblClick($event)"
        (outColumnStructureChange)="onStructureChange($event)"
      />
    </div>
  `,
})
export class EventsExampleComponent {
  protected mappings = signal<{ sheetId: string; colIndex: number; colLetter?: string }[]>([]);

  onDblClick(colIndex: number): void {
    console.log('Double-click cột', colIndex);
  }

  // Insert/remove/move cột → dịch lại mapping cho khớp vị trí mới (tránh lệch khi chèn/xoá cột giữa).
  onStructureChange(change: T_columnStructureChange): void {
    this.mappings.update((list) => remapColumnIndexes(list, change));
  }
}

Lưu & nạp lại snapshot

// Xuất snapshot (tự gỡ indicator nếu luồng auto đang bật) → gửi server.
const snapshot = this.sheet()?.FunctionControl.saveData();

// Nạp lại snapshot đã lưu.
this.sheet()?.FunctionControl.loadData(snapshot);

API

Selector

libs_ui-components-spreadsheet (khớp với selector trong @Component).

Inputs

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [locale] | 'vi' \| 'en' | 'vi' | Ngôn ngữ khởi tạo của toolbar/menu/panel. Đổi runtime qua FunctionControl.setLocale(). | [locale]="'en'" | | [mappingIndicatorConfig] | T_mappingIndicatorConfig | undefined | Truyền = bật luồng auto highlight cột đã map. | [mappingIndicatorConfig]="indicatorConfig" | | [mappingTargets] | T_indicatorTarget[] | [] | Danh sách cột cần highlight. Đổi runtime → tự vẽ lại header. | [mappingTargets]="targets()" | | [toolbarMenuConfig] | T_toolbar_menu_config | { ... } | Ẩn (hidden) / vô hiệu hoá (disabled) từng toolbar item. Thay đổi sẽ reinit Univer. | [toolbarMenuConfig]="{ 'sheet.command.set-range-bold': { hidden: true } }" |

Outputs

| Output | Type | Mô tả | |---|---|---| | (outColumnDblClick) | number | Emit colIndex khi double-click header cột. | | (outColumnStructureChange) | T_columnStructureChange | Emit khi insert / remove / move cột (gồm undo/redo). |

Handler ví dụ:

// component.ts
onColumnDblClick(colIndex: number): void {
  this.openMappingModal(colIndex);
}

onColumnStructureChange(change: T_columnStructureChange): void {
  this.mappings.update((list) => remapColumnIndexes(list, change));
}
<!-- template.html -->
<libs_ui-components-spreadsheet
  (outColumnDblClick)="onColumnDblClick($event)"
  (outColumnStructureChange)="onColumnStructureChange($event)"
/>

FunctionControl Methods

Lấy qua viewChildref().FunctionControl.method().

| Method | Mô tả | |---|---| | applyNumfmt(row, col, numRows, numCols, pattern) | Áp numfmt pattern cho một vùng ô. | | extractAllColumnFormats(snapshot) | Trích pattern numfmt của mọi cột từ snapshot. | | getActiveSheetInfo() | Lấy { sheetId, sheetName } của sheet đang active (null nếu chưa init). | | getColumnNumfmt(sheetId, colIndex) | Đọc numfmt pattern đại diện của một cột. | | loadData(data) | Nạp workbook snapshot (JSON) vào bảng tính. | | reset(data?) | Destroy + khởi tạo lại với data (mặc định = workbook rỗng). | | saveData() | Xuất snapshot JSON (tự gỡ indicator nếu luồng auto đang bật). | | scheduleOnReady(cb) | Chạy callback sau khi toolbar/numfmt model render xong. | | setLocale(locale) | Đổi ngôn ngữ runtime (kéo theo reinit Univer). | | toggleSheetTabs() | Ẩn/hiện thanh sheet tabs (footer). | | toggleToolbar() | Ẩn/hiện toolbar (header). |

Ngoài ra FunctionControl expose các signal read-only: activeCellFormat, activeCellRef, locale, showToolbar, showSheetTabs.

Hàm tiện ích (pure)

| Hàm | Mô tả | |---|---| | defaultMappingIndicatorConfig() | Trả config highlight mặc định (style 'm' xanh, revert 'h', prefix '● '). | | applyMappingIndicators(snapshot, targets, config?) | Đánh dấu header cột đã map trên snapshot (không mutate). | | stripMappingIndicators(snapshot, config?) | Gỡ indicator khỏi snapshot trước khi gửi server. | | remapColumnIndexes(items, change) | Dịch lại colIndex (+ colLetter) của mapping theo thao tác cấu trúc cột. | | toColumnLetter(index) | Chuyển colIndex 0-based → chữ cái Excel (0→'A', 26→'AA'). |

Types & Interfaces

type T_indicatorTarget = { sheetId: string; colIndex: number };

type T_mappingIndicatorConfig = {
  mappedStyleId?: string;        // @default 'm'
  mappedStyle?: T_indicatorStyle;
  defaultHeaderStyleId?: string; // @default 'h'
  scopeSheetIds?: string[];      // @default mọi sheet trong snapshot
  prefix?: string;               // @default '● '
  headerRowIndex?: number;       // @default 0
  autoResize?: boolean;          // @default true
  charWidth?: number;            // @default 7.5
  padding?: number;              // @default 16
};

type T_columnStructureChange = {
  sheetId: string;
  type: 'insert' | 'remove' | 'move';
  startColumn: number;
  count: number;
  toColumn?: number; // chỉ có với 'move'
};

type T_cellFormatResult = { sheet: string; col: string; colIndex: number; header: string; numfmt: string };

// Ẩn/vô hiệu hoá toolbar item — key tham chiếu T_toolbar_item_id
type T_toolbar_menu_config = Record<string, { hidden?: boolean; disabled?: boolean }>;

Lưu ý quan trọng

  • ⚠️ CSS Univer (BẮT BUỘC): phải nạp đủ 5 file CSS @univerjs/* (xem mục Cài đặt). Thiếu = toolbar/panel/menu trắng, layout vỡ.
  • ⚠️ Chiều cao: Component cao 100% — luôn bọc trong khung có chiều cao cố định, nếu không bảng tính sẽ không hiển thị.
  • ⚠️ FunctionControl: Tương tác qua getter FunctionControl lấy bằng viewChild, gọi trong/sau ngAfterViewInit. KHÔNG gọi method private.
  • ⚠️ Đổi locale / toolbarMenuConfig: kéo theo reinit toàn bộ Univer (mất undo history hiện tại).
  • ⚠️ Univer internal DOM: các tính năng numfmt panel/toolbar thao tác DOM nội bộ Univer — đọc BUSINESS.md trước khi sửa.