@iyulab/flex-table 0.61.0 → 0.63.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 +58 -0
- package/README.md +60 -4
- package/dist/array/index.js +2 -2
- package/dist/clipboard/clipboard.d.ts +11 -0
- package/dist/core/cell-value.d.ts +13 -0
- package/dist/events.d.ts +3 -4
- package/dist/export/delimited-reader.d.ts +11 -0
- package/dist/export/export.d.ts +11 -2
- package/dist/export/import.d.ts +30 -0
- package/dist/export/values.d.ts +17 -0
- package/dist/{fetch-all-J37bOtgc.js → fetch-all-DkdNzWrF.js} +22 -19
- package/dist/{flex-table-BD_T3SqO.js → flex-table-BufHlQ2v.js} +781 -764
- package/dist/flex-table.d.ts +14 -7
- package/dist/flex-table.js +4 -3
- package/dist/index.d.ts +3 -1
- package/dist/{locale-D9g0ksXq.js → locale-Covm8PfH.js} +4 -0
- package/dist/locale.d.ts +1 -1
- package/dist/models/types.d.ts +11 -0
- package/dist/odata/index.js +2 -2
- package/dist/odata/query.d.ts +6 -0
- package/dist/odata/source.d.ts +7 -0
- package/dist/react.js +4 -4
- package/dist/sorting-BJszwEHw.js +75 -0
- package/dist/{source-DNPtWmC3.js → source-dm6qXFh1.js} +9 -3
- package/dist/{view-BtoXdUGF.js → view-DuDIMoXV.js} +2 -2
- package/package.json +2 -2
- package/skills/iyulab-flex-table/references/api.md +8 -5
- package/skills/iyulab-flex-table/references/react.md +2 -0
- package/dist/sorting-CjfjRxwL.js +0 -51
package/dist/flex-table.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LitElement, type PropertyValues } from 'lit';
|
|
2
2
|
import '@iyulab/components/dist/components/date-picker/UDatePicker.js';
|
|
3
3
|
import type { ExportFormat } from './export/export.js';
|
|
4
|
+
import type { ImportReport } from './export/import.js';
|
|
4
5
|
import type { CellPosition, CellRange } from './core/selection.js';
|
|
5
6
|
import type { SortCriteria } from './core/sorting.js';
|
|
6
7
|
import type { FilterPredicate } from './core/filtering.js';
|
|
@@ -11,12 +12,18 @@ import type { TemplateResult } from 'lit';
|
|
|
11
12
|
* 표 내보내기의 대상 — 선택 범위(`selectionOnly`) 또는 바깥에서 준 행(`rows`, 예: `await source.fetchAll()`). 둘은
|
|
12
13
|
* 함께 쓰지 않는다(바깥 행에는 표의 선택 범위가 없다).
|
|
13
14
|
*/
|
|
14
|
-
export type TableExportOptions = {
|
|
15
|
+
export type TableExportOptions = ({
|
|
15
16
|
selectionOnly?: boolean;
|
|
16
17
|
rows?: undefined;
|
|
17
18
|
} | {
|
|
18
19
|
rows: DataRow[];
|
|
19
20
|
selectionOnly?: undefined;
|
|
21
|
+
}) & {
|
|
22
|
+
/**
|
|
23
|
+
* CSV/TSV — start with a UTF-8 byte order mark so spreadsheet apps (Excel) read non-ASCII text correctly.
|
|
24
|
+
* Default: `true` for `exportToFile` (a file a person opens), `false` for `exportToString`/`exportToBlob`.
|
|
25
|
+
*/
|
|
26
|
+
bom?: boolean;
|
|
20
27
|
};
|
|
21
28
|
export declare class FlexTable extends LitElement {
|
|
22
29
|
static styles: import("lit").CSSResult;
|
|
@@ -375,14 +382,14 @@ export declare class FlexTable extends LitElement {
|
|
|
375
382
|
*/
|
|
376
383
|
clearComments(): void;
|
|
377
384
|
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
385
|
+
* Imports an `.xlsx`, `.csv` or `.tsv` file — the first row is the header, matched to columns by `label` or
|
|
386
|
+
* `importAliases`, and each cell is read as its column's type. Replaces `data` (undoable) and fires `data-import`.
|
|
387
|
+
* Returns the report of what came in and what did not (headers no column matched, columns the file lacks, cells
|
|
388
|
+
* that are not their column's type — those keep their text); `null` for a file type it does not read.
|
|
389
|
+
* A CSV may be separated by commas or semicolons; a leading byte-order mark is not part of the first header.
|
|
380
390
|
*/
|
|
381
|
-
importFromFile(file: File): Promise<
|
|
391
|
+
importFromFile(file: File): Promise<ImportReport | null>;
|
|
382
392
|
private _applyImportedSheet;
|
|
383
|
-
private _applyImportedRows;
|
|
384
|
-
/** Map header text → column key using exact header match (case-insensitive fallback). */
|
|
385
|
-
private _buildHeaderColumnMap;
|
|
386
393
|
private _onDragover;
|
|
387
394
|
private _onDragleave;
|
|
388
395
|
private _onDrop;
|
package/dist/flex-table.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import { a as e, c as t, i as n, n as r, o as i, r as a, s as o, t as s } from "./flex-table-
|
|
2
|
-
import { t as c } from "./locale-
|
|
3
|
-
|
|
1
|
+
import { a as e, c as t, i as n, n as r, o as i, r as a, s as o, t as s } from "./flex-table-BufHlQ2v.js";
|
|
2
|
+
import { t as c } from "./locale-Covm8PfH.js";
|
|
3
|
+
import { i as l, r as u } from "./sorting-BJszwEHw.js";
|
|
4
|
+
export { s as FlexTable, o as RowSelectionState, i as UndoStack, a as downloadBlob, r as effectiveAlign, n as exportData, e as exportDataBlob, c as flexTableLocale, u as getCellValue, t as renderCell, l as setCellValue };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { FlexTable } from './flex-table.js';
|
|
|
2
2
|
export type { TableExportOptions } from './flex-table.js';
|
|
3
3
|
export type { ColumnDefinition, ColumnType, ColumnAlign, DataRow, CellRenderer, CellEditor, CellValidator, SelectionMode, DataMode, CellStyle, ConditionalRule } from './models/types.js';
|
|
4
4
|
export { effectiveAlign } from './models/types.js';
|
|
5
|
+
export { getCellValue, setCellValue } from './core/cell-value.js';
|
|
5
6
|
export type { CellPosition, CellRange } from './core/selection.js';
|
|
6
7
|
export type { FlexTableEventMap, CellChange } from './events.js';
|
|
7
8
|
export type { SortCriteria, SortDirection } from './core/sorting.js';
|
|
@@ -9,8 +10,9 @@ export type { ColumnFilter, FilterPredicate, FilterErrorCallback } from './core/
|
|
|
9
10
|
export { RowSelectionState } from './core/row-selection.js';
|
|
10
11
|
export { UndoStack } from './core/undo.js';
|
|
11
12
|
export type { UndoAction } from './core/undo.js';
|
|
12
|
-
export type { ExportFormat } from './export/export.js';
|
|
13
|
+
export type { ExportFormat, ExportOptions } from './export/export.js';
|
|
13
14
|
export { exportData, exportDataBlob, downloadBlob } from './export/export.js';
|
|
15
|
+
export type { ImportReport } from './export/import.js';
|
|
14
16
|
export { renderCell } from './renderers/cell-renderer.js';
|
|
15
17
|
export { flexTableLocale } from './locale.js';
|
|
16
18
|
export type { FlexTableMessageKey } from './locale.js';
|
|
@@ -66,6 +66,8 @@ t.register("en", {
|
|
|
66
66
|
deleteComment: "Delete Comment",
|
|
67
67
|
booleanTrue: "True",
|
|
68
68
|
booleanFalse: "False",
|
|
69
|
+
booleanTrueWords: "yes,y",
|
|
70
|
+
booleanFalseWords: "no,n",
|
|
69
71
|
dropFileToImport: "Drop file to import (.xlsx / .csv)",
|
|
70
72
|
notANumber: "Enter a number",
|
|
71
73
|
notADate: "Enter a date as YYYY-MM-DD",
|
|
@@ -139,6 +141,8 @@ t.register("en", {
|
|
|
139
141
|
deleteComment: "메모 삭제",
|
|
140
142
|
booleanTrue: "참",
|
|
141
143
|
booleanFalse: "거짓",
|
|
144
|
+
booleanTrueWords: "예,네,yes,y",
|
|
145
|
+
booleanFalseWords: "아니오,아니요,no,n",
|
|
142
146
|
dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)",
|
|
143
147
|
notANumber: "숫자를 입력하세요",
|
|
144
148
|
notADate: "날짜를 YYYY-MM-DD 로 입력하세요",
|
package/dist/locale.d.ts
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* (아이콘 자리의 글리프)는 어느 로케일에서도 같은 것을 뜻하며, 번역하면 오히려 읽히지 않는다.
|
|
26
26
|
* 그 판단은 «번역하지 않기로 한 것»이지 «빠뜨린 것»이 아니다.
|
|
27
27
|
*/
|
|
28
|
-
export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | 'noData' | 'noMatchingData' | 'clear' | 'blankCells' | 'emptyOnly' | 'nonEmptyOnly' | 'blankAll' | 'all' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'searchPlaceholder' | 'valuePlaceholder' | 'fromPlaceholder' | 'toPlaceholder' | 'findPlaceholder' | 'findPrevious' | 'findNext' | 'matchCase' | 'wholeCell' | 'closeFind' | 'findNoResults' | 'replaceWithPlaceholder' | 'replace' | 'replaceAll' | 'findInput' | 'replaceInput' | 'filterFor' | 'filterMatchMode' | 'filterText' | 'conditionOperator' | 'conditionValue' | 'conditionJoin' | 'sortAscending' | 'sortDescending' | 'filter' | 'clearFilter' | 'hideColumn' | 'showColumn' | 'autoFitWidth' | 'wider' | 'narrower' | 'columnMenuFor' | 'columnMenuRegion' | 'copy' | 'insertRowAbove' | 'insertRowBelow' | 'deleteRow' | 'selectRow' | 'selectAllRows' | 'filterByThisValue' | 'addComment' | 'editComment' | 'deleteComment' | 'booleanTrue' | 'booleanFalse' | 'dropFileToImport' | 'notANumber' | 'notADate' | 'notADateTime' | 'notInList' | 'requestFailed' | 'networkFailed' | 'tooManyRows';
|
|
28
|
+
export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | 'noData' | 'noMatchingData' | 'clear' | 'blankCells' | 'emptyOnly' | 'nonEmptyOnly' | 'blankAll' | 'all' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'searchPlaceholder' | 'valuePlaceholder' | 'fromPlaceholder' | 'toPlaceholder' | 'findPlaceholder' | 'findPrevious' | 'findNext' | 'matchCase' | 'wholeCell' | 'closeFind' | 'findNoResults' | 'replaceWithPlaceholder' | 'replace' | 'replaceAll' | 'findInput' | 'replaceInput' | 'filterFor' | 'filterMatchMode' | 'filterText' | 'conditionOperator' | 'conditionValue' | 'conditionJoin' | 'sortAscending' | 'sortDescending' | 'filter' | 'clearFilter' | 'hideColumn' | 'showColumn' | 'autoFitWidth' | 'wider' | 'narrower' | 'columnMenuFor' | 'columnMenuRegion' | 'copy' | 'insertRowAbove' | 'insertRowBelow' | 'deleteRow' | 'selectRow' | 'selectAllRows' | 'filterByThisValue' | 'addComment' | 'editComment' | 'deleteComment' | 'booleanTrue' | 'booleanFalse' | 'booleanTrueWords' | 'booleanFalseWords' | 'dropFileToImport' | 'notANumber' | 'notADate' | 'notADateTime' | 'notInList' | 'requestFailed' | 'networkFailed' | 'tooManyRows';
|
|
29
29
|
/** 이 패키지의 chrome 문자열 묶음. 소비자가 `register()` 로 언어를 더하거나 문구를 덮을 수 있다. */
|
|
30
30
|
export declare const flexTableLocale: import("@iyulab/components/dist/utilities/Locale.js").LocaleNamespace<FlexTableMessageKey>;
|
|
31
31
|
/** 짧은 조회 별칭 — 렌더 코드가 읽히게 유지한다. */
|
package/dist/models/types.d.ts
CHANGED
|
@@ -102,6 +102,17 @@ export interface ColumnDefinition<T = DataRow> {
|
|
|
102
102
|
* - Function: custom formatter receiving (value, row, col)
|
|
103
103
|
*/
|
|
104
104
|
format?: string | ((value: unknown, row: T, col: ColumnDefinition<T>) => string);
|
|
105
|
+
/**
|
|
106
|
+
* The value export writes for this column — CSV/TSV/JSON/XLSX. Without it export writes the raw value (as
|
|
107
|
+
* `format`/`render` do not apply to export). Give it where the file should say what the list shows, e.g. a status
|
|
108
|
+
* code shown as a label: `exportValue: (v) => statusLabel(v)`. A returned `Date` becomes a date cell in XLSX.
|
|
109
|
+
*/
|
|
110
|
+
exportValue?: (value: unknown, row: T) => string | number | boolean | Date | null | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Other headers an imported file may give this column (`importFromFile`) — a template a person made says
|
|
113
|
+
* «관리 번호» where the label is «관리번호». Matched like the label: exactly, then ignoring case and surrounding spaces.
|
|
114
|
+
*/
|
|
115
|
+
importAliases?: string[];
|
|
105
116
|
/** Per-column conditional formatting rules applied during cell rendering */
|
|
106
117
|
conditionalRules?: ConditionalRule<T>[];
|
|
107
118
|
/**
|
package/dist/odata/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as e, l as t, n, r, s as i, t as a } from "../fetch-all-
|
|
2
|
-
import { t as o } from "../source-
|
|
1
|
+
import { c as e, l as t, n, r, s as i, t as a } from "../fetch-all-DkdNzWrF.js";
|
|
2
|
+
import { t as o } from "../source-dm6qXFh1.js";
|
|
3
3
|
//#region src/odata/controller.ts
|
|
4
4
|
var s = class {
|
|
5
5
|
constructor(e, t, n = {}) {
|
package/dist/odata/query.d.ts
CHANGED
|
@@ -65,7 +65,13 @@ export interface ODataQueryState {
|
|
|
65
65
|
search?: string;
|
|
66
66
|
/** odata-query 의 필터 객체(`{ IsActive: true }` 등). */
|
|
67
67
|
fixedFilter?: Record<string, unknown>;
|
|
68
|
+
/** `$expand` — 문자열(`'Customer($select=Name)'`) 또는 배열(쉼표로 잇는다). */
|
|
69
|
+
expand?: string | string[];
|
|
70
|
+
/** `$select` — 받을 속성 이름. */
|
|
71
|
+
select?: string[];
|
|
68
72
|
}
|
|
73
|
+
/** 열 키(점 경로 `Customer.Name`)를 `$orderby` 의 속성 경로(`Customer/Name`)로. */
|
|
74
|
+
export declare function orderByPath(key: string): string;
|
|
69
75
|
/**
|
|
70
76
|
* 표 상태를 OData 쿼리 문자열(`?$top=…&$skip=…&$count=true…`)로 만든다.
|
|
71
77
|
*
|
package/dist/odata/source.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ export interface ODataSourceOptions {
|
|
|
19
19
|
initialSort?: SortCriteria[];
|
|
20
20
|
/** 고정 필터. 값(직렬화)이 바뀌면 페이지가 첫 장으로 돌아간다 — 참조만 다른 같은 값은 아무 일도 없다. */
|
|
21
21
|
fixedFilter?: Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* `$expand` — 참조(navigation)를 함께 받는다: `'Customer($select=Name),Owner'` 또는 `['Customer', 'Owner']`. 열은 점 경로
|
|
24
|
+
* 키(`Customer.Name`)로 그 값을 읽고, 그 열의 서버 정렬은 `$orderby=Customer/Name` 이 된다. 페이지 읽기와 `fetchAll` 이 같은 값을 낸다.
|
|
25
|
+
*/
|
|
26
|
+
expand?: string | string[];
|
|
27
|
+
/** `$select` — 받을 속성 이름. 생략하면 `$select` 없이 전부. */
|
|
28
|
+
select?: string[];
|
|
22
29
|
/** 기본값: `window.location.origin`. 프록시/BFF 등 다른 origin 으로 요청해야 할 때 지정. */
|
|
23
30
|
baseUrl?: string;
|
|
24
31
|
/** 커스텀 fetch transport(예: 인증 헤더를 주입하는 `HttpClient` 래퍼). 기본값: 전역 `fetch`. */
|
package/dist/react.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as e } from "./flex-table-
|
|
2
|
-
import { n as t, r as n, u as r } from "./fetch-all-
|
|
3
|
-
import { t as i } from "./source-
|
|
4
|
-
import { n as a, t as o } from "./view-
|
|
1
|
+
import { t as e } from "./flex-table-BufHlQ2v.js";
|
|
2
|
+
import { n as t, r as n, u as r } from "./fetch-all-DkdNzWrF.js";
|
|
3
|
+
import { t as i } from "./source-dm6qXFh1.js";
|
|
4
|
+
import { n as a, t as o } from "./view-DuDIMoXV.js";
|
|
5
5
|
import s, { useCallback as c, useEffect as l, useMemo as u, useState as d, useSyncExternalStore as f } from "react";
|
|
6
6
|
import { createComponent as p } from "@lit/react";
|
|
7
7
|
//#region src/odata/use-odata-source.ts
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region src/core/cell-value.ts
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
if (e == null) return;
|
|
4
|
+
if (t in e || !t.includes(".")) return e[t];
|
|
5
|
+
let n = e;
|
|
6
|
+
for (let e of t.split(".")) {
|
|
7
|
+
if (typeof n != "object" || !n) return;
|
|
8
|
+
n = n[e];
|
|
9
|
+
}
|
|
10
|
+
return n;
|
|
11
|
+
}
|
|
12
|
+
function t(e, t, n) {
|
|
13
|
+
if (t in e || !t.includes(".")) {
|
|
14
|
+
e[t] = n;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let r = t.split("."), i = e;
|
|
18
|
+
for (let e of r.slice(0, -1)) {
|
|
19
|
+
let t = i[e];
|
|
20
|
+
(typeof t != "object" || !t) && (i[e] = {}), i = i[e];
|
|
21
|
+
}
|
|
22
|
+
i[r[r.length - 1]] = n;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/core/sorting.ts
|
|
26
|
+
function n(t, n, i) {
|
|
27
|
+
let a = Array.from({ length: t.length }, (e, t) => t);
|
|
28
|
+
if (n.length === 0) return a;
|
|
29
|
+
let o = /* @__PURE__ */ new Map();
|
|
30
|
+
for (let e of i) o.set(e.key, e.type ?? "text");
|
|
31
|
+
return a.sort((i, a) => {
|
|
32
|
+
for (let { key: s, direction: c } of n) {
|
|
33
|
+
let n = e(t[i], s), l = e(t[a], s), u = n == null, d = l == null;
|
|
34
|
+
if (u && d) continue;
|
|
35
|
+
if (u) return 1;
|
|
36
|
+
if (d) return -1;
|
|
37
|
+
let f = r(n, l, o.get(s) ?? "text");
|
|
38
|
+
if (f !== 0) return c === "asc" ? f : -f;
|
|
39
|
+
}
|
|
40
|
+
return i - a;
|
|
41
|
+
}), a;
|
|
42
|
+
}
|
|
43
|
+
function r(e, t, n) {
|
|
44
|
+
switch (n) {
|
|
45
|
+
case "number": {
|
|
46
|
+
let n = Number(e), r = Number(t);
|
|
47
|
+
return isNaN(n) && isNaN(r) ? 0 : isNaN(n) ? 1 : isNaN(r) ? -1 : n - r;
|
|
48
|
+
}
|
|
49
|
+
case "boolean": return !!e - +!!t;
|
|
50
|
+
case "date":
|
|
51
|
+
case "datetime": {
|
|
52
|
+
let n = new Date(e).getTime(), r = new Date(t).getTime();
|
|
53
|
+
return (isNaN(n) ? 0 : n) - (isNaN(r) ? 0 : r);
|
|
54
|
+
}
|
|
55
|
+
default: return String(e).localeCompare(String(t));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function i(e, t, n) {
|
|
59
|
+
let r = e.find((e) => e.key === t);
|
|
60
|
+
return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
|
|
61
|
+
...e,
|
|
62
|
+
direction: "desc"
|
|
63
|
+
} : e) : e.filter((e) => e.key !== t) : [...e, {
|
|
64
|
+
key: t,
|
|
65
|
+
direction: "asc"
|
|
66
|
+
}] : r ? r.direction === "asc" ? [{
|
|
67
|
+
key: t,
|
|
68
|
+
direction: "desc"
|
|
69
|
+
}] : [] : [{
|
|
70
|
+
key: t,
|
|
71
|
+
direction: "asc"
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { t as i, i as n, e as r, n as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, s as a, t as o, u as s } from "./fetch-all-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, s as a, t as o, u as s } from "./fetch-all-DkdNzWrF.js";
|
|
2
2
|
//#region src/odata/source.ts
|
|
3
3
|
function c(e, t = {}) {
|
|
4
4
|
let i = e, c = t, d = u(t.fixedFilter), f = s({
|
|
@@ -48,6 +48,8 @@ function c(e, t = {}) {
|
|
|
48
48
|
b(),
|
|
49
49
|
c.defaultOrderBy,
|
|
50
50
|
d,
|
|
51
|
+
c.expand,
|
|
52
|
+
c.select,
|
|
51
53
|
p.page,
|
|
52
54
|
p.sortCriteria,
|
|
53
55
|
p.search
|
|
@@ -82,7 +84,9 @@ function c(e, t = {}) {
|
|
|
82
84
|
sortCriteria: n,
|
|
83
85
|
defaultOrderBy: c.defaultOrderBy,
|
|
84
86
|
search: o,
|
|
85
|
-
fixedFilter: c.fixedFilter
|
|
87
|
+
fixedFilter: c.fixedFilter,
|
|
88
|
+
expand: c.expand,
|
|
89
|
+
select: c.select
|
|
86
90
|
});
|
|
87
91
|
l(`${c.baseUrl ?? window.location.origin}${i}${f}`, {
|
|
88
92
|
fetcher: u,
|
|
@@ -147,7 +151,9 @@ function c(e, t = {}) {
|
|
|
147
151
|
sortCriteria: s,
|
|
148
152
|
defaultOrderBy: c.defaultOrderBy,
|
|
149
153
|
search: u,
|
|
150
|
-
fixedFilter: c.fixedFilter
|
|
154
|
+
fixedFilter: c.fixedFilter,
|
|
155
|
+
expand: c.expand,
|
|
156
|
+
select: c.select
|
|
151
157
|
}), { rows: f } = await l(`${c.baseUrl ?? window.location.origin}${i}${d}`, {
|
|
152
158
|
fetcher: c.fetcher ?? fetch,
|
|
153
159
|
signal: t,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as e } from "./sorting-
|
|
2
|
-
import { n as t, t as n } from "./fetch-all-
|
|
1
|
+
import { t as e } from "./sorting-BJszwEHw.js";
|
|
2
|
+
import { n as t, t as n } from "./fetch-all-DkdNzWrF.js";
|
|
3
3
|
//#region src/array/view.ts
|
|
4
4
|
function r(t, { search: n, sortCriteria: r, page: i, pageSize: a, columns: o, searchFields: s }) {
|
|
5
5
|
let c = n.trim().toLowerCase(), l = c ? t.filter((e) => (s ? s(e) : Object.values(e)).some((e) => e != null && String(e).toLowerCase().includes(c))) : t, u = l;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/flex-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"description": "A minimalist, input-centric data grid web component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/flex-table.js",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"odata-query": "^8.1.0"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
|
-
"@iyulab/components": ">=2.
|
|
77
|
+
"@iyulab/components": ">=2.18.0",
|
|
78
78
|
"@lit/react": "^1.0.8",
|
|
79
79
|
"react": "^18.0.0 || ^19.0.0"
|
|
80
80
|
},
|
|
@@ -50,7 +50,7 @@ Replacing `data` with the same array reference does not trigger the clear-on-cha
|
|
|
50
50
|
|
|
51
51
|
| Field | Type | Notes |
|
|
52
52
|
|---|---|---|
|
|
53
|
-
| `key` | `string` | Property name in the row (required) |
|
|
53
|
+
| `key` | `string` | Property name in the row, or a dot path into a nested record (`'Customer.Name'`) — display, sort, filter, copy, edit, import and export all read it the same way; a property named by the whole key (`'@odata.etag'`) wins over the path (required) |
|
|
54
54
|
| `label` | `string` | Header text (required) |
|
|
55
55
|
| `type` | `ColumnType` | `'text' \| 'number' \| 'boolean' \| 'date' \| 'datetime' \| 'select'`; other strings act as text |
|
|
56
56
|
| `width` / `minWidth` | `number` | px; `minWidth` defaults to 40 |
|
|
@@ -130,14 +130,17 @@ Enter/Escape and blur-to-commit behavior.
|
|
|
130
130
|
| `undo()` / `redo()` / `clearUndoHistory()` | |
|
|
131
131
|
| `setComment(dataIndex, colKey, text)` | `null` or `''` removes; undoable |
|
|
132
132
|
| `getComment(dataIndex, colKey)` / `clearComments()` | |
|
|
133
|
-
| `importFromFile(file)` | `Promise<
|
|
133
|
+
| `importFromFile(file)` | `Promise<ImportReport \| null>`; `.xlsx`, `.csv` (comma or semicolon), `.tsv`; headers match `label` or `importAliases`; fires `data-import` with the same report — `{ count, unmatchedHeaders, missingColumns, coercionFailures }`; a cell that is not its column's type keeps its text and is reported (an unread boolean is not `false`) |
|
|
134
134
|
| `exportToString(format, { selectionOnly? } \| { rows })` | `string \| Uint8Array`; format `'csv' \| 'tsv' \| 'json' \| 'xlsx'` (xlsx returns uncompressed bytes — synchronous). `rows`: export these rows with the visible columns |
|
|
135
135
|
| `exportToBlob(format, options?)` | `Promise<Blob>` typed with the format's MIME; xlsx is DEFLATE-compressed |
|
|
136
|
-
| `exportToFile(format, filename?, options?)` | `Promise<void>` — triggers a download (xlsx compressed) |
|
|
136
|
+
| `exportToFile(format, filename?, options?)` | `Promise<void>` — triggers a download (xlsx compressed); CSV/TSV start with a UTF-8 BOM unless `{ bom: false }` |
|
|
137
137
|
|
|
138
138
|
A server-paged table holds one page. Export the list's whole result with
|
|
139
139
|
`table.exportToFile('xlsx', 'x.xlsx', { rows: await source.fetchAll() })` — never the table's own rows there.
|
|
140
|
-
Table-less: `exportDataBlob(rows, columns, format)` + `downloadBlob(blob, name)` from the root entry.
|
|
140
|
+
Table-less: `exportDataBlob(rows, columns, format, { bom? })` + `downloadBlob(blob, name)` from the root entry.
|
|
141
|
+
|
|
142
|
+
A column's `exportValue(value, row)` is what export writes for it (default: the raw value — `format`/`render` do not
|
|
143
|
+
apply). In XLSX a `date`/`datetime` column's ISO strings become date cells, at the wall-clock time the table shows.
|
|
141
144
|
|
|
142
145
|
## Events
|
|
143
146
|
|
|
@@ -173,7 +176,7 @@ cast, and the React `on*` props carry the same types.
|
|
|
173
176
|
| `fill-handle-apply` | `{ sourceRange, targetRange, cells }` |
|
|
174
177
|
| `find-replace` | `{ type: 'replace' \| 'replace-all', cells }` |
|
|
175
178
|
| `comment-change` | `{ dataIndex, id, colKey, text }` |
|
|
176
|
-
| `data-import` | `{ count }` |
|
|
179
|
+
| `data-import` | `ImportReport` — `{ count, unmatchedHeaders, missingColumns, coercionFailures }` |
|
|
177
180
|
| `undo-state-change` | `{ canUndo, canRedo }` |
|
|
178
181
|
| `context-menu` | `{ x, y, row, col, key, value, rowData }` — cancelable; `preventDefault()` suppresses the built-in menu |
|
|
179
182
|
| `header-context-menu` | `{ key, label, x, y }` |
|
|
@@ -97,6 +97,8 @@ function Orders() {
|
|
|
97
97
|
| `initialSearch` | `''` | First render only |
|
|
98
98
|
| `initialSort` | — | `SortCriteria[]`; overrides `defaultOrderBy`; `[]` means no sort |
|
|
99
99
|
| `fixedFilter` | — | odata-query filter object, always applied; value change resets to page 0 (compared by value) |
|
|
100
|
+
| `expand` | — | `$expand` string or array; columns read it with dot-path keys (`'Customer.Name'` → server sort `Customer/Name`); `fetchAll` sends it too |
|
|
101
|
+
| `select` | — | `$select` property names |
|
|
100
102
|
| `baseUrl` | `window.location.origin` | For proxy/BFF setups |
|
|
101
103
|
| `fetcher` | global `fetch` | `(input, init) => Promise<Response>`; read when each request starts |
|
|
102
104
|
| `onUnauthorized` | — | `(response) => void` on 401 only (403 surfaces as `error`); read when each request starts |
|
package/dist/sorting-CjfjRxwL.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
//#region src/core/sorting.ts
|
|
2
|
-
function e(e, n, r) {
|
|
3
|
-
let i = Array.from({ length: e.length }, (e, t) => t);
|
|
4
|
-
if (n.length === 0) return i;
|
|
5
|
-
let a = /* @__PURE__ */ new Map();
|
|
6
|
-
for (let e of r) a.set(e.key, e.type ?? "text");
|
|
7
|
-
return i.sort((r, i) => {
|
|
8
|
-
for (let { key: o, direction: s } of n) {
|
|
9
|
-
let n = e[r][o], c = e[i][o], l = n == null, u = c == null;
|
|
10
|
-
if (l && u) continue;
|
|
11
|
-
if (l) return 1;
|
|
12
|
-
if (u) return -1;
|
|
13
|
-
let d = t(n, c, a.get(o) ?? "text");
|
|
14
|
-
if (d !== 0) return s === "asc" ? d : -d;
|
|
15
|
-
}
|
|
16
|
-
return r - i;
|
|
17
|
-
}), i;
|
|
18
|
-
}
|
|
19
|
-
function t(e, t, n) {
|
|
20
|
-
switch (n) {
|
|
21
|
-
case "number": {
|
|
22
|
-
let n = Number(e), r = Number(t);
|
|
23
|
-
return isNaN(n) && isNaN(r) ? 0 : isNaN(n) ? 1 : isNaN(r) ? -1 : n - r;
|
|
24
|
-
}
|
|
25
|
-
case "boolean": return !!e - +!!t;
|
|
26
|
-
case "date":
|
|
27
|
-
case "datetime": {
|
|
28
|
-
let n = new Date(e).getTime(), r = new Date(t).getTime();
|
|
29
|
-
return (isNaN(n) ? 0 : n) - (isNaN(r) ? 0 : r);
|
|
30
|
-
}
|
|
31
|
-
default: return String(e).localeCompare(String(t));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function n(e, t, n) {
|
|
35
|
-
let r = e.find((e) => e.key === t);
|
|
36
|
-
return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
|
|
37
|
-
...e,
|
|
38
|
-
direction: "desc"
|
|
39
|
-
} : e) : e.filter((e) => e.key !== t) : [...e, {
|
|
40
|
-
key: t,
|
|
41
|
-
direction: "asc"
|
|
42
|
-
}] : r ? r.direction === "asc" ? [{
|
|
43
|
-
key: t,
|
|
44
|
-
direction: "desc"
|
|
45
|
-
}] : [] : [{
|
|
46
|
-
key: t,
|
|
47
|
-
direction: "asc"
|
|
48
|
-
}];
|
|
49
|
-
}
|
|
50
|
-
//#endregion
|
|
51
|
-
export { n, e as t };
|