comins-table 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.1.4 - 2026-07-23
6
+
7
+ - Added opt-in priority-based multi-column sorting for flat and Tree Grid data, including Shift-assisted Header input, sort-model callbacks and Ref methods, accessibility metadata, documentation, and a runnable Playground example.
8
+
9
+ ## 0.1.3 - 2026-07-22
10
+
11
+ - Added 6-pixel mouse Header reorder activation with source placeholder, ghost, target marker, vertical-intent cancellation, and preserved non-mouse long-press compatibility.
12
+ - Connected Virtual List Item and More activation to owning Row selection, preserved More keyboard focus, and suppressed invalid column-layout callback emissions.
13
+ - Added a consumer-first README and real-product animated preview covering sorting, column reorder, Virtual List selection, Summary Row, and Tree Grid interaction.
14
+ - Expanded focused browser and documentation regression coverage for the shipped interaction and README contracts.
15
+
5
16
  ## 0.1.2 - 2026-07-22
6
17
 
7
18
  - Extended Summary Row with descriptor-based `colSpan`, aggregate output `format`, and row or cell `className` and `style`.
package/README.md CHANGED
@@ -1,14 +1,38 @@
1
1
  # Comins Table
2
2
 
3
- Comins Table is a controlled React data table for data-heavy application screens. It provides a reusable table component, framework-independent core helpers, virtualized rendering, selection, clipboard helpers, pagination, sorting, two-level headers, summary rows, controlled Tree Grid rendering, lazy loading, infinite scrolling, loading states, and CSS-variable based theming.
3
+ Comins Table is a controlled React data table for data-heavy application screens, with virtualized rendering, precise selection, movable headers, Summary Row aggregation, Tree Grid data, built-in component cells, and framework-independent core helpers.
4
4
 
5
- Comins Table is built as a standalone open-source package. It does not wrap another table or grid implementation.
5
+ [![npm version](https://img.shields.io/npm/v/comins-table)](https://www.npmjs.com/package/comins-table)
6
+ [![TypeScript declarations](https://img.shields.io/npm/types/comins-table)](https://www.npmjs.com/package/comins-table)
7
+ [![Verify](https://github.com/kim1124/comins-table/actions/workflows/verify.yml/badge.svg?branch=main)](https://github.com/kim1124/comins-table/actions/workflows/verify.yml)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
9
 
7
- ## Repository Scope
10
+ ![Comins Table sorting, column reorder, Row selection, Summary Row, and Tree Grid demo](https://raw.githubusercontent.com/kim1124/comins-table/main/docs/assets/comins-table-demo.gif)
8
11
 
9
- Comins Table is maintained as an independent repository. This repository is the source of truth for the library, Playground, public documentation, tests, and releases.
12
+ ## Why Comins Table
10
13
 
11
- Run development and verification commands from this repository root. Comins Table is not managed as a workspace package, so commands do not require an `npm --workspace` prefix. Future feature work and releases belong in this repository.
14
+ | Area | Shipped capabilities |
15
+ | --- | --- |
16
+ | Controlled data | Application-owned `data`, CRUD helpers, `onChangeData`, pagination, sorting, and layout callbacks |
17
+ | Rendering and scale | Fixed-height virtualization with a tested 100,000-row route, infinite scroll, append-mode lazy loading, loading, and empty states |
18
+ | Interaction | Accessible single and opt-in multi-column Header sorting, resize, 6-pixel horizontal column reorder with source placeholder, Row and Cell selection, ranges, clipboard, and context menu callbacks |
19
+ | Data structure | Summary Row count/sum/avg/min/max/custom aggregation, `colSpan`, `format`, style/class hooks, and controlled Tree Grid expand/fold |
20
+ | Custom UI | Cell/Header renderers, built-in button/input/checkbox/radio/select/toggle/progress/menu/Virtual List components, and CSS-variable themes |
21
+
22
+ Comins Table is standalone and does not wrap another table or grid implementation.
23
+
24
+ ## Support
25
+
26
+ | Surface | Support |
27
+ | --- | --- |
28
+ | React | `>=18.0.0 <20.0.0` |
29
+ | React DOM | `>=18.0.0 <20.0.0` |
30
+ | TypeScript | Declarations bundled with every JavaScript entry point; CSS available through the stylesheet export |
31
+ | Chrome and Edge | Current stable Chromium-based releases |
32
+ | Automated browser gate | Playwright-bundled Chromium |
33
+ | Firefox and Safari | Outside the supported contract until Firefox and WebKit projects are added |
34
+ | SSR | Client boundary required; server rendering is not currently supported |
35
+ | Runtime network behavior | No package-owned requests, remote assets, telemetry, or error reporting |
12
36
 
13
37
  ## Installation
14
38
 
@@ -21,27 +45,7 @@ import { CominsTable, type CominsTableColumn } from "comins-table";
21
45
  import "comins-table/styles.css";
22
46
  ```
23
47
 
24
- React and React DOM are peer dependencies:
25
-
26
- | Package | Version |
27
- | --- | --- |
28
- | `react` | `>=18.0.0 <20.0.0` |
29
- | `react-dom` | `>=18.0.0 <20.0.0` |
30
-
31
- ## Runtime Boundary
32
-
33
- Comins Table is browser UI. Its package source does not make network requests, load remote assets, collect telemetry, or send error reports. Server rendering is not yet a supported integration contract; use an application client boundary where SSR is present.
34
-
35
- ## Supported Platforms
36
-
37
- | Surface | Support |
38
- | --- | --- |
39
- | React | `>=18.0.0 <20.0.0` |
40
- | React DOM | `>=18.0.0 <20.0.0` |
41
- | Chrome and Edge | Current stable Chromium-based releases |
42
- | Automated browser gate | Playwright-bundled Chromium |
43
- | Firefox and Safari | Not in the supported contract until Firefox and WebKit projects are added |
44
- | SSR | Client boundary required; server rendering is not currently supported |
48
+ React and React DOM are peer dependencies. Import `comins-table/styles.css` when the default table shell, themes, and built-in component skin are required.
45
49
 
46
50
  ## Quick Start
47
51
 
@@ -73,7 +77,7 @@ const columns: Array<CominsTableColumn<UserRow>> = [
73
77
 
74
78
  export function UsersTable() {
75
79
  const [data, setData] = useState<UserRow[]>([
76
- { active: true, age: 31, id: "u-1", name: "Kim", role: "Admin" },
80
+ { active: true, age: 31, id: "u-1", name: "Example user", role: "Admin" },
77
81
  ]);
78
82
 
79
83
  return (
@@ -89,11 +93,32 @@ export function UsersTable() {
89
93
  }
90
94
  ```
91
95
 
92
- ## Core Model
96
+ ## Controlled Model
97
+
98
+ Comins Table is a CSR-focused controlled component for application-owned data. The application owns the `data` array.
99
+
100
+ Only `onChangeData` requires application write-back. It emits the next flat Row array or Tree Grid node array after table-owned mutations; pass that array back through `data` to retain the change.
101
+
102
+ Selection, column layout, and sort are internal view state. `onChangeSelection`, `onChangeColumnLayout`, `onChangeSort`, and `onChangeSortModel` observe those changes so an application can coordinate or persist them externally; the table updates the corresponding view state even when a callback is omitted.
103
+
104
+ Where restoration is supported, use the supported Ref API: `setSelectedRow` and `setSelectedRows` restore Row selection by visible index, `setColumnLayout` restores layout, and `setSortState` and `clearSort` restore or clear sorting. `setSortModel` restores the complete ordered model; `getColumnLayout`, `getSortState`, and `getSortModel` read the current layout and sort state.
93
105
 
94
- Comins Table is a CSR-focused controlled component. The application owns the `data` array. Table operations such as row movement, paste, and selection emit callbacks like `onChangeData`, `onChangeSelection`, `onChangeColumnLayout`, and `onChangeSort`; the application then writes the next state back into the component.
106
+ ### Multi-column Sort
95
107
 
96
- The root export includes `CominsTable`, public types, and core helpers. Narrower helper sets are also available from stable subpaths.
108
+ Set `multiSort` to opt into ordered multi-column sorting. Normal Header click or `Enter`/`Space` keeps single sorting; hold `Shift` while using the same input to add, update, or remove one rule without replacing the others. Active Headers display their 1-based priority.
109
+
110
+ ```tsx
111
+ <CominsTable
112
+ columns={columns}
113
+ data={data}
114
+ multiSort
115
+ onChangeSortModel={(model) => saveSortModel(model)}
116
+ />
117
+ ```
118
+
119
+ `getSortModel()` and `setSortModel(model)` read and restore the full model. The existing `getSortState()`, `setSortState(rule)`, and `onChangeSort` APIs remain the single-rule compatibility surface. Two-level child Columns and Tree Grid sibling sets use the same ordered comparison rules.
120
+
121
+ ## Package Entry Points
97
122
 
98
123
  | Import | Purpose |
99
124
  | --- | --- |
@@ -103,66 +128,57 @@ The root export includes `CominsTable`, public types, and core helpers. Narrower
103
128
  | `comins-table/selection` | Selection helper subset |
104
129
  | `comins-table/styles.css` | Optional table shell, theme, and built-in component skin |
105
130
 
106
- ```ts
107
- import {
108
- addCominsRows,
109
- applyCominsColumnLayout,
110
- copyCominsCellRange,
111
- createCominsTableState,
112
- deleteCominsRows,
113
- exportCominsRowsToCsv,
114
- exportCominsRowsToJson,
115
- fillCominsCellRange,
116
- pasteCominsCellRange,
117
- queryCominsRows,
118
- selectCell,
119
- selectCellRange,
120
- selectRow,
121
- serializeCominsColumnLayout,
122
- setCominsPagination,
123
- setCominsSortState,
124
- updateCominsRows,
125
- } from "comins-table/core";
126
- ```
131
+ ## Header And Layout
127
132
 
128
- ## Features
129
-
130
- - Controlled `data` and `onChangeData` flow for application-owned state.
131
- - Column definitions with `field`, `id`, `label`, `sort`, width constraints, row/cell `props`, header configuration, and cell configuration.
132
- - Header visibility, keyboard sorting, `aria-sort`, resize, long-press column reorder, and layout persistence.
133
- - Two-level headers through `columnGroups`.
134
- - Row click, double click, keyboard callbacks, context menu callbacks, row selection, row drag reorder, row copy, and row paste.
135
- - Cell formatting, custom renderer, cell events, single-cell selection, range selection, and drag range selection.
136
- - Clipboard helpers with `props.copyable`, `props.pasteable`, and disabled guard support.
137
- - Pagination, loading and empty states, virtualized rendering, infinite scroll, and append-mode lazy loading.
138
- - Configurable Summary Row aggregation with `count`, `sum`, `avg`, `min`, `max`, custom aggregators, visible-column `colSpan`, output `format`, and row/cell styling.
139
- - Controlled Tree Grid data with `{ item, expand, children }`, initial `defaultExpandAll`, array-based ref expansion, existing component/renderer cells, recursive sibling sorting, and accessible expanders.
140
- - CSS-variable based themes, including `comins-table-theme--basic`, `--dark`, `--skyblue`, `--mint`, `--gray`, and `--orange`.
141
- - Built-in header and cell controls: `button`, `input`, `checkbox`, `radio`, `select`, `toggle`, `progress`, header `menu`, and cell `virtual-list`.
142
- - CSV and JSON export helpers.
143
-
144
- ## Props And Events
145
-
146
- | Prop | Purpose |
147
- | --- | --- |
148
- | `data` | Controlled row array. Replace it with a new array when the source data changes. |
149
- | `columns` | Leaf column definitions. `field` supports nested paths. |
150
- | `columnGroups` | Optional two-level parent header definitions. |
151
- | `getRowId` | Stable row id resolver used by selection, movement, and callbacks. |
152
- | `onChangeData` | Receives data changes from paste and row movement. |
153
- | `onChangeSelection` | Receives row, cell, and range selection changes. |
154
- | `onChangeColumnLayout` | Receives column width, order, and visibility changes. |
155
- | `onChangeSort` | Receives sort state changes. |
156
- | `onClickCell` / `onClickRow` | Receives click payloads for cell and row interactions. |
157
- | `pagination` | Controls `pageIndex` and `pageSize`. |
158
- | `loading`, `emptyComponent`, `skeletonRowCount` | Control skeleton rows, refetch overlay, and empty state content. |
159
- | `virtualized`, `"buffer-size"`, `rowHeight` | Enable and tune virtualized row rendering. |
160
- | `infiniteScroll`, `infiniteScrollThreshold`, `hasMoreRows`, `loadingMore`, `onLoadMore` | Control append loading when the body viewport nears the bottom. |
161
- | `lazyLoad`, `lazyLoadBatchSize`, `lazyLoadMode`, `lazyLoadThreshold`, `onLazyLoad` | Control async append-mode data loading with `AbortSignal`. |
162
- | `summary` | Configures fixed footer aggregates, `colSpan`, `format`, `className`, and `style` by column. Tree Grid aggregates leaf items only. |
163
- | `tree`, `defaultExpandAll` | Opt into controlled `{ item, expand, children }` data and set the initial fallback expansion state. `defaultExpandAll` defaults to `true`; explicit node state wins. Tree Grid does not support pagination, lazy loading, infinite scrolling, row drag, or row-level copy/paste in V1. |
164
- | `theme` | Supplies optional `className`, inline `style`, and density settings. |
165
- | `rowProps` | Supplies row class, style, disabled, and `rowProps.draggable` behavior. |
133
+ Sortable headers support pointer and keyboard activation and expose `aria-sort`. Columns support width constraints and resize interactions.
134
+
135
+ A left-button mouse interaction activates column movement after a 6-pixel horizontal drag, provided horizontal movement remains greater than vertical movement. The source becomes a source placeholder while a ghost and target marker show the proposed move. Pointer Up commits only over a valid target; vertical intent, pointer cancellation, `Escape`, and window blur cancel the pending move. Non-mouse pointers retain one-second long-press compatibility. Parent header groups move their children as one block.
136
+
137
+ Use `getColumnLayout()` and `setColumnLayout()` through the Ref API, or `serializeCominsColumnLayout()` and `applyCominsColumnLayout()` from `comins-table/core`, to persist and restore order, widths, and visibility.
138
+
139
+ ## Rows, Cells, And Selection
140
+
141
+ Rows expose click, double-click, keyboard, and context-menu callbacks. Cells expose the corresponding Cell callbacks plus `format`, `renderer`, and props hooks.
142
+
143
+ A normal Row interaction selects one Row, `Ctrl`/`Cmd` toggles a Row, and `Shift` extends the visible Row range from the selection anchor. Cell selection supports a single Cell, `Ctrl`/`Cmd` multi-selection, and `Shift` or pointer-drag ranges. Built-in component interactions remain isolated from `onClickCell` and `onClickRow` callback payloads so component actions do not also trigger the owning Cell or Row action.
144
+
145
+ ## Virtualization And Loading
146
+
147
+ Set `virtualized`, `rowHeight`, and `"buffer-size"` for fixed-height windowed rendering. The performance Playground includes a tested 100,000-row route while keeping only the current window and buffer mounted.
148
+
149
+ `infiniteScroll` requests application-owned append loading near the body viewport boundary. `lazyLoad` supports asynchronous append-mode batches with an `AbortSignal`. When `loading` is true, an empty table renders skeleton Rows and a populated table keeps its Rows visible under a loading overlay. `emptyComponent` controls the no-data content.
150
+
151
+ ## Summary Row
152
+
153
+ See the [Summary Row guide](https://github.com/kim1124/comins-table/blob/main/docs/user/18-summary-row.md) and run the [`/examples/summary-row`](http://127.0.0.1:4002/examples/summary-row) Playground route.
154
+
155
+ Configure `summary.columns` with built-in `count`, `sum`, `avg`, `min`, and `max` aggregation or a custom aggregator. The object form supports visible-column `colSpan`, post-aggregation `format`, and per-cell `className` and `style`; `summary.className` and `summary.style` apply to the footer Row.
156
+
157
+ ## Tree Grid
158
+
159
+ See the [Tree Grid guide](https://github.com/kim1124/comins-table/blob/main/docs/user/17-tree-grid.md) and run the [`/examples/tree-grid`](http://127.0.0.1:4002/examples/tree-grid) Playground route.
160
+
161
+ Set `tree` and provide controlled `{ item, expand, children }` nodes. `defaultExpandAll` supplies the initial fallback expansion state and defaults to `true`; explicit node state wins. `expand(nodeIds?)` and `fold(nodeIds?)` update multiple node ids, while an omitted argument targets every branch and an empty array is a no-op. Descendant-only expansion is blocked while an ancestor remains folded unless both ids are included in the same call.
162
+
163
+ Tree Grid reuses `cell.components` and `cell.renderer`, so component cells and custom React renderers work against each node's `item`. The Tree Grid Playground includes an exactly 10,000-node virtual example.
164
+
165
+ ## Components And Renderers
166
+
167
+ Cell components include `button`, `input`, `checkbox`, `radio`, `select`, `toggle`, `progress`, and `virtual-list`; Header components also support `menu`. Use `cell.renderer` or `header.renderer` when the built-in component types are not sufficient.
168
+
169
+ Virtual List Item activation follows the normal Row selection modifiers. More selects its owning Row exclusively before expanding the virtualized list. Search is available only while exactly one Row is selected. Keyboard activation keeps the More button focused after expansion. Item and More actions remain isolated from the Row and Cell click callbacks.
170
+
171
+ ## Clipboard And Export
172
+
173
+ `copyCominsRow`, `copyCominsCell`, and `copyCominsCellRange` read Row or Cell selections. `pasteCominsRow`, `pasteCominsCell`, and `pasteCominsCellRange` apply clipboard data while respecting `props.copyable`, `props.pasteable`, and disabled guards. `fillCominsCellRange` remains a framework-independent core helper; no visual fill handle is presented as shipped UI.
174
+
175
+ Use `exportCominsRowsToCsv` and `exportCominsRowsToJson` with the exact rows and export columns the application wants to serialize. Export remains independent of visible pagination, filtering, and selection unless the application passes those rows.
176
+
177
+ ## Styling And Themes
178
+
179
+ The package stylesheet exposes module-local `--comins-table-*` CSS variables and does not apply a global reset. The six shipped theme classes are `comins-table-theme--basic`, `comins-table-theme--dark`, `comins-table-theme--skyblue`, `comins-table-theme--mint`, `comins-table-theme--gray`, and `comins-table-theme--orange`.
180
+
181
+ Use `theme.className`, `theme.style`, Row class/style hooks, Cell props, and renderer output for application-specific presentation. Keep virtualized `rowHeight` aligned with `--comins-table-row-height` when overriding height tokens.
166
182
 
167
183
  ## Ref API
168
184
 
@@ -173,6 +189,11 @@ tableRef.current?.getColumnLayout();
173
189
  tableRef.current?.setColumnLayout(savedLayout);
174
190
  tableRef.current?.getSortState();
175
191
  tableRef.current?.setSortState({ columnId: "age", direction: "desc" });
192
+ tableRef.current?.getSortModel();
193
+ tableRef.current?.setSortModel([
194
+ { columnId: "team", direction: "asc" },
195
+ { columnId: "age", direction: "desc" },
196
+ ]);
176
197
  tableRef.current?.clearSort();
177
198
  tableRef.current?.setSelectedRow(0);
178
199
  tableRef.current?.setSelectedRows([0, 1]);
@@ -183,14 +204,7 @@ tableRef.current?.expand(); // all Tree Grid branches
183
204
  tableRef.current?.fold(); // all Tree Grid branches
184
205
  ```
185
206
 
186
- `setSelectedRow`, `setSelectedRows`, and `setMoveTargetRow` use the visible row index after current sorting and pagination are applied.
187
- `expand(nodeIds?)` and `fold(nodeIds?)` accept readonly Tree Grid node-id arrays. Omitting the array targets every branch; an empty array is a no-op. A folded ancestor blocks descendant-only expansion unless both ids are included in the same call. Flat tables ignore these methods.
188
-
189
- ## Documentation
190
-
191
- English user documentation starts at `docs/user/01-quick-start.md`. Detailed Tree Grid and Summary Row contracts are in `docs/user/17-tree-grid.md` and `docs/user/18-summary-row.md`.
192
-
193
- The previous Korean documentation is preserved under `docs/ko/` as secondary documentation while the public package moves to English-first docs.
207
+ `setSelectedRow`, `setSelectedRows`, and `setMoveTargetRow` use the visible Row index after current sorting and pagination. `getColumnLayout`, `setColumnLayout`, `getSortState`, `setSortState`, `getSortModel`, `setSortModel`, and `clearSort` read and update the current Header view state. `expand(nodeIds?)` and `fold(nodeIds?)` accept readonly Tree Grid node-id arrays; flat tables ignore them.
194
208
 
195
209
  ## Playground
196
210
 
@@ -198,7 +212,19 @@ The previous Korean documentation is preserved under `docs/ko/` as secondary doc
198
212
  npm run dev
199
213
  ```
200
214
 
201
- The playground starts at `/docs/getting-started` and includes examples for CRUD, sizing, theme, loading and empty states, headers, column groups, pagination, infinite scroll, lazy load, virtualization, cells, rows, Summary Row, Tree Grid, built-in components, selection, clipboard, context menu, and export helpers. The Tree Grid route includes a 30-node baseline and an exactly 10000-node virtualized example.
215
+ The local Playground starts at [`/docs/getting-started`](http://127.0.0.1:4002/docs/getting-started). Key routes include [`/examples/summary-row`](http://127.0.0.1:4002/examples/summary-row), [`/examples/tree-grid`](http://127.0.0.1:4002/examples/tree-grid), [`/examples/component`](http://127.0.0.1:4002/examples/component), and [`/performance/virtualization`](http://127.0.0.1:4002/performance/virtualization).
216
+
217
+ ## Documentation
218
+
219
+ Start with the [English Quick Start](https://github.com/kim1124/comins-table/blob/main/docs/user/01-quick-start.md), then browse [all English feature guides](https://github.com/kim1124/comins-table/tree/main/docs/user). The detailed [Tree Grid](https://github.com/kim1124/comins-table/blob/main/docs/user/17-tree-grid.md) and [Summary Row](https://github.com/kim1124/comins-table/blob/main/docs/user/18-summary-row.md) contracts include runnable examples and edge cases. [Korean guides](https://github.com/kim1124/comins-table/tree/main/docs/ko) are retained as secondary documentation.
220
+
221
+ Use the [source repository](https://github.com/kim1124/comins-table) for development context, review the [changelog](https://github.com/kim1124/comins-table/blob/main/CHANGELOG.md) for version history, and follow the [security policy](https://github.com/kim1124/comins-table/blob/main/SECURITY.md) for vulnerability reporting.
222
+
223
+ ## Current Boundaries
224
+
225
+ Comins Table currently ships a CSR controlled data model. Server-side Row models, Row grouping, pivoting, charts, AI assistance, remote Tree loading, hierarchy pagination, Tree Row drag, Tree Row copy/paste, Firefox, Safari, and SSR are not shipped or supported. Flat Row Expand details and master/detail layouts also remain outside the current package contract.
226
+
227
+ The visual fill handle is not shipped or supported. `fillCominsCellRange` remains available as a core helper without a drag-handle UI.
202
228
 
203
229
  ## Development
204
230
 
@@ -208,17 +234,13 @@ npm run test:run
208
234
  npm run build
209
235
  npm run test:e2e
210
236
  npm run test:perf -- --workers=1
211
- npm pack --dry-run --json
237
+ npm run test:consumer
238
+ npm run verify
239
+ npm run docs:readme-gif
212
240
  ```
213
241
 
214
- ## Release Bootstrap
215
-
216
- `comins-table` does not yet exist on the npm registry. npm cannot register trusted or staged publishing for a brand-new package, so the first public version must be published interactively by the maintainer with npm 2FA and without an automation token.
217
-
218
- After that bootstrap publication, register `kim1124/comins-table`, `publish.yml`, and the `npm` environment as the trusted publisher. Allow only `npm stage publish`, disallow token publishing, and require maintainer 2FA approval for every staged version. The repository workflow is intentionally manual and refuses non-`main` refs, mismatched versions, and missing bootstrap packages.
219
-
220
- ## Current Scope
242
+ `npm run docs:readme-gif` is a maintainer command that captures the real hidden Playground fixture and regenerates the checked-in README animation.
221
243
 
222
- Comins Table currently ships CSR table rendering, controlled data updates, row/cell selection, clipboard helpers, pagination, sorting, layout helpers, two-level headers, built-in controls, virtualized rendering, Summary Row aggregation, controlled Tree Grid rendering, loading and empty states, CSV/JSON export helpers, controlled infinite scrolling, and append-mode lazy loading.
244
+ ## Trusted Publishing
223
245
 
224
- It does not currently ship server-side row models, row grouping, pivoting, flat Row Expand detail areas, master/detail, charts integration, an AI assistant, or a drag-handle UI for Excel-like visual fill. Tree Grid V1 deliberately excludes remote tree loading, hierarchy pagination, row drag, and row-level copy/paste. The `fillCominsCellRange` core helper exists, but the drag UX remains outside the first public release.
246
+ The package bootstrap is complete. Trusted publishing for later versions uses the manual `publish.yml` OIDC trusted publisher and `npm stage publish` through the protected `npm` environment. The workflow builds one exact package artifact, verifies and scans that artifact before staging, and requires maintainer approval before public publication. Token-based publication is not part of this release path.
@@ -0,0 +1,9 @@
1
+ export declare const COMINS_COLUMN_MOUSE_DRAG_THRESHOLD = 6;
2
+ export type CominsColumnMouseIntent = "activate" | "cancel" | "pending";
3
+ export declare function getCominsColumnMouseIntent({ clientX, clientY, startX, startY, }: {
4
+ clientX: number;
5
+ clientY: number;
6
+ startX: number;
7
+ startY: number;
8
+ }): CominsColumnMouseIntent;
9
+ //# sourceMappingURL=column-pointer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-pointer.d.ts","sourceRoot":"","sources":["../src/column-pointer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExE,wBAAgB,0BAA0B,CAAC,EACzC,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,GACP,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,uBAAuB,CAa1B"}
@@ -1,5 +1,11 @@
1
1
  import type React from "react";
2
2
  import type { CominsCellComponentConfig, CominsCellComponentPayload, CominsHeaderComponentConfig, CominsHeaderComponentPayload } from "./core";
3
- export declare function renderCominsBuiltInComponent<TData, TValue>(component: CominsCellComponentConfig<TData, TValue>, payload: CominsCellComponentPayload<TData, TValue>): React.ReactNode;
4
- export declare function renderCominsBuiltInComponent<TData, TValue>(component: CominsHeaderComponentConfig<TData, TValue>, payload: CominsHeaderComponentPayload<TData, TValue>): React.ReactNode;
3
+ export type CominsBuiltInComponentInteraction = {
4
+ requestRowSelection?: (request: {
5
+ event: React.KeyboardEvent<HTMLButtonElement> | React.MouseEvent<HTMLButtonElement>;
6
+ mode: "exclusive" | "row-click";
7
+ }) => boolean;
8
+ };
9
+ export declare function renderCominsBuiltInComponent<TData, TValue>(component: CominsCellComponentConfig<TData, TValue>, payload: CominsCellComponentPayload<TData, TValue>, interaction?: CominsBuiltInComponentInteraction): React.ReactNode;
10
+ export declare function renderCominsBuiltInComponent<TData, TValue>(component: CominsHeaderComponentConfig<TData, TValue>, payload: CominsHeaderComponentPayload<TData, TValue>, interaction?: CominsBuiltInComponentInteraction): React.ReactNode;
5
11
  //# sourceMappingURL=component-renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-renderer.d.ts","sourceRoot":"","sources":["../src/component-renderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EACV,yBAAyB,EACzB,0BAA0B,EAG1B,2BAA2B,EAC3B,4BAA4B,EAE7B,MAAM,QAAQ,CAAC;AAivBhB,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EACxD,SAAS,EAAE,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,EACnD,OAAO,EAAE,0BAA0B,CAAC,KAAK,EAAE,MAAM,CAAC,GACjD,KAAK,CAAC,SAAS,CAAC;AACnB,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EACxD,SAAS,EAAE,2BAA2B,CAAC,KAAK,EAAE,MAAM,CAAC,EACrD,OAAO,EAAE,4BAA4B,CAAC,KAAK,EAAE,MAAM,CAAC,GACnD,KAAK,CAAC,SAAS,CAAC"}
1
+ {"version":3,"file":"component-renderer.d.ts","sourceRoot":"","sources":["../src/component-renderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EACV,yBAAyB,EACzB,0BAA0B,EAG1B,2BAA2B,EAC3B,4BAA4B,EAE7B,MAAM,QAAQ,CAAC;AA4vBhB,MAAM,MAAM,iCAAiC,GAAG;IAC9C,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC9B,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QACpF,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;KACjC,KAAK,OAAO,CAAC;CACf,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EACxD,SAAS,EAAE,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,EACnD,OAAO,EAAE,0BAA0B,CAAC,KAAK,EAAE,MAAM,CAAC,EAClD,WAAW,CAAC,EAAE,iCAAiC,GAC9C,KAAK,CAAC,SAAS,CAAC;AACnB,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EACxD,SAAS,EAAE,2BAA2B,CAAC,KAAK,EAAE,MAAM,CAAC,EACrD,OAAO,EAAE,4BAA4B,CAAC,KAAK,EAAE,MAAM,CAAC,EACpD,WAAW,CAAC,EAAE,iCAAiC,GAC9C,KAAK,CAAC,SAAS,CAAC"}
package/dist/core.d.ts CHANGED
@@ -11,6 +11,7 @@ export type CominsSortState = {
11
11
  columnId: string;
12
12
  direction: CominsSortDirection;
13
13
  };
14
+ export type CominsSortModel = readonly CominsSortState[];
14
15
  export type CominsCellFormatParams<TData, TValue = unknown> = {
15
16
  column: CominsTableRuntimeColumn<TData, TValue>;
16
17
  row: TData;
@@ -79,8 +80,10 @@ export type CominsHeaderComponentPayload<TData, TValue = unknown> = {
79
80
  width?: number;
80
81
  };
81
82
  sort: {
83
+ count: number;
82
84
  direction: CominsSortDirection | null;
83
85
  enabled: boolean;
86
+ priority: number | null;
84
87
  };
85
88
  };
86
89
  export type CominsClipboardGuard<TData, TValue = unknown> = boolean | ((params: CominsCellComponentPayload<TData, TValue>) => boolean);
@@ -285,6 +288,7 @@ export type CominsTableState<TData> = {
285
288
  selection: CominsSelectionState;
286
289
  showHeader: boolean;
287
290
  sort: CominsSortState | null;
291
+ sortModel: CominsSortModel;
288
292
  theme: CominsTableTheme;
289
293
  };
290
294
  export type CominsTableStateInput<TData> = {
@@ -296,6 +300,7 @@ export type CominsTableStateInput<TData> = {
296
300
  rows: readonly TData[];
297
301
  showHeader?: boolean;
298
302
  sort?: CominsSortState | null;
303
+ sortModel?: CominsSortModel;
299
304
  theme?: CominsTableTheme;
300
305
  };
301
306
  export type CominsRowUpdate<TData> = {
@@ -394,7 +399,7 @@ export type CominsFillCellRangeOptions = {
394
399
  source: CominsCellAddress;
395
400
  target: CominsCellRange;
396
401
  };
397
- export declare function createCominsTableState<TData>({ columnLayout, columnGroups, columns, getRowId, pagination, rows, showHeader, sort, theme, }: CominsTableStateInput<TData>): CominsTableState<TData>;
402
+ export declare function createCominsTableState<TData>({ columnLayout, columnGroups, columns, getRowId, pagination, rows, showHeader, sort, sortModel, theme, }: CominsTableStateInput<TData>): CominsTableState<TData>;
398
403
  export declare function queryCominsRows<TData>(state: CominsTableState<TData>, predicate?: (row: TData, index: number) => boolean): TData[];
399
404
  export declare function replaceCominsRows<TData>(state: CominsTableState<TData>, rows: readonly TData[]): CominsTableState<TData>;
400
405
  export declare function addCominsRows<TData>(state: CominsTableState<TData>, rows: readonly TData[]): CominsTableState<TData>;
@@ -413,6 +418,7 @@ export declare function setCominsTableTheme<TData>(state: CominsTableState<TData
413
418
  selection: CominsSelectionState;
414
419
  showHeader: boolean;
415
420
  sort: CominsSortState | null;
421
+ sortModel: CominsSortModel;
416
422
  theme: {
417
423
  className?: string;
418
424
  density?: CominsTableDensity;
@@ -431,6 +437,7 @@ export declare function setCominsHeaderVisible<TData>(state: CominsTableState<TD
431
437
  rows: TData[];
432
438
  selection: CominsSelectionState;
433
439
  sort: CominsSortState | null;
440
+ sortModel: CominsSortModel;
434
441
  theme: CominsTableTheme;
435
442
  showHeader: boolean;
436
443
  };
@@ -446,42 +453,16 @@ export declare function setCominsPagination<TData>(state: CominsTableState<TData
446
453
  selection: CominsSelectionState;
447
454
  showHeader: boolean;
448
455
  sort: CominsSortState | null;
456
+ sortModel: CominsSortModel;
449
457
  theme: CominsTableTheme;
450
458
  pagination: {
451
459
  pageIndex: number;
452
460
  pageSize: number;
453
461
  };
454
462
  };
455
- export declare function setCominsSortState<TData>(state: CominsTableState<TData>, sort: CominsSortState | null): {
456
- columnOrder: string[];
457
- columnGroups: CominsTableRuntimeColumnGroup[];
458
- columnGroupState: Record<string, CominsColumnGroupRuntimeState>;
459
- columns: CominsTableRuntimeColumn<TData, unknown>[];
460
- columnState: Record<string, CominsColumnRuntimeState>;
461
- getRowId: (row: TData, index: number) => CominsRowId;
462
- pagination: CominsPaginationState;
463
- rowIds: CominsRowId[];
464
- rows: TData[];
465
- selection: CominsSelectionState;
466
- showHeader: boolean;
467
- theme: CominsTableTheme;
468
- sort: CominsSortState | null;
469
- };
470
- export declare function clearCominsSortState<TData>(state: CominsTableState<TData>): {
471
- columnOrder: string[];
472
- columnGroups: CominsTableRuntimeColumnGroup[];
473
- columnGroupState: Record<string, CominsColumnGroupRuntimeState>;
474
- columns: CominsTableRuntimeColumn<TData, unknown>[];
475
- columnState: Record<string, CominsColumnRuntimeState>;
476
- getRowId: (row: TData, index: number) => CominsRowId;
477
- pagination: CominsPaginationState;
478
- rowIds: CominsRowId[];
479
- rows: TData[];
480
- selection: CominsSelectionState;
481
- showHeader: boolean;
482
- theme: CominsTableTheme;
483
- sort: CominsSortState | null;
484
- };
463
+ export declare function setCominsSortState<TData>(state: CominsTableState<TData>, sort: CominsSortState | null): CominsTableState<TData>;
464
+ export declare function setCominsSortModel<TData>(state: CominsTableState<TData>, sortModel: CominsSortModel): CominsTableState<TData>;
465
+ export declare function clearCominsSortState<TData>(state: CominsTableState<TData>): CominsTableState<TData>;
485
466
  export declare function setCominsColumnWidth<TData>(state: CominsTableState<TData>, columnId: string, width: number): {
486
467
  columnOrder: string[];
487
468
  columnGroups: CominsTableRuntimeColumnGroup[];
@@ -494,6 +475,7 @@ export declare function setCominsColumnWidth<TData>(state: CominsTableState<TDat
494
475
  selection: CominsSelectionState;
495
476
  showHeader: boolean;
496
477
  sort: CominsSortState | null;
478
+ sortModel: CominsSortModel;
497
479
  theme: CominsTableTheme;
498
480
  columnState: {
499
481
  [x: string]: CominsColumnRuntimeState | {
@@ -514,6 +496,7 @@ export declare function setCominsColumnHidden<TData>(state: CominsTableState<TDa
514
496
  selection: CominsSelectionState;
515
497
  showHeader: boolean;
516
498
  sort: CominsSortState | null;
499
+ sortModel: CominsSortModel;
517
500
  theme: CominsTableTheme;
518
501
  columnState: {
519
502
  [x: string]: CominsColumnRuntimeState | {
@@ -537,6 +520,7 @@ export declare function applyCominsColumnLayout<TData>(state: CominsTableState<T
537
520
  selection: CominsSelectionState;
538
521
  showHeader: boolean;
539
522
  sort: CominsSortState | null;
523
+ sortModel: CominsSortModel;
540
524
  theme: CominsTableTheme;
541
525
  columnOrder: string[];
542
526
  columnGroupState: Record<string, CominsColumnGroupRuntimeState>;
@@ -554,6 +538,7 @@ export declare function selectRow<TData>(state: CominsTableState<TData>, rowId:
554
538
  rows: TData[];
555
539
  showHeader: boolean;
556
540
  sort: CominsSortState | null;
541
+ sortModel: CominsSortModel;
557
542
  theme: CominsTableTheme;
558
543
  selection: {
559
544
  cell: CominsCellAddress | null;
@@ -573,6 +558,7 @@ export declare function selectRows<TData>(state: CominsTableState<TData>, rowIds
573
558
  rows: TData[];
574
559
  showHeader: boolean;
575
560
  sort: CominsSortState | null;
561
+ sortModel: CominsSortModel;
576
562
  theme: CominsTableTheme;
577
563
  selection: {
578
564
  cell: CominsCellAddress | null;
@@ -592,6 +578,7 @@ export declare function selectCell<TData>(state: CominsTableState<TData>, cell:
592
578
  rows: TData[];
593
579
  showHeader: boolean;
594
580
  sort: CominsSortState | null;
581
+ sortModel: CominsSortModel;
595
582
  theme: CominsTableTheme;
596
583
  selection: {
597
584
  rowIds: CominsRowId[];
@@ -611,6 +598,7 @@ export declare function selectCellRange<TData>(state: CominsTableState<TData>, r
611
598
  rows: TData[];
612
599
  showHeader: boolean;
613
600
  sort: CominsSortState | null;
601
+ sortModel: CominsSortModel;
614
602
  theme: CominsTableTheme;
615
603
  selection: {
616
604
  rowIds: CominsRowId[];
@@ -630,6 +618,7 @@ export declare function clearCominsCellRange<TData>(state: CominsTableState<TDat
630
618
  rows: TData[];
631
619
  showHeader: boolean;
632
620
  sort: CominsSortState | null;
621
+ sortModel: CominsSortModel;
633
622
  theme: CominsTableTheme;
634
623
  selection: {
635
624
  cell: CominsCellAddress | null;
@@ -649,6 +638,7 @@ export declare function clearCominsSelection<TData>(state: CominsTableState<TDat
649
638
  rows: TData[];
650
639
  showHeader: boolean;
651
640
  sort: CominsSortState | null;
641
+ sortModel: CominsSortModel;
652
642
  theme: CominsTableTheme;
653
643
  selection: CominsSelectionState;
654
644
  };