@iyulab/flex-table 0.40.3 → 0.41.0
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 +41 -2
- package/README.md +23 -2
- package/dist/clipboard/clipboard.d.ts +5 -0
- package/dist/{flex-table-DvETrA1w.js → flex-table-BF46G1Uw.js} +272 -204
- package/dist/flex-table.d.ts +10 -0
- package/dist/flex-table.js +1 -1
- package/dist/locale.d.ts +1 -1
- package/dist/models/types.d.ts +11 -0
- package/dist/react.js +1 -1
- package/package.json +3 -3
- package/skills/iyulab-flex-table/SKILL.md +1 -0
- package/skills/iyulab-flex-table/references/api.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.41.0] - 2026-10-03
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`mergeRepeated` column option — a run of repeated values reads as one merged cell.** For lists of
|
|
8
|
+
child rows under a parent (order lines under an order, boxes under a shipment), the parent's columns
|
|
9
|
+
no longer repeat on every line: the value shows once, on the run's first row, the lines inside the run
|
|
10
|
+
are dropped, and the run keeps one background. `true` merges equal values (empty values never merge);
|
|
11
|
+
a function `(row, previousRow, col) => boolean` decides by any rule — e.g. merge a customer only within
|
|
12
|
+
one order. Every row keeps its own value, so sorting, filtering, copying, export and screen readers
|
|
13
|
+
see each row as before. Rows are compared in display order; the value is drawn again on the first row
|
|
14
|
+
in view and below frozen rows, so scrolling or paging through a run never hides it.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **Number entry reads a decimal comma.** The `number` cell editor and the number filter used the native
|
|
19
|
+
number input, which turns `1,5` into `15` or an empty value depending on the browser. Both are now text
|
|
20
|
+
fields with a decimal keyboard (`inputmode="decimal"`) that read numbers in the active `Locale` — `1,5`
|
|
21
|
+
is 1.5 and `1.234,5` is 1234.5 on a comma-decimal page — and the editor shows the current value with
|
|
22
|
+
that locale's decimal separator. The filter keeps what you typed while you type it and marks a condition
|
|
23
|
+
it cannot read (`aria-invalid`).
|
|
24
|
+
- **Pasting `1,5` into a number column stores 1.5.** Pasted text was read with `Number()`, so a value from a
|
|
25
|
+
comma-decimal spreadsheet stayed text (`"1,5"`) and sorted and summed wrongly. Plain notation (`1e3`) is
|
|
26
|
+
still read; text that is not a number still stays text.
|
|
27
|
+
- **The built-in editor rejects text that is not a number** in a `number` column. It fires
|
|
28
|
+
`validation-error` (`error`: "Enter a number") and keeps the old value, like a validator failure — the
|
|
29
|
+
native input never let such text through, so a text field must not store it.
|
|
30
|
+
- The strict-autocomplete error ("Value must be from the existing list") follows the `Locale` (new keys
|
|
31
|
+
`notANumber` and `notInList` in `flexTableLocale`; `ko` built in).
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- **The `@iyulab/components` peer is `>=1.54.0`** — number parsing uses its `parseNumber`.
|
|
36
|
+
|
|
37
|
+
- The optional `@lit/react` peer is `^1.0.8` (was `^1.0.0`) — the version the React entry is tested
|
|
38
|
+
with.
|
|
39
|
+
|
|
40
|
+
### Documentation
|
|
41
|
+
|
|
42
|
+
- README: the Accessibility section links the KWCAG 2.2 table in `@iyulab/components`.
|
|
43
|
+
|
|
3
44
|
## [0.40.3] - 2026-09-30
|
|
4
45
|
|
|
5
46
|
### Fixed
|
|
@@ -587,8 +628,6 @@ All notable changes to this project will be documented in this file.
|
|
|
587
628
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
588
629
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
589
630
|
|
|
590
|
-
## [Unreleased]
|
|
591
|
-
|
|
592
631
|
## [0.23.1] - 2026-08-03
|
|
593
632
|
|
|
594
633
|
### Fixed
|
package/README.md
CHANGED
|
@@ -150,6 +150,7 @@ interface ColumnDefinition {
|
|
|
150
150
|
editor?: CellEditor; // Custom cell editor: (value, row, col) => TemplateResult
|
|
151
151
|
validator?: CellValidator; // Validate before commit: (value, row, col) => string | null
|
|
152
152
|
conditionalRules?: ConditionalRule[]; // Per-cell style rules, see below
|
|
153
|
+
mergeRepeated?: boolean | ((row, previousRow, col) => boolean); // Merge runs of repeated values, see below
|
|
153
154
|
}
|
|
154
155
|
```
|
|
155
156
|
|
|
@@ -157,6 +158,8 @@ The `editor` callback must return a Lit `TemplateResult` containing an input ele
|
|
|
157
158
|
|
|
158
159
|
The `validator` callback returns `null` if valid, or an error message string. On failure, the cell shows a red border for 3 seconds and a `validation-error` event is dispatched.
|
|
159
160
|
|
|
161
|
+
A `number` column's built-in editor reads numbers the way people type them in the active `Locale` — `1,5` on a comma-decimal page is 1.5, `1.234,5` is 1234.5 — and shows the value with that locale's decimal separator. Text that is not a number is rejected the same way as a validator failure (`error` is the localized "Enter a number"). The number filter's conditions and pasted values are read the same way; pasted text that is not a number stays text.
|
|
162
|
+
|
|
160
163
|
### `format` vs `render`
|
|
161
164
|
|
|
162
165
|
Both control how a cell's raw value is displayed, but they differ in what they replace:
|
|
@@ -193,6 +196,22 @@ const columns: ColumnDefinition<Order>[] = [
|
|
|
193
196
|
|
|
194
197
|
Rules are evaluated in order and combined; later matching rules override earlier ones for overlapping style properties.
|
|
195
198
|
|
|
199
|
+
### Merging Repeated Values
|
|
200
|
+
|
|
201
|
+
A list of child rows under a parent — order lines under an order, boxes under a shipment — repeats the parent's columns on every line. `mergeRepeated` draws each run of repeated values as one merged cell: the value shows once, on the run's first row, and the lines between the run's rows are dropped.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
const columns: ColumnDefinition<OrderLine>[] = [
|
|
205
|
+
{ key: 'orderNo', label: 'Order', mergeRepeated: true },
|
|
206
|
+
// Two adjacent orders can share a customer — merge only within one order.
|
|
207
|
+
{ key: 'customer', label: 'Customer', mergeRepeated: (row, prev) => row.orderNo === prev.orderNo },
|
|
208
|
+
{ key: 'product', label: 'Product' },
|
|
209
|
+
{ key: 'qty', label: 'Qty', type: 'number' },
|
|
210
|
+
];
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Every row keeps its own value. Sorting, filtering, copying, CSV/XLSX export and screen readers see each row exactly as without merging — a filter that drops a run's first row leaves the rest of the run labelled, and an export pivots. Rows are compared in display order, so sort by the merged column (or keep the server's order) for runs to form. The value is drawn again on the first row in view and on the first row below frozen rows, so scrolling or paging through a run never hides it. With `true`, empty values (`null`, `undefined`, `''`) never merge.
|
|
214
|
+
|
|
196
215
|
## Methods
|
|
197
216
|
|
|
198
217
|
### Row Operations
|
|
@@ -209,7 +228,7 @@ Rules are evaluated in order and combined; later matching rules override earlier
|
|
|
209
228
|
| Method | Returns | Description |
|
|
210
229
|
|--------|---------|-------------|
|
|
211
230
|
| `addColumn(def, index?)` | `ColumnDefinition` | Add column at position (default: end) |
|
|
212
|
-
| `deleteColumn(key)` | `void` | Remove column + cleanup filters/sort/widths |
|
|
231
|
+
| `deleteColumn(key)` | `void` | Remove column + cleanup filters/sort/widths. Row objects keep that key's values (undo restores the column with them); delete the key from `data` yourself if you need it gone |
|
|
213
232
|
| `moveColumn(key, newIndex)` | `void` | Reorder column to target index (clamped) |
|
|
214
233
|
| `getColumnWidth(key)` | `number \| undefined` | Get internal resize width for column |
|
|
215
234
|
| `selectColumn(colIndex)` | `void` | Select entire column (range selection) |
|
|
@@ -257,7 +276,7 @@ All events use `CustomEvent` with `bubbles: true, composed: true`.
|
|
|
257
276
|
| `cell-edit-start` | `{ row, col, key, value }` | Cell editing started |
|
|
258
277
|
| `cell-edit-commit` | `{ row, col, key, oldValue, newValue }` | Cell value committed |
|
|
259
278
|
| `cell-edit-cancel` | `{ row, col }` | Cell edit cancelled (Escape) |
|
|
260
|
-
| `validation-error` | `{ row, col, key, value, error }` | Cell validator rejected value |
|
|
279
|
+
| `validation-error` | `{ row, col, key, value, error }` | Cell validator rejected value, or a `number` cell got text that is not a number |
|
|
261
280
|
|
|
262
281
|
### Data Events
|
|
263
282
|
|
|
@@ -476,6 +495,8 @@ conformance claim for the success criteria it does not list.
|
|
|
476
495
|
Not yet measured: the boolean and date filter dropdowns and the comment popup. Color contrast comes
|
|
477
496
|
from the `@iyulab/components` tokens this package reads.
|
|
478
497
|
|
|
498
|
+
For **KWCAG 2.2** (the Korean web accessibility standard), the `@iyulab/components` README has a table of all 33 check items — which are guaranteed by a test across the sibling packages, which are shared with the app, and which do not apply: [KWCAG 2.2 대응표](https://github.com/iyulab/node-components#kwcag-22-대응표).
|
|
499
|
+
|
|
479
500
|
## Usage Guide
|
|
480
501
|
|
|
481
502
|
### React
|
|
@@ -6,3 +6,8 @@ import type { ColumnDefinition, DataRow } from '../models/types.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function copyToClipboard(data: DataRow[], columns: ColumnDefinition[], range: CellRange): string;
|
|
8
8
|
export declare function parseValueForColumn(raw: string, col: ColumnDefinition): unknown;
|
|
9
|
+
/**
|
|
10
|
+
* A number as a person edits it: the active locale's decimal separator, no grouping, every digit
|
|
11
|
+
* kept (`1234.5` → `1234,5` on a German page). The inverse is {@link parseValueForColumn}.
|
|
12
|
+
*/
|
|
13
|
+
export declare function editableNumber(value: number): string;
|