Skip to content

ryuhojin/OneGrid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

7 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

โšก OneGrid

๊ธˆ์œตยท๊ณต๊ณต SI ํ”„๋กœ์ ํŠธ๋ฅผ ๋ชฉํ‘œ๋กœ ์„ค๊ณ„ ์ค‘์ธ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ํ”„๋ก ํŠธ์—”๋“œ ๋ฐ์ดํ„ฐ ๊ทธ๋ฆฌ๋“œ

TypeScript React Vue Docusaurus Security

OneGrid๋Š” ๋‹จ์ˆœ ํ…Œ์ด๋ธ” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ, ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์กฐํšŒยทํŽธ์ง‘ยท๋ณด์•ˆยท์ ‘๊ทผ์„ฑยท๋ฌธ์„œํ™”ยทํ”„๋ ˆ์ž„์›Œํฌ ๋ž˜ํผ๊นŒ์ง€ ํฌํ•จํ•˜๋Š” ์ƒ์šฉ ๊ทธ๋ฆฌ๋“œ 1.0์„ ๋ชฉํ‘œ๋กœ ๊ฐœ๋ฐœ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿงญ ํ˜„์žฌ ์ƒํƒœ

ํ˜„์žฌ ๋ฒ„์ „์€ 0.0.0 ํ”„๋ฆฌ ๋ฆด๋ฆฌ์ฆˆ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. API๋Š” 1.0 ์•ˆ์ •ํ™” ์ „๊นŒ์ง€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ API_CHANGELOG.md์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

์˜์—ญ ์ƒํƒœ
ํŒจํ‚ค์ง€ ๊ตฌ์กฐ core, dom, react, vue, themes, pagination, adapters, testing ๋ถ„๋ฆฌ
๋ฐ์ดํ„ฐ ๋ชจ๋ธ Client, Infinite, Server, Viewport, Tree row model baseline
๋Œ€์šฉ๋Ÿ‰ ์ „๋žต 10M/100M rows๋Š” ์ „์ฒด ๋ฐฐ์—ด/DOM์ด ์•„๋‹ˆ๋ผ Server/Viewport/Segmented virtual scroll ๊ธฐ๋ฐ˜
๋ ˆ์ด์•„์›ƒ pinned pane, frozen rows/columns, row/column virtualization, header/cell merge
ํ•ต์‹ฌ ๊ธฐ๋Šฅ sort, filter, edit, selection, clipboard, menu, summary, grouping, tree, pivot, pagination
๋ณด์•ˆ CSP nonce, text-only ๊ธฐ๋ณธ ๋ Œ๋”๋ง, sanitizer hook, URL protocol allowlist
๋ž˜ํผ Vanilla DOM, React, Vue API parity baseline
๋ฌธ์„œ/์˜ˆ์ œ Docusaurus ๋ฌธ์„œ์™€ Vanilla/React/Vue ์˜ˆ์ œ ์นดํƒˆ๋กœ๊ทธ ์šด์˜

๐Ÿ–ผ๏ธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

Column Virtualization Pivot Pagination
Column virtualization screenshot Pivot screenshot Pagination screenshot

โœจ ์™œ OneGrid์ธ๊ฐ€

  • ๐Ÿฆ SI ์นœํ™” ๊ตฌ์กฐ: ๊ธˆ์œตยท๊ณต๊ณต ํ”„๋กœ์ ํŠธ์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ณ ์ • ์ปฌ๋Ÿผ, ๋ณ‘ํ•ฉ, ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ, ํŽธ์ง‘ ์ด๋ ฅ, ๋ณด์•ˆ ์ •์ฑ…์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿงฑ ๋ถ„๋ฆฌ๋œ ์•„ํ‚คํ…์ฒ˜: @onegrid/core๋Š” DOM์— ์˜์กดํ•˜์ง€ ์•Š๊ณ , @onegrid/dom, @onegrid/react, @onegrid/vue๊ฐ€ ๋™์ผํ•œ ๊ณ„์•ฝ์„ ์†Œ๋น„ํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿš€ ๋Œ€์šฉ๋Ÿ‰ ๊ธฐ์ค€์˜ ์„ค๊ณ„: 10M ~ 100M rows๋Š” client array๊ฐ€ ์•„๋‹ˆ๋ผ row model๊ณผ segmented viewport mapping์œผ๋กœ ๋‹ค๋ฃน๋‹ˆ๋‹ค.
  • ๐Ÿ” ์•ˆ์ „ํ•œ ๊ธฐ๋ณธ๊ฐ’: ๋ฌธ์ž์—ด ๋ Œ๋”๋ง์€ ๊ธฐ๋ณธ์ ์œผ๋กœ text ์ฒ˜๋ฆฌ๋˜๊ณ , HTML ๋ Œ๋”๋ง์€ sanitizer๊ฐ€ ์žˆ๋Š” ๋ช…์‹œ์  opt-in์œผ๋กœ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.
  • โ™ฟ ์‹ค์‚ฌ์šฉ ์ ‘๊ทผ์„ฑ: ํ‚ค๋ณด๋“œ ํฌ์ปค์Šค, ARIA grid semantics, header/menu interaction์„ E2E๋กœ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  • ๐ŸŽจ ํ…Œ๋งˆ ํ™•์žฅ์„ฑ: CSS variable ๊ธฐ๋ฐ˜ theme foundation๊ณผ SI tenant palette๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ฆ ํŒจํ‚ค์ง€

ํŒจํ‚ค์ง€ ์—ญํ• 
@onegrid/core public type, column/row/state/event/plugin contract, ์ˆœ์ˆ˜ ๋กœ์ง
@onegrid/dom DOM renderer, virtualization, focus, editor/menu/export runtime
@onegrid/react React wrapper, ref ๊ธฐ๋ฐ˜ GridApi, React renderer slot bridge
@onegrid/vue Vue wrapper, expose ๊ธฐ๋ฐ˜ GridApi, Vue slot bridge
@onegrid/themes default theme, SI theme token, runtime theme helper
@onegrid/pagination pagination contract/package baseline
@onegrid/adapters import/export and external adapter boundary
@onegrid/testing test helpers and shared verification utilities

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

pnpm add @onegrid/core @onegrid/dom @onegrid/themes
import { OneGrid } from "@onegrid/dom";
import type { ColumnDef } from "@onegrid/core";
import "@onegrid/themes/default.css";

interface OrderRow {
  readonly id: string;
  readonly customer: string;
  readonly amount: number;
  readonly status: "Draft" | "Approved" | "Rejected";
}

const columns: readonly ColumnDef<OrderRow>[] = [
  { field: "id", headerName: "ID", pinned: "left" },
  { field: "customer", headerName: "Customer" },
  { field: "amount", headerName: "Amount", type: "number" },
  { field: "status", headerName: "Status", filter: "set" }
];

const rows: readonly OrderRow[] = [
  { id: "ORD-1001", customer: "Han Public Office", amount: 1200000, status: "Approved" },
  { id: "ORD-1002", customer: "Korea Finance", amount: 450000, status: "Draft" },
  { id: "ORD-1003", customer: "Metro Audit Team", amount: 780000, status: "Rejected" }
];

const grid = new OneGrid<OrderRow>({
  el: document.querySelector("#grid") as HTMLElement,
  columns,
  data: rows,
  rowModel: "client",
  accessibility: { label: "Orders grid" }
});

grid.selectRows(["ORD-1001"]);

React

pnpm add @onegrid/react @onegrid/core @onegrid/dom @onegrid/themes
import { useRef } from "react";
import { OneGrid, type OneGridHandle } from "@onegrid/react";
import "@onegrid/themes/default.css";

export function OrdersGrid() {
  const gridRef = useRef<OneGridHandle<OrderRow>>(null);

  return (
    <OneGrid<OrderRow>
      ref={gridRef}
      columns={columns}
      data={rows}
      rowKey="id"
      rowModel="client"
      accessibility={{ label: "Orders grid" }}
      onSelectionChanged={(event) => console.log(event.rowKeys)}
    />
  );
}

Vue

pnpm add @onegrid/vue @onegrid/core @onegrid/dom @onegrid/themes
<script setup lang="ts">
import { ref } from "vue";
import { OneGrid, type OneGridExpose } from "@onegrid/vue";
import "@onegrid/themes/default.css";

const grid = ref<OneGridExpose>();
</script>

<template>
  <OneGrid
    ref="grid"
    :columns="columns"
    :data="rows"
    row-key="id"
    row-model="client"
    :accessibility="{ label: 'Orders grid' }"
  />
</template>

๐Ÿงฉ ์ฃผ์š” ๊ธฐ๋Šฅ

Column / Header

  • field ๊ธฐ๋ฐ˜ ์ปฌ๋Ÿผ๊ณผ columnId ๊ธฐ๋ฐ˜ fieldless column์„ ๋ชจ๋‘ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • defaultColumnDef, columnTypes, columnState, getColumnState, setColumnState, resetColumnState๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • group header, header merge, pinned column, column resize/move/hide UI๋ฅผ ์˜ˆ์ œ์™€ E2E ๊ธฐ์ค€์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

Row Model

  • client: ๋ธŒ๋ผ์šฐ์ € ๋ฉ”๋ชจ๋ฆฌ์— ์ ํ•ฉํ•œ ๋ฐ์ดํ„ฐ์…‹์šฉ์ž…๋‹ˆ๋‹ค.
  • infinite: block request์™€ lazy loading ๊ธฐ๋ฐ˜์ž…๋‹ˆ๋‹ค.
  • server: ์„œ๋ฒ„ ์ •๋ ฌ/ํ•„ํ„ฐ/๊ทธ๋ฃน ํ™•์žฅ ์š”์ฒญ์„ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • viewport: ๋…ผ๋ฆฌ row index์™€ visible range ๊ธฐ๋ฐ˜ ๋Œ€์šฉ๋Ÿ‰ ํƒ์ƒ‰์šฉ์ž…๋‹ˆ๋‹ค.
  • tree: hierarchical row ํ‘œ์‹œ์™€ expand/collapse baseline์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Editing

  • cell editing, batch edit session, pending edit history, commit/cancel, undo/redo edit stack์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • Tab, Enter, Escape, Backspace ํŽธ์ง‘ ์ •์ฑ…์„ ๋ฌธ์„œํ™”ํ•˜๊ณ  ํ‚ค๋ณด๋“œ ์ด๋™๊ณผ ์Šคํฌ๋กค ๋™๊ธฐํ™”๋ฅผ ๋ณด๊ฐ•ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • read-only edit / external state integration์„ ํ†ตํ•ด wrapper controlled state์™€ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Export / Import

  • CSV, XLSX, PDF, print layout export๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • import๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๊ต์ฒดํ•˜๋ฉฐ, append ๋ฐฉ์‹์€ ๋ณ„๋„ ์˜ต์…˜์œผ๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • merge layout, grouped header, paged data, wide columns๋ฅผ ์ƒ์šฉ ์‚ฐ์ถœ๋ฌผ ํ’ˆ์งˆ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์† ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽ๏ธ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์›์น™

OneGrid์˜ 10M ~ 100M rows ์ง€์›์€ ์•„๋ž˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  • ์ „์ฒด row ๋ฐฐ์—ด์„ ๋ธŒ๋ผ์šฐ์ €์— ์˜ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ „์ฒด row DOM์„ ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ServerRowModel, InfiniteRowModel, ViewportRowModel, segmented virtual scroll mapping์œผ๋กœ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.
  • request dedupe, cancellation, cache window, logical row index๋ฅผ ์กฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๊ธˆ์ง€๋˜๋Š” ๋ฐฉ์‹:

// ๊ธˆ์ง€: 100M rows ์ „์ฒด ๋ฐฐ์—ด ์ƒ์„ฑ
const rows = Array.from({ length: 100_000_000 }, createRow);

๊ถŒ์žฅ ๋ฐฉ์‹:

const grid = new OneGrid({
  el,
  columns,
  rowModel: "viewport",
  dataSource: {
    async getRows({ startRow, endRow }) {
      return {
        rows: await fetchRows(startRow, endRow),
        rowCount: 100_000_000
      };
    }
  },
  viewport: {
    initialRowCount: 100_000_000,
    viewportSize: 60,
    overscan: 24
  },
  virtualization: {
    segmented: true,
    rowHeight: 30
  }
});

๐Ÿ” ๋ณด์•ˆ ๊ธฐ๋ณธ๊ฐ’

  • eval, new Function, inline event handler๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ cell/header renderer๋Š” ๋ฌธ์ž์—ด์„ HTML์ด ์•„๋‹ˆ๋ผ text๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • HTML renderer๋Š” ๋ช…์‹œ์  opt-in์ด๋ฉฐ sanitizer๋ฅผ ์ฃผ์ž…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • CSP nonce ๊ธฐ๋ฐ˜ style injection์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • URL formatter๋Š” http:, https:, mailto:, tel: ๋“ฑ ํ—ˆ์šฉ protocol๋งŒ ํ†ต๊ณผ์‹œํ‚ต๋‹ˆ๋‹ค.

๊ด€๋ จ ๋ฌธ์„œ:


๐ŸŽจ ํ…Œ๋งˆ์™€ SI ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

@onegrid/themes๋Š” CSS variable ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ , tenant ๋‹จ์œ„ ํ…Œ๋งˆ๋ฅผ ๋Ÿฐํƒ€์ž„์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { createSiTheme } from "@onegrid/themes";

const theme = createSiTheme({
  name: "bnk-red",
  density: "compact",
  tokens: {
    colors: {
      accent: "rgb(215 25 31)",
      accentHover: "rgb(139 3 4)",
      border: "rgb(183 169 151)",
      header: "rgb(248 250 252)",
      selected: "rgb(255 238 238)",
      muted: "rgb(101 92 79)"
    }
  }
});

์˜ˆ์ œ ์นดํƒˆ๋กœ๊ทธ์—๋Š” BNK CI ์ƒ‰์ƒ์„ ๊ธฐ์ค€์œผ๋กœ ์•„๋ž˜ ๊ณ„์—ด์„ ๊ตฌ์„ฑํ•ด ๋‘” SI ํŒ”๋ ˆํŠธ ์˜ˆ์ œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • si-bnk-red
  • si-bnk-gold
  • si-bnk-gray

๐Ÿงช ๋กœ์ปฌ ๊ฐœ๋ฐœ

pnpm install
pnpm --filter @onegrid/examples dev --host 127.0.0.1 --port 4174

๋ธŒ๋ผ์šฐ์ €์—์„œ ์•„๋ž˜ ์ฃผ์†Œ๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

http://127.0.0.1:4174

์ž์ฃผ ๋ณด๋Š” ์˜ˆ์ œ:

๊ฒฝ๋กœ ํ™•์ธ ํฌ์ธํŠธ
/#COL-003 ์ปฌ๋Ÿผ UI, ๋ฉ”๋‰ด, resize, pin/hide/move
/#ROW-003 Server row model๊ณผ group expand request
/#LAY-003 Column virtualization๊ณผ pinned pane scroll sync
/#LAY-004 Cell merge layout๊ณผ range selection
/#F-EDIT Batch edit, pending edits, undo/redo
/#F-EXPORT CSV/XLSX/PDF/print/import
/#F-I18N ๋Ÿฐํƒ€์ž„ locale ๋ณ€๊ฒฝ
/#SEC-001 CSP nonce ์˜ˆ์ œ
/#THEME-002 SI theme customization
/#EX-005-006 100M viewport rows setup

โœ… ๊ฒ€์ฆ ๋ช…๋ น

pnpm lint
pnpm typecheck
pnpm test:unit
pnpm test:e2e
pnpm test:a11y
pnpm test:perf:smoke
pnpm build
pnpm docs:build

์‹œ๊ฐ ํšŒ๊ท€ smoke:

pnpm test:e2e:visual

๐Ÿ—‚๏ธ ๋ฌธ์„œ ์ง€๋„

๋ฌธ์„œ ์šฉ๋„
AGENTS.md ๊ฐœ๋ฐœ ์—์ด์ „ํŠธ ์šด์˜ ๊ทœ์น™๊ณผ ํ’ˆ์งˆ ๊ธฐ์ค€
ARCHITECT.md ์•„ํ‚คํ…์ฒ˜ ์›์น™, ํŒจํ‚ค์ง€ ๊ฒฝ๊ณ„, ๋Œ€์šฉ๋Ÿ‰ ์ „๋žต
CHECKLIST.md ๋กœ๋“œ๋งต, ์™„๋ฃŒ ์ฆ๋น™, ๋ฆฌ์Šคํฌ/๊ฒฐ์ • ๊ธฐ๋ก
API_CHANGELOG.md public API ๋ณ€๊ฒฝ ์ด๋ ฅ
SECURITY.md ๋ณด์•ˆ ์ •์ฑ…๊ณผ ๊ธฐ๋ณธ๊ฐ’
apps/docs/docs/api GridOptions, ColumnDef, GridApi, Events, Plugins
apps/docs/docs/features ๊ธฐ๋Šฅ๋ณ„ ๊ฐ€์ด๋“œ
apps/docs/docs/frameworks React, Vue, API parity
apps/docs/docs/quick-start Vanilla, React, Vue ๋น ๋ฅธ ์‹œ์ž‘

๐Ÿ›ฃ๏ธ ๋ฆด๋ฆฌ์ฆˆ ๋ฐฉํ–ฅ

OneGrid 1.0 ์ „๊นŒ์ง€ ํŠนํžˆ ์•„๋ž˜ ํ•ญ๋ชฉ์„ ๊ณ„์† ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.

  • ๋Œ€์šฉ๋Ÿ‰ viewport/server row model์˜ ๋ธŒ๋ผ์šฐ์ €๋ณ„ ์Šคํฌ๋กค ํ’ˆ์งˆ
  • cell/header merge์™€ pinned/virtualization ์กฐํ•ฉ์˜ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ
  • export/import ์‚ฐ์ถœ๋ฌผ์˜ Excel/PDF/print fidelity
  • framework wrapper API parity์™€ controlled state integration
  • CSP/XSS/a11y/performance ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ ์ž๋™ํ™”

๐Ÿ“œ ๋ผ์ด์„ ์Šค

๋ผ์ด์„ ์Šค๋Š” ์•„์ง ํ™•์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. npm/CDN ๋ฐฐํฌ ๋˜๋Š” ์™ธ๋ถ€ ๋ฐฐํฌ ์ „ ํ”„๋กœ์ ํŠธ ๋ผ์ด์„ ์Šค๋ฅผ ํ™•์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

About

Grid

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors