@iyulab/flex-table 0.46.0 → 0.47.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 +27 -0
- package/README.md +8 -3
- package/dist/array/types.d.ts +2 -1
- package/dist/core/source-error.d.ts +35 -0
- package/dist/{flex-table-DIQhqj12.js → flex-table-h2noRChg.js} +177 -163
- package/dist/flex-table.d.ts +6 -0
- package/dist/flex-table.js +1 -1
- package/dist/odata/types.d.ts +6 -1
- package/dist/react.d.ts +1 -0
- package/dist/react.js +82 -55
- package/package.json +2 -1
- package/skills/iyulab-flex-table/SKILL.md +1 -1
- package/skills/iyulab-flex-table/references/react.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.47.0] - 2026-10-05
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Breaking: `error` from `useODataSource` and `useArraySource` is a structured failure, not a
|
|
8
|
+
string** — `SourceError | null`, where `SourceError` is `{ message, status?, code?, details?, body? }`
|
|
9
|
+
(exported from `@iyulab/flex-table/react` with `SourceErrorDetail`). The message alone lost which
|
|
10
|
+
failure it was, so an app could not tell a 403 the server marked with its own code (for example
|
|
11
|
+
"password change required") from any other 403, or a 404 from a 409, without wrapping `fetcher`
|
|
12
|
+
to watch the status. Now `status` is the HTTP status, `code` the server's rejection code (OData
|
|
13
|
+
`error.code`), `details` the OData `error.details` entries, and `body` the parsed response (or its
|
|
14
|
+
text). A failure with no response — a network error, or a `@odata.nextLink` the hook refused — has
|
|
15
|
+
a `message` only. The message itself is unchanged.
|
|
16
|
+
|
|
17
|
+
Migration: render `error.message` where you rendered `error`
|
|
18
|
+
(`{source.error && <p role="alert">{source.error.message}</p>}`), and compare `error?.message`
|
|
19
|
+
where you compared the string.
|
|
20
|
+
|
|
21
|
+
- **Date and datetime column filters use `u-date-picker`** for their From and To bounds, like the
|
|
22
|
+
cell editor since 0.46. The native date inputs they replace showed the browser's UI language
|
|
23
|
+
(`10/02/2026` in an English browser) while the table shows ISO; the bounds now read and show
|
|
24
|
+
`YYYY-MM-DD` (`YYYY-MM-DD HH:mm`) everywhere, with a calendar beside each. The bounds are labelled
|
|
25
|
+
(**From**, **To**), each calendar stops at the other bound, and either bound may still stay empty.
|
|
26
|
+
A bound now applies when it is committed — Enter, leaving the box, or a day picked in the calendar —
|
|
27
|
+
rather than on every keystroke. While a calendar is open, Escape closes the calendar and the next
|
|
28
|
+
Escape closes the filter. Opening the filter from the column menu focuses the From bound.
|
|
29
|
+
|
|
3
30
|
## [0.46.0] - 2026-10-05
|
|
4
31
|
|
|
5
32
|
### Changed
|
package/README.md
CHANGED
|
@@ -684,8 +684,13 @@ button is highlighted while its column has an active filter.
|
|
|
684
684
|
- **text**: case-insensitive substring search
|
|
685
685
|
- **number**: min/max range inputs
|
|
686
686
|
- **boolean**: All / True / False select
|
|
687
|
-
- **date**:
|
|
688
|
-
-
|
|
687
|
+
- **date**: **From** and **To** `u-date-picker`s (`@iyulab/components`) — the cell editor's control, so the
|
|
688
|
+
bounds read and show `YYYY-MM-DD` in every browser language, with a calendar beside each. Either
|
|
689
|
+
bound may stay empty; the end day is inclusive, and each calendar stops at the other bound.
|
|
690
|
+
- **datetime**: the same pickers with a time (`YYYY-MM-DD HH:mm`)
|
|
691
|
+
|
|
692
|
+
A bound applies when it is committed — Enter, leaving the box, or a day picked in its calendar. While a
|
|
693
|
+
calendar is open, Escape closes the calendar; the next Escape closes the filter.
|
|
689
694
|
|
|
690
695
|
Filters set via the UI and the programmatic API (`setFilter()`) share the same filter state. Filter dropdowns automatically flip upward when near the viewport bottom.
|
|
691
696
|
|
|
@@ -787,7 +792,7 @@ The hook returns:
|
|
|
787
792
|
|---|---|
|
|
788
793
|
| `data` / `totalCount` | Current page rows and the server's total (`@odata.count`). When the server pages its response (`@odata.nextLink`, e.g. a page size smaller than `pageSize`), the hook follows the link until the page is filled; a link outside the request's origin, or one that returns to a page already read, is reported through `error` instead of showing a short page |
|
|
789
794
|
| `loading` | A request is in flight |
|
|
790
|
-
| `error` |
|
|
795
|
+
| `error` | The last failed request, or `null`: `{ message, status?, code?, details?, body? }`. **Render `error.message`** — a failed request otherwise leaves the grid silently empty. Branch on `status` (HTTP), `code` (the server's rejection code, OData `error.code`) and `details` (OData `error.details`); `body` is the parsed response (or its text). A failure with no response — a network error, or a `@odata.nextLink` the hook refused — has a `message` only |
|
|
791
796
|
| `page` / `setPage` | Zero-based page index |
|
|
792
797
|
| `sortCriteria` / `onSortChange` | Bind `onSortChange` to the table's `sort-change` event |
|
|
793
798
|
| `search` / `setSearch` | Current search term and its setter (resets to page 0) |
|
package/dist/array/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SortCriteria } from '../core/sorting.js';
|
|
2
|
+
import type { SourceError } from '../core/source-error.js';
|
|
2
3
|
export interface UseArraySourceOptions<T> {
|
|
3
4
|
/** 페이지당 행 수. `useODataSource`와 동일 기본값. */
|
|
4
5
|
pageSize?: number;
|
|
@@ -36,7 +37,7 @@ export interface UseArraySourceResult<T> {
|
|
|
36
37
|
/** 항상 `false` — 로컬 배열은 동기 처리라 로딩 상태가 없다. `useODataSource`와의 반환 형태 동일성을 위해 유지. */
|
|
37
38
|
loading: boolean;
|
|
38
39
|
/** 항상 `null` — 로컬 배열 처리는 실패하지 않는다. 위와 같은 이유로 유지. */
|
|
39
|
-
error:
|
|
40
|
+
error: SourceError | null;
|
|
40
41
|
page: number;
|
|
41
42
|
setPage: (page: number) => void;
|
|
42
43
|
sortCriteria: SortCriteria[];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** OData v4 오류 봉투의 `error.details` 항목 — 필드별 검증 실패 상세. */
|
|
2
|
+
export interface SourceErrorDetail {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
target?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* 데이터 소스 훅(`useODataSource`/`useArraySource`)의 실패 값.
|
|
9
|
+
*
|
|
10
|
+
* 문자열 하나가 아니라 구조로 싣는 이유: 소비자는 «어떤 실패인가» 로 갈라야 한다 — 403 중에서도
|
|
11
|
+
* 서버가 코드로 구분한 거절(«비밀번호를 바꿔야 한다»), 404(지워진 행), 409(동시성), 429(제한).
|
|
12
|
+
* 메시지만 남기면 그 정보가 소스 경계에서 사라지고, 소비자는 전송(`fetcher`)을 감싸 상태를
|
|
13
|
+
* 엿보는 것 말고는 길이 없다.
|
|
14
|
+
*/
|
|
15
|
+
export interface SourceError {
|
|
16
|
+
/** 보여 줄 문장 — 서버가 준 메시지가 있으면 그것, 없으면 `Request failed (<status>)`. */
|
|
17
|
+
message: string;
|
|
18
|
+
/** HTTP 상태. 응답이 없던 실패(네트워크 오류 · `@odata.nextLink` 검사)에는 없다. */
|
|
19
|
+
status?: number;
|
|
20
|
+
/** 서버가 정한 거절 코드 — OData 오류 봉투의 `error.code`(또는 최상위 `code`). */
|
|
21
|
+
code?: string;
|
|
22
|
+
/** 오류 봉투의 `error.details` 중 `code`·`message` 가 둘 다 문자열인 항목. */
|
|
23
|
+
details?: SourceErrorDetail[];
|
|
24
|
+
/** 응답 본문 — JSON 이면 파싱한 값, 아니면 텍스트. 비어 있으면 없다. */
|
|
25
|
+
body?: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** 실패 응답을 `SourceError` 로 읽는다. 본문을 읽을 수 없어도 상태와 기본 문장은 남긴다. */
|
|
28
|
+
export declare function readFailedResponse(res: Response): Promise<SourceError>;
|
|
29
|
+
/** 실패 응답을 실어 나르는 내부 예외 — `catch` 가 상태를 잃지 않고 `SourceError` 를 꺼낸다. */
|
|
30
|
+
export declare class SourceRequestError extends Error {
|
|
31
|
+
readonly failure: SourceError;
|
|
32
|
+
constructor(failure: SourceError);
|
|
33
|
+
}
|
|
34
|
+
/** 잡힌 예외를 `SourceError` 로 — 응답이 있던 실패는 그 구조 그대로, 나머지는 메시지만. */
|
|
35
|
+
export declare function toSourceError(err: unknown): SourceError;
|
|
@@ -567,6 +567,19 @@ var v = r`
|
|
|
567
567
|
width: 50%;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
+
/* Date bounds stack: side by side, half of the dropdown is narrower than a date (and far narrower
|
|
571
|
+
than a date and a time) plus the calendar button. */
|
|
572
|
+
.ft-filter-range-dates {
|
|
573
|
+
flex-direction: column;
|
|
574
|
+
gap: 6px;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.ft-filter-date {
|
|
578
|
+
display: block;
|
|
579
|
+
width: 100%;
|
|
580
|
+
min-width: 0;
|
|
581
|
+
}
|
|
582
|
+
|
|
570
583
|
.ft-filter-actions {
|
|
571
584
|
margin-top: 6px;
|
|
572
585
|
text-align: right;
|
|
@@ -1464,19 +1477,19 @@ function N(e, t) {
|
|
|
1464
1477
|
default: return e;
|
|
1465
1478
|
}
|
|
1466
1479
|
}
|
|
1467
|
-
function
|
|
1480
|
+
function se(e) {
|
|
1468
1481
|
let t = String(e);
|
|
1469
1482
|
if (!Number.isFinite(e) || t.includes("e")) return t;
|
|
1470
1483
|
let n = new Intl.NumberFormat(l.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
|
|
1471
1484
|
return n && n !== "." ? t.replace(".", n) : t;
|
|
1472
1485
|
}
|
|
1473
|
-
function
|
|
1486
|
+
function ce(e) {
|
|
1474
1487
|
if (e == null || e === "") return "";
|
|
1475
1488
|
if (e instanceof Date) return Number.isNaN(e.getTime()) ? "" : `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
|
|
1476
1489
|
let t = String(e), n = /^(\d{4}-\d{2}-\d{2})(?:$|T)/.exec(t);
|
|
1477
1490
|
return n ? n[1] : t;
|
|
1478
1491
|
}
|
|
1479
|
-
function
|
|
1492
|
+
function le(e) {
|
|
1480
1493
|
if (e == null || e === "") return "";
|
|
1481
1494
|
let t = e instanceof Date ? "" : String(e), n = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(t);
|
|
1482
1495
|
if (n) return `${n[1]} ${n[2]}`;
|
|
@@ -1487,7 +1500,7 @@ function ce(e) {
|
|
|
1487
1500
|
}
|
|
1488
1501
|
//#endregion
|
|
1489
1502
|
//#region src/export/xlsx-writer.ts
|
|
1490
|
-
var
|
|
1503
|
+
var ue = (() => {
|
|
1491
1504
|
let e = /* @__PURE__ */ new Uint32Array(256);
|
|
1492
1505
|
for (let t = 0; t < 256; t++) {
|
|
1493
1506
|
let n = t;
|
|
@@ -1496,23 +1509,23 @@ var le = (() => {
|
|
|
1496
1509
|
}
|
|
1497
1510
|
return e;
|
|
1498
1511
|
})();
|
|
1499
|
-
function
|
|
1512
|
+
function de(e) {
|
|
1500
1513
|
let t = 4294967295;
|
|
1501
|
-
for (let n = 0; n < e.length; n++) t =
|
|
1514
|
+
for (let n = 0; n < e.length; n++) t = ue[(t ^ e[n]) & 255] ^ t >>> 8;
|
|
1502
1515
|
return (t ^ 4294967295) >>> 0;
|
|
1503
1516
|
}
|
|
1504
|
-
var
|
|
1505
|
-
function
|
|
1506
|
-
return
|
|
1517
|
+
var P = new TextEncoder();
|
|
1518
|
+
function fe(e) {
|
|
1519
|
+
return F(e.map((e) => ({
|
|
1507
1520
|
...e,
|
|
1508
1521
|
body: e.data,
|
|
1509
1522
|
method: 0
|
|
1510
1523
|
})));
|
|
1511
1524
|
}
|
|
1512
|
-
async function
|
|
1525
|
+
async function pe(e) {
|
|
1513
1526
|
let t = [];
|
|
1514
1527
|
for (let n of e) {
|
|
1515
|
-
let e = await
|
|
1528
|
+
let e = await me(n.data);
|
|
1516
1529
|
t.push(e.length < n.data.length ? {
|
|
1517
1530
|
...n,
|
|
1518
1531
|
body: e,
|
|
@@ -1523,9 +1536,9 @@ async function fe(e) {
|
|
|
1523
1536
|
method: 0
|
|
1524
1537
|
});
|
|
1525
1538
|
}
|
|
1526
|
-
return
|
|
1539
|
+
return F(t);
|
|
1527
1540
|
}
|
|
1528
|
-
async function
|
|
1541
|
+
async function me(e) {
|
|
1529
1542
|
let t = new CompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1530
1543
|
n.write(e), n.close();
|
|
1531
1544
|
let i = [];
|
|
@@ -1534,52 +1547,52 @@ async function pe(e) {
|
|
|
1534
1547
|
if (e) break;
|
|
1535
1548
|
i.push(t);
|
|
1536
1549
|
}
|
|
1537
|
-
return
|
|
1550
|
+
return I(i);
|
|
1538
1551
|
}
|
|
1539
|
-
function
|
|
1552
|
+
function F(e) {
|
|
1540
1553
|
let t = [], n = [], r = 0;
|
|
1541
1554
|
for (let i of e) {
|
|
1542
|
-
let e =
|
|
1555
|
+
let e = P.encode(i.name), a = de(i.data), o = i.data.length, s = i.body.length, c = i.method === 8 ? 20 : 10, l = new ArrayBuffer(30 + e.length), u = new DataView(l);
|
|
1543
1556
|
u.setUint32(0, 67324752, !0), u.setUint16(4, c, !0), u.setUint16(6, 0, !0), u.setUint16(8, i.method, !0), u.setUint16(10, 0, !0), u.setUint16(12, 33, !0), u.setUint32(14, a, !0), u.setUint32(18, s, !0), u.setUint32(22, o, !0), u.setUint16(26, e.length, !0), u.setUint16(28, 0, !0), new Uint8Array(l, 30).set(e), t.push(new Uint8Array(l)), t.push(i.body);
|
|
1544
1557
|
let d = new ArrayBuffer(46 + e.length), f = new DataView(d);
|
|
1545
1558
|
f.setUint32(0, 33639248, !0), f.setUint16(4, 20, !0), f.setUint16(6, c, !0), f.setUint16(8, 0, !0), f.setUint16(10, i.method, !0), f.setUint16(12, 0, !0), f.setUint16(14, 33, !0), f.setUint32(16, a, !0), f.setUint32(20, s, !0), f.setUint32(24, o, !0), f.setUint16(28, e.length, !0), f.setUint16(30, 0, !0), f.setUint16(32, 0, !0), f.setUint16(34, 0, !0), f.setUint16(36, 0, !0), f.setUint32(38, 0, !0), f.setUint32(42, r, !0), new Uint8Array(d, 46).set(e), n.push(new Uint8Array(d)), r += 30 + e.length + s;
|
|
1546
1559
|
}
|
|
1547
|
-
let i =
|
|
1548
|
-
return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0),
|
|
1560
|
+
let i = I(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
|
|
1561
|
+
return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), I([
|
|
1549
1562
|
...t,
|
|
1550
1563
|
i,
|
|
1551
1564
|
new Uint8Array(a)
|
|
1552
1565
|
]);
|
|
1553
1566
|
}
|
|
1554
|
-
function
|
|
1567
|
+
function I(e) {
|
|
1555
1568
|
let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
|
|
1556
1569
|
for (let t of e) n.set(t, r), r += t.length;
|
|
1557
1570
|
return n;
|
|
1558
1571
|
}
|
|
1559
|
-
function
|
|
1572
|
+
function L(e) {
|
|
1560
1573
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1561
1574
|
}
|
|
1562
|
-
function
|
|
1575
|
+
function he(e) {
|
|
1563
1576
|
let t = "";
|
|
1564
1577
|
for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
|
|
1565
1578
|
return t;
|
|
1566
1579
|
}
|
|
1567
|
-
function
|
|
1568
|
-
return
|
|
1580
|
+
function R(e, t) {
|
|
1581
|
+
return he(t) + (e + 1);
|
|
1569
1582
|
}
|
|
1570
|
-
function
|
|
1583
|
+
function ge(e) {
|
|
1571
1584
|
let t = Date.UTC(1899, 11, 30);
|
|
1572
1585
|
return (e.getTime() - t) / 864e5;
|
|
1573
1586
|
}
|
|
1574
|
-
var
|
|
1575
|
-
function
|
|
1576
|
-
let n = [], r = t.map((e, t) => `<c r="${
|
|
1587
|
+
var _e = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", ve = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", ye = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\n <sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>\n</workbook>", be = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n</Relationships>", xe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n <numFmts count=\"1\"><numFmt numFmtId=\"164\" formatCode=\"yyyy-mm-dd\"/></numFmts>\n <fonts count=\"2\">\n <font><sz val=\"11\"/><name val=\"Calibri\"/></font>\n <font><sz val=\"11\"/><b/><name val=\"Calibri\"/></font>\n </fonts>\n <fills count=\"2\">\n <fill><patternFill patternType=\"none\"/></fill>\n <fill><patternFill patternType=\"gray125\"/></fill>\n </fills>\n <borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>\n <cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>\n <cellXfs count=\"3\">\n <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>\n <xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>\n <xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>\n </cellXfs>\n</styleSheet>";
|
|
1588
|
+
function Se(e, t) {
|
|
1589
|
+
let n = [], r = t.map((e, t) => `<c r="${R(0, t)}" t="str" s="2"><v>${L(e.label)}</v></c>`);
|
|
1577
1590
|
return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
|
|
1578
1591
|
let i = t.map((t, n) => {
|
|
1579
|
-
let i =
|
|
1592
|
+
let i = R(r + 1, n), a = e[t.key];
|
|
1580
1593
|
if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
|
|
1581
1594
|
let o = t.type ?? "text";
|
|
1582
|
-
return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${
|
|
1595
|
+
return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${ge(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${L(String(a))}</v></c>`;
|
|
1583
1596
|
});
|
|
1584
1597
|
n.push(`<row r="${r + 2}">${i.join("")}</row>`);
|
|
1585
1598
|
}), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -1587,65 +1600,65 @@ function xe(e, t) {
|
|
|
1587
1600
|
<sheetData>${n.join("")}</sheetData>
|
|
1588
1601
|
</worksheet>`;
|
|
1589
1602
|
}
|
|
1590
|
-
function Se(e, t) {
|
|
1591
|
-
return de(B(e, t));
|
|
1592
|
-
}
|
|
1593
1603
|
function Ce(e, t) {
|
|
1594
|
-
return fe(
|
|
1604
|
+
return fe(z(e, t));
|
|
1605
|
+
}
|
|
1606
|
+
function we(e, t) {
|
|
1607
|
+
return pe(z(e, t));
|
|
1595
1608
|
}
|
|
1596
|
-
function
|
|
1597
|
-
let n =
|
|
1609
|
+
function z(e, t) {
|
|
1610
|
+
let n = Se(e, t);
|
|
1598
1611
|
return [
|
|
1599
1612
|
{
|
|
1600
1613
|
name: "[Content_Types].xml",
|
|
1601
|
-
data:
|
|
1614
|
+
data: P.encode(_e)
|
|
1602
1615
|
},
|
|
1603
1616
|
{
|
|
1604
1617
|
name: "_rels/.rels",
|
|
1605
|
-
data:
|
|
1618
|
+
data: P.encode(ve)
|
|
1606
1619
|
},
|
|
1607
1620
|
{
|
|
1608
1621
|
name: "xl/workbook.xml",
|
|
1609
|
-
data:
|
|
1622
|
+
data: P.encode(ye)
|
|
1610
1623
|
},
|
|
1611
1624
|
{
|
|
1612
1625
|
name: "xl/_rels/workbook.xml.rels",
|
|
1613
|
-
data:
|
|
1626
|
+
data: P.encode(be)
|
|
1614
1627
|
},
|
|
1615
1628
|
{
|
|
1616
1629
|
name: "xl/worksheets/sheet1.xml",
|
|
1617
|
-
data:
|
|
1630
|
+
data: P.encode(n)
|
|
1618
1631
|
},
|
|
1619
1632
|
{
|
|
1620
1633
|
name: "xl/styles.xml",
|
|
1621
|
-
data:
|
|
1634
|
+
data: P.encode(xe)
|
|
1622
1635
|
}
|
|
1623
1636
|
];
|
|
1624
1637
|
}
|
|
1625
1638
|
//#endregion
|
|
1626
1639
|
//#region src/export/export.ts
|
|
1627
|
-
function
|
|
1640
|
+
function B(e, t, n) {
|
|
1628
1641
|
switch (n) {
|
|
1629
|
-
case "csv": return
|
|
1630
|
-
case "tsv": return
|
|
1631
|
-
case "json": return
|
|
1632
|
-
case "xlsx": return
|
|
1642
|
+
case "csv": return V(e, t, ",");
|
|
1643
|
+
case "tsv": return V(e, t, " ");
|
|
1644
|
+
case "json": return De(e, t);
|
|
1645
|
+
case "xlsx": return Ce(e, t);
|
|
1633
1646
|
}
|
|
1634
1647
|
}
|
|
1635
|
-
async function
|
|
1636
|
-
let r = n === "xlsx" ? await
|
|
1637
|
-
return new Blob([r], { type:
|
|
1648
|
+
async function Te(e, t, n) {
|
|
1649
|
+
let r = n === "xlsx" ? await we(e, t) : B(e, t, n);
|
|
1650
|
+
return new Blob([r], { type: je(n) });
|
|
1638
1651
|
}
|
|
1639
|
-
function
|
|
1652
|
+
function Ee(e, t) {
|
|
1640
1653
|
return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
|
|
1641
1654
|
}
|
|
1642
|
-
function
|
|
1643
|
-
return [t.map((e) =>
|
|
1655
|
+
function V(e, t, n) {
|
|
1656
|
+
return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(Ee(e[t.key], t), n)).join(n))].join("\n");
|
|
1644
1657
|
}
|
|
1645
|
-
function
|
|
1658
|
+
function H(e, t) {
|
|
1646
1659
|
return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
|
|
1647
1660
|
}
|
|
1648
|
-
function
|
|
1661
|
+
function De(e, t) {
|
|
1649
1662
|
let n = e.map((e) => {
|
|
1650
1663
|
let n = {};
|
|
1651
1664
|
for (let r of t) {
|
|
@@ -1656,35 +1669,35 @@ function Ee(e, t) {
|
|
|
1656
1669
|
});
|
|
1657
1670
|
return JSON.stringify(n, null, 2);
|
|
1658
1671
|
}
|
|
1659
|
-
function
|
|
1672
|
+
function Oe(e, t) {
|
|
1660
1673
|
let n = URL.createObjectURL(e), r = document.createElement("a");
|
|
1661
1674
|
r.href = n, r.download = t, r.style.display = "none", document.body.appendChild(r), r.click(), document.body.removeChild(r), setTimeout(() => URL.revokeObjectURL(n), 100);
|
|
1662
1675
|
}
|
|
1663
|
-
var
|
|
1676
|
+
var ke = {
|
|
1664
1677
|
csv: "text/csv;charset=utf-8",
|
|
1665
1678
|
tsv: "text/tab-separated-values;charset=utf-8",
|
|
1666
1679
|
json: "application/json;charset=utf-8",
|
|
1667
1680
|
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
1668
|
-
},
|
|
1681
|
+
}, Ae = {
|
|
1669
1682
|
csv: ".csv",
|
|
1670
1683
|
tsv: ".tsv",
|
|
1671
1684
|
json: ".json",
|
|
1672
1685
|
xlsx: ".xlsx"
|
|
1673
1686
|
};
|
|
1674
|
-
function Ae(e) {
|
|
1675
|
-
return Oe[e];
|
|
1676
|
-
}
|
|
1677
1687
|
function je(e) {
|
|
1678
1688
|
return ke[e];
|
|
1679
1689
|
}
|
|
1690
|
+
function Me(e) {
|
|
1691
|
+
return Ae[e];
|
|
1692
|
+
}
|
|
1680
1693
|
//#endregion
|
|
1681
1694
|
//#region src/export/xlsx-reader.ts
|
|
1682
|
-
function
|
|
1695
|
+
function Ne(e) {
|
|
1683
1696
|
for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
|
|
1684
1697
|
throw Error("XLSX: End of central directory not found — not a valid ZIP file");
|
|
1685
1698
|
}
|
|
1686
|
-
function
|
|
1687
|
-
let t =
|
|
1699
|
+
function Pe(e) {
|
|
1700
|
+
let t = Ne(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
|
|
1688
1701
|
for (; o < s && e.getUint32(o, !0) === 33639248;) {
|
|
1689
1702
|
let t = e.getUint16(o + 10, !0), n = e.getUint32(o + 20, !0), r = e.getUint32(o + 24, !0), s = e.getUint16(o + 28, !0), c = e.getUint16(o + 30, !0), l = e.getUint16(o + 32, !0), u = e.getUint32(o + 42, !0), d = i.decode(new Uint8Array(e.buffer, o + 46, s));
|
|
1690
1703
|
a.push({
|
|
@@ -1697,7 +1710,7 @@ function Ne(e) {
|
|
|
1697
1710
|
}
|
|
1698
1711
|
return a;
|
|
1699
1712
|
}
|
|
1700
|
-
async function
|
|
1713
|
+
async function Fe(e) {
|
|
1701
1714
|
let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1702
1715
|
n.write(e), n.close();
|
|
1703
1716
|
let i = [];
|
|
@@ -1710,28 +1723,28 @@ async function Pe(e) {
|
|
|
1710
1723
|
for (let e of i) o.set(e, s), s += e.length;
|
|
1711
1724
|
return o;
|
|
1712
1725
|
}
|
|
1713
|
-
async function
|
|
1726
|
+
async function Ie(e, t) {
|
|
1714
1727
|
let n = t.localHeaderOffset, r = e.getUint16(n + 26, !0), i = e.getUint16(n + 28, !0), a = n + 30 + r + i, o = new Uint8Array(e.buffer, a, t.compressedSize);
|
|
1715
1728
|
if (t.compressionMethod === 0) return o.slice();
|
|
1716
|
-
if (t.compressionMethod === 8) return
|
|
1729
|
+
if (t.compressionMethod === 8) return Fe(o);
|
|
1717
1730
|
throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
|
|
1718
1731
|
}
|
|
1719
|
-
async function
|
|
1720
|
-
let t = new DataView(e), n =
|
|
1721
|
-
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await
|
|
1732
|
+
async function Le(e) {
|
|
1733
|
+
let t = new DataView(e), n = Pe(t), r = /* @__PURE__ */ new Map();
|
|
1734
|
+
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ie(t, e));
|
|
1722
1735
|
return r;
|
|
1723
1736
|
}
|
|
1724
|
-
var
|
|
1725
|
-
function
|
|
1726
|
-
let t =
|
|
1737
|
+
var Re = new TextDecoder("utf-8");
|
|
1738
|
+
function U(e) {
|
|
1739
|
+
let t = Re.decode(e);
|
|
1727
1740
|
return new DOMParser().parseFromString(t, "application/xml");
|
|
1728
1741
|
}
|
|
1729
|
-
function
|
|
1742
|
+
function ze(e) {
|
|
1730
1743
|
if (!e) return [];
|
|
1731
|
-
let t =
|
|
1744
|
+
let t = U(e);
|
|
1732
1745
|
return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
|
|
1733
1746
|
}
|
|
1734
|
-
var
|
|
1747
|
+
var Be = /* @__PURE__ */ new Set([
|
|
1735
1748
|
14,
|
|
1736
1749
|
15,
|
|
1737
1750
|
16,
|
|
@@ -1751,37 +1764,37 @@ var ze = /* @__PURE__ */ new Set([
|
|
|
1751
1764
|
57,
|
|
1752
1765
|
58
|
|
1753
1766
|
]);
|
|
1754
|
-
function
|
|
1767
|
+
function Ve(e) {
|
|
1755
1768
|
let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
|
|
1756
1769
|
return /[dy]/i.test(t);
|
|
1757
1770
|
}
|
|
1758
|
-
function
|
|
1771
|
+
function He(e) {
|
|
1759
1772
|
let t = /* @__PURE__ */ new Set();
|
|
1760
1773
|
if (!e) return t;
|
|
1761
|
-
let n =
|
|
1774
|
+
let n = U(e), r = /* @__PURE__ */ new Map();
|
|
1762
1775
|
for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
|
|
1763
1776
|
return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
|
|
1764
1777
|
let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
|
|
1765
|
-
(a === void 0 ?
|
|
1778
|
+
(a === void 0 ? Be.has(i) : Ve(a)) && t.add(n);
|
|
1766
1779
|
}), t;
|
|
1767
1780
|
}
|
|
1768
|
-
function
|
|
1781
|
+
function Ue(e) {
|
|
1769
1782
|
if (!e) return !1;
|
|
1770
|
-
let t =
|
|
1783
|
+
let t = U(e).querySelector("workbookPr")?.getAttribute("date1904");
|
|
1771
1784
|
return t === "1" || t === "true";
|
|
1772
1785
|
}
|
|
1773
|
-
function
|
|
1786
|
+
function We(e, t) {
|
|
1774
1787
|
return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
|
|
1775
1788
|
}
|
|
1776
|
-
function
|
|
1777
|
-
let i =
|
|
1789
|
+
function Ge(e, t, n, r) {
|
|
1790
|
+
let i = U(e).querySelectorAll("row");
|
|
1778
1791
|
if (i.length === 0) return [];
|
|
1779
1792
|
let a = 0, o = /* @__PURE__ */ new Map();
|
|
1780
1793
|
for (let e of i) {
|
|
1781
1794
|
let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
|
|
1782
1795
|
o.set(i, s);
|
|
1783
1796
|
for (let i of e.querySelectorAll("c")) {
|
|
1784
|
-
let e =
|
|
1797
|
+
let e = Ke(i.getAttribute("r") ?? "");
|
|
1785
1798
|
e > a && (a = e);
|
|
1786
1799
|
let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
|
|
1787
1800
|
if (o === "s") d = t[parseInt(l, 10)] ?? "";
|
|
@@ -1790,7 +1803,7 @@ function We(e, t, n, r) {
|
|
|
1790
1803
|
else if (l === "") d = "";
|
|
1791
1804
|
else {
|
|
1792
1805
|
let e = parseFloat(l);
|
|
1793
|
-
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ?
|
|
1806
|
+
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? We(e, r) : l;
|
|
1794
1807
|
}
|
|
1795
1808
|
s.set(e, d);
|
|
1796
1809
|
}
|
|
@@ -1804,13 +1817,13 @@ function We(e, t, n, r) {
|
|
|
1804
1817
|
}
|
|
1805
1818
|
return c;
|
|
1806
1819
|
}
|
|
1807
|
-
function
|
|
1820
|
+
function Ke(e) {
|
|
1808
1821
|
let t = 0, n = 0;
|
|
1809
1822
|
for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
|
|
1810
1823
|
return t - 1;
|
|
1811
1824
|
}
|
|
1812
|
-
async function
|
|
1813
|
-
let t = await
|
|
1825
|
+
async function qe(e) {
|
|
1826
|
+
let t = await Le(e), n = ze(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
|
|
1814
1827
|
if (!r) {
|
|
1815
1828
|
for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
|
|
1816
1829
|
r = n;
|
|
@@ -1818,7 +1831,7 @@ async function Ke(e) {
|
|
|
1818
1831
|
}
|
|
1819
1832
|
}
|
|
1820
1833
|
if (!r) throw Error("XLSX: No worksheet found");
|
|
1821
|
-
let i =
|
|
1834
|
+
let i = He(t.get("xl/styles.xml")), a = Ue(t.get("xl/workbook.xml")), o = Ge(r, n, i, a);
|
|
1822
1835
|
return o.length === 0 ? {
|
|
1823
1836
|
headers: [],
|
|
1824
1837
|
rows: []
|
|
@@ -1829,12 +1842,12 @@ async function Ke(e) {
|
|
|
1829
1842
|
}
|
|
1830
1843
|
//#endregion
|
|
1831
1844
|
//#region src/models/types.ts
|
|
1832
|
-
function
|
|
1845
|
+
function W(e) {
|
|
1833
1846
|
return e.align ? e.align : e.type === "number" ? "end" : e.type === "boolean" ? "center" : "start";
|
|
1834
1847
|
}
|
|
1835
1848
|
//#endregion
|
|
1836
1849
|
//#region \0@oxc-project+runtime@0.152.0/helpers/esm/decorate.js
|
|
1837
|
-
function
|
|
1850
|
+
function G(e, t, n, r) {
|
|
1838
1851
|
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
1839
1852
|
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
1840
1853
|
else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
|
|
@@ -1842,16 +1855,16 @@ function K(e, t, n, r) {
|
|
|
1842
1855
|
}
|
|
1843
1856
|
//#endregion
|
|
1844
1857
|
//#region src/flex-table.ts
|
|
1845
|
-
var
|
|
1858
|
+
var K = {
|
|
1846
1859
|
eq: "=",
|
|
1847
1860
|
neq: "≠",
|
|
1848
1861
|
gt: ">",
|
|
1849
1862
|
lt: "<",
|
|
1850
1863
|
gte: "≥",
|
|
1851
1864
|
lte: "≤"
|
|
1852
|
-
},
|
|
1865
|
+
}, q = 120, J = 40, Y = 20, X = 32, Z = 5, Je = 200, Q = class extends n {
|
|
1853
1866
|
constructor(...e) {
|
|
1854
|
-
super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss =
|
|
1867
|
+
super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = X, this._targetFloor = 0, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new ne(), this._editing = new re(), this._rowSelection = new j(), this._undo = new M(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._warnedUnconstrained = !1, this._onCommentPopupOutsideClick = () => {
|
|
1855
1868
|
this._commitCommentPopup();
|
|
1856
1869
|
}, this._invalidCells = /* @__PURE__ */ new Map(), this._textFilterState = /* @__PURE__ */ new Map(), this._numberFilterState = /* @__PURE__ */ new Map(), this._dateFilterState = /* @__PURE__ */ new Map(), this._emptyFilterState = /* @__PURE__ */ new Map();
|
|
1857
1870
|
}
|
|
@@ -1866,7 +1879,7 @@ var q = {
|
|
|
1866
1879
|
this._data = e, n && !this._inUndoRedo && (this.clearUndoOnDataChange && this._undo.clear(), this.clearSelectionOnDataChange && this._rowSelection.selectedCount > 0 && (this._rowSelection.deselectAll(), this._rowSelectionVersion++, this._dispatchRowSelectionEvent())), this.requestUpdate("data", t);
|
|
1867
1880
|
}
|
|
1868
1881
|
get rowHeight() {
|
|
1869
|
-
let e = this._rowHeightExplicit ?? this._rowHeightFromCss ??
|
|
1882
|
+
let e = this._rowHeightExplicit ?? this._rowHeightFromCss ?? X;
|
|
1870
1883
|
return Math.max(e, this._targetFloor);
|
|
1871
1884
|
}
|
|
1872
1885
|
set rowHeight(e) {
|
|
@@ -2216,17 +2229,17 @@ var q = {
|
|
|
2216
2229
|
}
|
|
2217
2230
|
exportToString(e, t) {
|
|
2218
2231
|
let n = this._exportSlice(t);
|
|
2219
|
-
return n ?
|
|
2232
|
+
return n ? B(n.rows, n.cols, e) : "";
|
|
2220
2233
|
}
|
|
2221
2234
|
async exportToBlob(e, t) {
|
|
2222
2235
|
let n = this._exportSlice(t) ?? {
|
|
2223
2236
|
rows: [],
|
|
2224
2237
|
cols: []
|
|
2225
2238
|
};
|
|
2226
|
-
return
|
|
2239
|
+
return Te(n.rows, n.cols, e);
|
|
2227
2240
|
}
|
|
2228
2241
|
async exportToFile(e, t) {
|
|
2229
|
-
|
|
2242
|
+
Oe(await this.exportToBlob(e), t ?? `export${Me(e)}`);
|
|
2230
2243
|
}
|
|
2231
2244
|
_exportSlice(e) {
|
|
2232
2245
|
if (e?.selectionOnly) {
|
|
@@ -2299,7 +2312,7 @@ var q = {
|
|
|
2299
2312
|
async importFromFile(e) {
|
|
2300
2313
|
let t = e.name.toLowerCase();
|
|
2301
2314
|
if (t.endsWith(".xlsx")) {
|
|
2302
|
-
let t = await
|
|
2315
|
+
let t = await qe(await e.arrayBuffer());
|
|
2303
2316
|
this._applyImportedSheet(t);
|
|
2304
2317
|
} else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
|
|
2305
2318
|
let t = await e.text(), n = h(t);
|
|
@@ -2391,8 +2404,8 @@ var q = {
|
|
|
2391
2404
|
return this._columnWidths.get(e);
|
|
2392
2405
|
}
|
|
2393
2406
|
_getColWidth(e) {
|
|
2394
|
-
let t = this._columnWidths.get(e.key) ?? e.width ??
|
|
2395
|
-
return Math.max(t, e.minWidth ??
|
|
2407
|
+
let t = this._columnWidths.get(e.key) ?? e.width ?? q;
|
|
2408
|
+
return Math.max(t, e.minWidth ?? J);
|
|
2396
2409
|
}
|
|
2397
2410
|
get headerHeight() {
|
|
2398
2411
|
return this.rowHeight + 8;
|
|
@@ -2418,10 +2431,10 @@ var q = {
|
|
|
2418
2431
|
return Math.max(0, this._visibleRowCount - this._frozenRowCount) * this.rowHeight;
|
|
2419
2432
|
}
|
|
2420
2433
|
get visibleRange() {
|
|
2421
|
-
let e = this._frozenRowCount, t = e + Math.floor(Math.max(0, this._scrollTop) / this.rowHeight), n = Math.max(e, t -
|
|
2434
|
+
let e = this._frozenRowCount, t = e + Math.floor(Math.max(0, this._scrollTop) / this.rowHeight), n = Math.max(e, t - Z), r = Math.max(0, this._viewportHeight - this.headerHeight - this.frozenRowsHeight), i = Math.ceil(r / this.rowHeight) + 1;
|
|
2422
2435
|
return {
|
|
2423
2436
|
start: n,
|
|
2424
|
-
end: Math.min(this._visibleRowCount, t + i +
|
|
2437
|
+
end: Math.min(this._visibleRowCount, t + i + Z)
|
|
2425
2438
|
};
|
|
2426
2439
|
}
|
|
2427
2440
|
connectedCallback() {
|
|
@@ -2464,13 +2477,13 @@ var q = {
|
|
|
2464
2477
|
i = r;
|
|
2465
2478
|
break;
|
|
2466
2479
|
}
|
|
2467
|
-
i = Math.max(0, i -
|
|
2480
|
+
i = Math.max(0, i - Z);
|
|
2468
2481
|
let a = e.length;
|
|
2469
2482
|
for (let e = i; e < t.length; e++) if (t[e] > r) {
|
|
2470
2483
|
a = e;
|
|
2471
2484
|
break;
|
|
2472
2485
|
}
|
|
2473
|
-
return a = Math.min(e.length, a +
|
|
2486
|
+
return a = Math.min(e.length, a + Z), {
|
|
2474
2487
|
start: i,
|
|
2475
2488
|
end: a
|
|
2476
2489
|
};
|
|
@@ -2530,7 +2543,7 @@ var q = {
|
|
|
2530
2543
|
e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
|
|
2531
2544
|
}
|
|
2532
2545
|
_warnIfUnconstrained() {
|
|
2533
|
-
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount <
|
|
2546
|
+
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Je || this.scrollHeight > this.clientHeight + 1 || (this._warnedUnconstrained = !0, console.warn(`[@iyulab/flex-table] ${this._visibleRowCount} rows but the host has no height constraint — it grew to fit every row, so virtual scrolling is off and all rows are rendered. Give the host a height (e.g. height: 400px, or flex: 1 1 auto with min-height: 0 inside a sized parent) so it becomes the scroll container.`));
|
|
2534
2547
|
}
|
|
2535
2548
|
_onScroll() {
|
|
2536
2549
|
this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
|
|
@@ -2766,7 +2779,7 @@ var q = {
|
|
|
2766
2779
|
_onEditorKeyDown(e) {
|
|
2767
2780
|
if (_(e)) return;
|
|
2768
2781
|
let t = e.currentTarget;
|
|
2769
|
-
if (!(t?.localName === "u-date-picker" && (e.composedPath().some((e) => e instanceof Element && e.part?.contains("popover")) || e.key === "Escape" &&
|
|
2782
|
+
if (!(t?.localName === "u-date-picker" && (e.composedPath().some((e) => e instanceof Element && e.part?.contains("popover")) || e.key === "Escape" && $(t)))) {
|
|
2770
2783
|
if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
|
|
2771
2784
|
if (e.key === "ArrowDown") {
|
|
2772
2785
|
e.preventDefault(), e.stopPropagation();
|
|
@@ -2822,7 +2835,7 @@ var q = {
|
|
|
2822
2835
|
this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._scrollToActiveCell(), this._dispatchSelectionEvent();
|
|
2823
2836
|
}
|
|
2824
2837
|
_onKeyDown(e) {
|
|
2825
|
-
if (this._editing.current) return;
|
|
2838
|
+
if (this._editing.current || this._openFilterKey && e.composedPath().some((e) => e instanceof Element && e.classList.contains("ft-filter-dropdown"))) return;
|
|
2826
2839
|
let t = this.visibleColumns;
|
|
2827
2840
|
if ((e.ctrlKey || e.metaKey) && !e.altKey) {
|
|
2828
2841
|
let t = e.key.toLowerCase();
|
|
@@ -2888,12 +2901,12 @@ var q = {
|
|
|
2888
2901
|
if (!e.altKey || !this._activeCell || e.key !== "ArrowLeft" && e.key !== "ArrowRight") return !1;
|
|
2889
2902
|
e.preventDefault();
|
|
2890
2903
|
let n = t[this._activeCell.col];
|
|
2891
|
-
return n && this._resizeColumnBy(n.key, e.key === "ArrowRight" ?
|
|
2904
|
+
return n && this._resizeColumnBy(n.key, e.key === "ArrowRight" ? Y : -20), !0;
|
|
2892
2905
|
}
|
|
2893
2906
|
_resizeColumnBy(e, t) {
|
|
2894
2907
|
let n = this.visibleColumns.findIndex((t) => t.key === e), r = this.visibleColumns[n];
|
|
2895
2908
|
if (!r) return;
|
|
2896
|
-
let i = this._columnWidths.get(r.key) ?? r.width ??
|
|
2909
|
+
let i = this._columnWidths.get(r.key) ?? r.width ?? q, a = r.minWidth ?? J, o = Math.max(a, i + t);
|
|
2897
2910
|
this._columnWidths.set(r.key, o), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
|
|
2898
2911
|
detail: {
|
|
2899
2912
|
key: r.key,
|
|
@@ -3215,7 +3228,7 @@ var q = {
|
|
|
3215
3228
|
return Math.min(n, i);
|
|
3216
3229
|
}
|
|
3217
3230
|
_renderHeaderCell(e, t) {
|
|
3218
|
-
let n = e.sortable !== !1, r = this._sortCriteria.find((t) => t.key === e.key), o = this._sortCriteria.length > 1 ? this._sortCriteria.findIndex((t) => t.key === e.key) : -1, s = this._filters.some((t) => t.key === e.key), c = e.pinned === "left", l = e.pinned === "right", u = c || l, d = e.headerAlign ??
|
|
3231
|
+
let n = e.sortable !== !1, r = this._sortCriteria.find((t) => t.key === e.key), o = this._sortCriteria.length > 1 ? this._sortCriteria.findIndex((t) => t.key === e.key) : -1, s = this._filters.some((t) => t.key === e.key), c = e.pinned === "left", l = e.pinned === "right", u = c || l, d = e.headerAlign ?? W(e), f = [
|
|
3219
3232
|
"ft-header-cell",
|
|
3220
3233
|
n ? "ft-sortable" : "",
|
|
3221
3234
|
u ? "ft-pinned" : "",
|
|
@@ -3349,8 +3362,9 @@ var q = {
|
|
|
3349
3362
|
_openFilterFromMenu(e) {
|
|
3350
3363
|
this._headerMenu = null, this._openFilterKey = e, requestAnimationFrame(() => {
|
|
3351
3364
|
document.addEventListener("click", this._onDocumentClick, { once: !0 });
|
|
3352
|
-
}), this.updateComplete.then(() => {
|
|
3353
|
-
this.shadowRoot?.querySelector(".ft-filter-dropdown input, .ft-filter-dropdown select")
|
|
3365
|
+
}), this.updateComplete.then(async () => {
|
|
3366
|
+
let e = this.shadowRoot?.querySelector(".ft-filter-dropdown input, .ft-filter-dropdown select, .ft-filter-dropdown u-date-picker");
|
|
3367
|
+
await e?.updateComplete, e?.focus();
|
|
3354
3368
|
});
|
|
3355
3369
|
}
|
|
3356
3370
|
_showHiddenBefore(e) {
|
|
@@ -3386,7 +3400,7 @@ var q = {
|
|
|
3386
3400
|
${r.map((e) => c("show", A("showColumn", { header: e.label }), () => this._setColumnHidden(e.key, !1)))}
|
|
3387
3401
|
<div class="ft-header-menu-separator" role="separator"></div>
|
|
3388
3402
|
${c("autofit", A("autoFitWidth"), () => this._autoFitColumn(e))}
|
|
3389
|
-
${c("wider", A("wider"), () => this._resizeColumnBy(e,
|
|
3403
|
+
${c("wider", A("wider"), () => this._resizeColumnBy(e, Y), !0)}
|
|
3390
3404
|
${c("narrower", A("narrower"), () => this._resizeColumnBy(e, -20), !0)}
|
|
3391
3405
|
</div>
|
|
3392
3406
|
`;
|
|
@@ -3675,10 +3689,10 @@ var q = {
|
|
|
3675
3689
|
@keydown=${(e) => {
|
|
3676
3690
|
e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
|
|
3677
3691
|
}}>
|
|
3678
|
-
${Object.keys(
|
|
3692
|
+
${Object.keys(K).map((e) => i`<option value=${e}>${K[e]}</option>`)}
|
|
3679
3693
|
</select>
|
|
3680
3694
|
<input class="ft-filter-input ft-num-cond-input" type="text" inputmode="decimal" placeholder=${A("valuePlaceholder")}
|
|
3681
|
-
.value=${n.text ?? (n.value == null ? "" :
|
|
3695
|
+
.value=${n.text ?? (n.value == null ? "" : se(n.value))}
|
|
3682
3696
|
aria-invalid=${n.text && n.value == null ? "true" : "false"}
|
|
3683
3697
|
@input=${(n) => {
|
|
3684
3698
|
let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
|
|
@@ -3737,21 +3751,21 @@ var q = {
|
|
|
3737
3751
|
return n ? n.error : null;
|
|
3738
3752
|
}
|
|
3739
3753
|
_renderDateFilter(e) {
|
|
3740
|
-
let t = e.type === "datetime"
|
|
3754
|
+
let t = e.type === "datetime", n = this._dateFilterState.get(e.key) ?? {}, r = (e) => e?.slice(0, 10), o = (e) => {
|
|
3755
|
+
e.key === "Escape" && $(e.currentTarget) || (e.stopPropagation(), e.key === "Escape" && (this._openFilterKey = null));
|
|
3756
|
+
};
|
|
3741
3757
|
return i`
|
|
3742
|
-
<div class="ft-filter-range">
|
|
3743
|
-
<
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
@
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
.value=${n.to ?? ""}
|
|
3751
|
-
@
|
|
3752
|
-
@keydown=${
|
|
3753
|
-
e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
|
|
3754
|
-
}}>
|
|
3758
|
+
<div class="ft-filter-range ft-filter-range-dates">
|
|
3759
|
+
<u-date-picker class="ft-filter-date" size="sm" clearable
|
|
3760
|
+
mode=${t ? "datetime" : "date"} label=${A("fromPlaceholder")}
|
|
3761
|
+
.value=${n.from ?? ""} max=${r(n.to) ?? a}
|
|
3762
|
+
@change=${(t) => this._applyDateFilter(e.key, t, "from")}
|
|
3763
|
+
@keydown=${o}></u-date-picker>
|
|
3764
|
+
<u-date-picker class="ft-filter-date" size="sm" clearable
|
|
3765
|
+
mode=${t ? "datetime" : "date"} label=${A("toPlaceholder")}
|
|
3766
|
+
.value=${n.to ?? ""} min=${r(n.from) ?? a}
|
|
3767
|
+
@change=${(t) => this._applyDateFilter(e.key, t, "to")}
|
|
3768
|
+
@keydown=${o}></u-date-picker>
|
|
3755
3769
|
</div>
|
|
3756
3770
|
${this._renderEmptyFilterRow(e.key, () => {
|
|
3757
3771
|
this._dateFilterState.delete(e.key);
|
|
@@ -3759,7 +3773,7 @@ var q = {
|
|
|
3759
3773
|
`;
|
|
3760
3774
|
}
|
|
3761
3775
|
_applyDateFilter(e, t, n) {
|
|
3762
|
-
let r = t.target.value, i = this._dateFilterState.get(e) ?? {};
|
|
3776
|
+
let r = t.target.value ?? "", i = this._dateFilterState.get(e) ?? {};
|
|
3763
3777
|
r === "" ? delete i[n] : i[n] = r, this._dateFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
|
|
3764
3778
|
}
|
|
3765
3779
|
_renderBooleanFilter(e) {
|
|
@@ -3787,7 +3801,7 @@ var q = {
|
|
|
3787
3801
|
if (!n) return;
|
|
3788
3802
|
let r = this.shadowRoot?.querySelectorAll(`.ft-cell[data-col-index="${t}"]`), i = 0, a = this.shadowRoot?.querySelector(`.ft-header-cell[data-col-index="${t}"]`);
|
|
3789
3803
|
if (a && (i = Math.max(i, a.scrollWidth)), r) for (let e of r) i = Math.max(i, e.scrollWidth);
|
|
3790
|
-
let o = n.minWidth ??
|
|
3804
|
+
let o = n.minWidth ?? J, s = Math.max(o, i + 8);
|
|
3791
3805
|
this._columnWidths.set(n.key, s), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
|
|
3792
3806
|
detail: {
|
|
3793
3807
|
key: n.key,
|
|
@@ -3800,7 +3814,7 @@ var q = {
|
|
|
3800
3814
|
}
|
|
3801
3815
|
_onResizeStart(e, t) {
|
|
3802
3816
|
e.preventDefault(), e.stopPropagation();
|
|
3803
|
-
let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ??
|
|
3817
|
+
let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? q;
|
|
3804
3818
|
this._resizing = {
|
|
3805
3819
|
colIndex: t,
|
|
3806
3820
|
startX: e.clientX,
|
|
@@ -3808,13 +3822,13 @@ var q = {
|
|
|
3808
3822
|
};
|
|
3809
3823
|
let i = (e) => {
|
|
3810
3824
|
if (!this._resizing) return;
|
|
3811
|
-
let t = e.clientX - this._resizing.startX, r = n.minWidth ??
|
|
3825
|
+
let t = e.clientX - this._resizing.startX, r = n.minWidth ?? J, i = Math.max(r, this._resizing.startWidth + t);
|
|
3812
3826
|
this._columnWidths.set(n.key, i), this.requestUpdate();
|
|
3813
3827
|
}, a = () => {
|
|
3814
3828
|
document.removeEventListener("mousemove", i), document.removeEventListener("mouseup", o), this._resizeCleanup = null;
|
|
3815
3829
|
}, o = () => {
|
|
3816
3830
|
if (a(), this._resizing) {
|
|
3817
|
-
let e = this._columnWidths.get(n.key) ??
|
|
3831
|
+
let e = this._columnWidths.get(n.key) ?? q;
|
|
3818
3832
|
this.dispatchEvent(new CustomEvent("column-resize", {
|
|
3819
3833
|
detail: {
|
|
3820
3834
|
key: n.key,
|
|
@@ -4406,7 +4420,7 @@ var q = {
|
|
|
4406
4420
|
let v = s || l, y = this._isCellInvalid(n, r), b = (this._findState?.results ?? []).findIndex((e) => e.row === n && e.col === r), x = b >= 0, S = x && b === this._findState.currentIndex, w = [
|
|
4407
4421
|
"ft-cell",
|
|
4408
4422
|
`ft-type-${t.type ?? "text"}`,
|
|
4409
|
-
`ft-align-${
|
|
4423
|
+
`ft-align-${W(t)}`,
|
|
4410
4424
|
s ? "ft-active" : "",
|
|
4411
4425
|
l ? "ft-selected" : "",
|
|
4412
4426
|
f ? "ft-pinned" : "",
|
|
@@ -4441,7 +4455,7 @@ var q = {
|
|
|
4441
4455
|
let n = e[t.key], r = n == null ? "" : String(n);
|
|
4442
4456
|
if (t.type === "number") return i`
|
|
4443
4457
|
<input class="ft-editor ft-editor-number" type="text" inputmode="decimal"
|
|
4444
|
-
.value=${typeof n == "number" ?
|
|
4458
|
+
.value=${typeof n == "number" ? se(n) : r}
|
|
4445
4459
|
@keydown=${this._onEditorKeyDown}
|
|
4446
4460
|
@blur=${() => this._commitEdit()}>
|
|
4447
4461
|
`;
|
|
@@ -4450,7 +4464,7 @@ var q = {
|
|
|
4450
4464
|
return i`
|
|
4451
4465
|
<u-date-picker class="ft-editor ft-editor-${t.type}" size="sm"
|
|
4452
4466
|
mode=${e ? "datetime" : "date"} ?confirm=${e}
|
|
4453
|
-
.value=${
|
|
4467
|
+
.value=${Ye(n, e)}
|
|
4454
4468
|
@keydown=${this._onEditorKeyDown}
|
|
4455
4469
|
@change=${() => this._commitEdit()}
|
|
4456
4470
|
@blur=${() => this._commitEdit()}></u-date-picker>
|
|
@@ -4497,70 +4511,70 @@ var q = {
|
|
|
4497
4511
|
`;
|
|
4498
4512
|
}
|
|
4499
4513
|
};
|
|
4500
|
-
|
|
4514
|
+
G([s({ type: Array })], Q.prototype, "columns", void 0), G([s({
|
|
4501
4515
|
type: Array,
|
|
4502
4516
|
hasChanged: () => !0
|
|
4503
|
-
})],
|
|
4517
|
+
})], Q.prototype, "data", null), G([s({
|
|
4504
4518
|
type: Boolean,
|
|
4505
4519
|
attribute: "clear-undo-on-data-change"
|
|
4506
|
-
})],
|
|
4520
|
+
})], Q.prototype, "clearUndoOnDataChange", void 0), G([s({
|
|
4507
4521
|
type: Boolean,
|
|
4508
4522
|
attribute: "clear-selection-on-data-change"
|
|
4509
|
-
})],
|
|
4523
|
+
})], Q.prototype, "clearSelectionOnDataChange", void 0), G([s({
|
|
4510
4524
|
type: Number,
|
|
4511
4525
|
attribute: "row-height"
|
|
4512
|
-
})],
|
|
4526
|
+
})], Q.prototype, "rowHeight", null), G([s({
|
|
4513
4527
|
type: Boolean,
|
|
4514
4528
|
attribute: "show-row-numbers"
|
|
4515
|
-
})],
|
|
4529
|
+
})], Q.prototype, "showRowNumbers", void 0), G([s({
|
|
4516
4530
|
type: String,
|
|
4517
4531
|
reflect: !0
|
|
4518
|
-
})],
|
|
4532
|
+
})], Q.prototype, "theme", void 0), G([s({
|
|
4519
4533
|
type: Number,
|
|
4520
4534
|
attribute: "max-rows"
|
|
4521
|
-
})],
|
|
4535
|
+
})], Q.prototype, "maxRows", void 0), G([s({ type: Boolean })], Q.prototype, "editable", void 0), G([s({
|
|
4522
4536
|
type: Boolean,
|
|
4523
4537
|
attribute: "show-filters"
|
|
4524
|
-
})],
|
|
4538
|
+
})], Q.prototype, "showFilters", void 0), G([s({
|
|
4525
4539
|
type: Boolean,
|
|
4526
4540
|
attribute: "show-context-menu"
|
|
4527
|
-
})],
|
|
4541
|
+
})], Q.prototype, "showContextMenu", void 0), G([s({
|
|
4528
4542
|
type: Number,
|
|
4529
4543
|
attribute: "frozen-rows"
|
|
4530
|
-
})],
|
|
4544
|
+
})], Q.prototype, "frozenRows", void 0), G([s({
|
|
4531
4545
|
type: String,
|
|
4532
4546
|
attribute: "empty-message"
|
|
4533
|
-
})],
|
|
4547
|
+
})], Q.prototype, "emptyMessage", void 0), G([s({
|
|
4534
4548
|
type: String,
|
|
4535
4549
|
attribute: "no-matching-message"
|
|
4536
|
-
})],
|
|
4550
|
+
})], Q.prototype, "noMatchingMessage", void 0), G([s({
|
|
4537
4551
|
type: Boolean,
|
|
4538
4552
|
reflect: !0
|
|
4539
|
-
})],
|
|
4553
|
+
})], Q.prototype, "loading", void 0), G([s({
|
|
4540
4554
|
type: Boolean,
|
|
4541
4555
|
attribute: "import-enabled"
|
|
4542
|
-
})],
|
|
4556
|
+
})], Q.prototype, "importEnabled", void 0), G([s({ type: Boolean })], Q.prototype, "selectable", void 0), G([s({
|
|
4543
4557
|
type: String,
|
|
4544
4558
|
attribute: "selection-mode"
|
|
4545
|
-
})],
|
|
4559
|
+
})], Q.prototype, "selectionMode", null), G([s({
|
|
4546
4560
|
type: String,
|
|
4547
4561
|
attribute: "data-mode"
|
|
4548
|
-
})],
|
|
4562
|
+
})], Q.prototype, "dataMode", void 0), G([s({
|
|
4549
4563
|
type: Object,
|
|
4550
4564
|
attribute: "footer-data"
|
|
4551
|
-
})],
|
|
4565
|
+
})], Q.prototype, "footerData", void 0), G([s({ attribute: !1 })], Q.prototype, "stylesheets", void 0), G([s({
|
|
4552
4566
|
type: Number,
|
|
4553
4567
|
attribute: "max-undo-size"
|
|
4554
|
-
})],
|
|
4555
|
-
function
|
|
4568
|
+
})], Q.prototype, "maxUndoSize", null), G([c()], Q.prototype, "_scrollTop", void 0), G([c()], Q.prototype, "_scrollLeft", void 0), G([c()], Q.prototype, "_viewportHeight", void 0), G([c()], Q.prototype, "_viewportWidth", void 0), G([c()], Q.prototype, "_activeCell", void 0), G([c()], Q.prototype, "_editingCell", void 0), G([c()], Q.prototype, "_sortCriteria", void 0), G([c()], Q.prototype, "_openFilterKey", void 0), G([c()], Q.prototype, "_rowSelectionVersion", void 0), G([c()], Q.prototype, "_autocompleteState", void 0), G([c()], Q.prototype, "_headerMenu", void 0), G([c()], Q.prototype, "_bodyContextMenu", void 0), G([c()], Q.prototype, "_commentPopup", void 0), G([c()], Q.prototype, "_isDragOver", void 0), Q = G([o("flex-table")], Q);
|
|
4569
|
+
function Ye(e, t) {
|
|
4556
4570
|
if (t) {
|
|
4557
|
-
let t =
|
|
4571
|
+
let t = le(e);
|
|
4558
4572
|
return /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(t) ? t.replace(" ", "T") : void 0;
|
|
4559
4573
|
}
|
|
4560
|
-
let n =
|
|
4574
|
+
let n = ce(e);
|
|
4561
4575
|
return /^\d{4}-\d{2}-\d{2}$/.test(n) ? n : void 0;
|
|
4562
4576
|
}
|
|
4563
|
-
function
|
|
4577
|
+
function $(e) {
|
|
4564
4578
|
try {
|
|
4565
4579
|
return e.matches(":state(open)");
|
|
4566
4580
|
} catch {
|
|
@@ -4568,4 +4582,4 @@ function Ye(e) {
|
|
|
4568
4582
|
}
|
|
4569
4583
|
}
|
|
4570
4584
|
//#endregion
|
|
4571
|
-
export { j as a, M as i,
|
|
4585
|
+
export { j as a, M as i, W as n, k as o, B as r, C as s, Q as t };
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -492,6 +492,12 @@ export declare class FlexTable extends LitElement {
|
|
|
492
492
|
private _numberFilterState;
|
|
493
493
|
private _dateFilterState;
|
|
494
494
|
private _emptyFilterState;
|
|
495
|
+
/**
|
|
496
|
+
* From/to bounds as two `u-date-picker`s — the cell editor's control, for the same reason: the native
|
|
497
|
+
* date inputs show the browser's UI language (`10/02/2026` in an English browser) while the table
|
|
498
|
+
* shows ISO. Two pickers, not one `u-date-range-picker`: either bound may be left open ("from this
|
|
499
|
+
* day on"), which a range value cannot say. Each bound's calendar stops at the other bound.
|
|
500
|
+
*/
|
|
495
501
|
private _renderDateFilter;
|
|
496
502
|
private _applyDateFilter;
|
|
497
503
|
private _renderBooleanFilter;
|
package/dist/flex-table.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-h2noRChg.js";
|
|
2
2
|
export { o as FlexTable, e as RowSelectionState, t as UndoStack, n as effectiveAlign, i as exportData, r as flexTableLocale, a as renderCell };
|
package/dist/odata/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SortCriteria } from '../core/sorting.js';
|
|
2
|
+
import type { SourceError } from '../core/source-error.js';
|
|
2
3
|
export interface UseODataSourceOptions {
|
|
3
4
|
pageSize?: number;
|
|
4
5
|
defaultOrderBy?: string;
|
|
@@ -43,7 +44,11 @@ export interface UseODataSourceResult<T> {
|
|
|
43
44
|
data: T[];
|
|
44
45
|
totalCount: number;
|
|
45
46
|
loading: boolean;
|
|
46
|
-
|
|
47
|
+
/**
|
|
48
|
+
* 마지막 요청의 실패, 없으면 `null`. 화면에는 `error.message` 를 그린다. «어떤 실패인가» 는
|
|
49
|
+
* `status`(HTTP) · `code`(서버의 거절 코드) · `details` 로 가른다 — 401 은 `onUnauthorized` 도 부른다.
|
|
50
|
+
*/
|
|
51
|
+
error: SourceError | null;
|
|
47
52
|
page: number;
|
|
48
53
|
setPage: (page: number) => void;
|
|
49
54
|
sortCriteria: SortCriteria[];
|
package/dist/react.d.ts
CHANGED
|
@@ -69,3 +69,4 @@ export { useODataSource } from './odata/use-odata-source.js';
|
|
|
69
69
|
export type { UseODataSourceOptions, UseODataSourceResult } from './odata/types.js';
|
|
70
70
|
export { useArraySource } from './array/use-array-source.js';
|
|
71
71
|
export type { UseArraySourceOptions, UseArraySourceResult } from './array/types.js';
|
|
72
|
+
export type { SourceError, SourceErrorDetail } from './core/source-error.js';
|
package/dist/react.js
CHANGED
|
@@ -1,47 +1,74 @@
|
|
|
1
|
-
import { t as e } from "./flex-table-
|
|
1
|
+
import { t as e } from "./flex-table-h2noRChg.js";
|
|
2
2
|
import { i as t, t as n } from "./query-Dw4iO0ir.js";
|
|
3
3
|
import { t as r } from "./view-DiLr-TdY.js";
|
|
4
4
|
import i, { useCallback as a, useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
|
|
5
5
|
import { createComponent as u } from "@lit/react";
|
|
6
|
+
//#region src/core/source-error.ts
|
|
7
|
+
async function d(e) {
|
|
8
|
+
let t = await e.text().catch(() => ""), n = {
|
|
9
|
+
message: `Request failed (${e.status})`,
|
|
10
|
+
status: e.status
|
|
11
|
+
};
|
|
12
|
+
if (!t) return n;
|
|
13
|
+
let r = t;
|
|
14
|
+
try {
|
|
15
|
+
r = JSON.parse(t);
|
|
16
|
+
} catch {}
|
|
17
|
+
if (n.body = r, !r || typeof r != "object") return n;
|
|
18
|
+
let i = r, a = i.error && typeof i.error == "object" ? i.error : i;
|
|
19
|
+
typeof a.message == "string" && a.message ? n.message = a.message : typeof i.message == "string" && i.message && (n.message = i.message), typeof a.code == "string" && a.code && (n.code = a.code);
|
|
20
|
+
let o = f(a.details);
|
|
21
|
+
return o && (n.details = o), n;
|
|
22
|
+
}
|
|
23
|
+
function f(e) {
|
|
24
|
+
if (!Array.isArray(e)) return;
|
|
25
|
+
let t = e.filter((e) => {
|
|
26
|
+
if (!e || typeof e != "object") return !1;
|
|
27
|
+
let t = e;
|
|
28
|
+
return typeof t.code == "string" && typeof t.message == "string";
|
|
29
|
+
});
|
|
30
|
+
return t.length > 0 ? t : void 0;
|
|
31
|
+
}
|
|
32
|
+
var p = class extends Error {
|
|
33
|
+
constructor(e) {
|
|
34
|
+
super(e.message), this.name = "SourceRequestError", this.failure = e;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function m(e) {
|
|
38
|
+
return e instanceof p ? e.failure : e instanceof Error ? { message: e.message } : { message: String(e) };
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
6
41
|
//#region src/odata/use-odata-source.ts
|
|
7
|
-
function
|
|
8
|
-
let { pageSize: i = 20, defaultOrderBy: s, initialPage: u = 0, initialSearch:
|
|
42
|
+
function h(e, r = {}) {
|
|
43
|
+
let { pageSize: i = 20, defaultOrderBy: s, initialPage: u = 0, initialSearch: f = "", initialSort: h, fixedFilter: g, baseUrl: _, fetcher: v = fetch, onUnauthorized: y, enabled: b = !0 } = r, x = g ? JSON.stringify(g) : "", [S, C] = l([]), [w, T] = l(0), [E, D] = l(!1), [O, k] = l(null), A = t({
|
|
9
44
|
defaultOrderBy: s,
|
|
10
45
|
initialPage: u,
|
|
11
|
-
initialSearch:
|
|
12
|
-
initialSort:
|
|
13
|
-
}), [
|
|
14
|
-
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
}, []),
|
|
18
|
-
|
|
19
|
-
}, []),
|
|
46
|
+
initialSearch: f,
|
|
47
|
+
initialSort: h
|
|
48
|
+
}), [j, M] = l(A.page), [N, P] = l(A.sortCriteria), [F, I] = l(A.search), [L, R] = l(0), [z, B] = l(x);
|
|
49
|
+
x !== z && (B(x), M(0));
|
|
50
|
+
let V = c(null), H = a(() => {
|
|
51
|
+
R((e) => e + 1);
|
|
52
|
+
}, []), U = a((e) => {
|
|
53
|
+
I(e), M(0);
|
|
54
|
+
}, []), W = a((e) => {
|
|
20
55
|
let t = e.detail?.criteria;
|
|
21
|
-
t && (
|
|
56
|
+
t && (P(t), M(0));
|
|
22
57
|
}, []);
|
|
23
58
|
return o(() => {
|
|
24
|
-
if (
|
|
59
|
+
if (V.current?.abort(), !b) return;
|
|
25
60
|
let t = new AbortController();
|
|
26
|
-
|
|
61
|
+
V.current = t, D(!0), k(null);
|
|
27
62
|
let r = n({
|
|
28
|
-
page:
|
|
63
|
+
page: j,
|
|
29
64
|
pageSize: i,
|
|
30
|
-
sortCriteria:
|
|
65
|
+
sortCriteria: N,
|
|
31
66
|
defaultOrderBy: s,
|
|
32
|
-
search:
|
|
33
|
-
fixedFilter:
|
|
34
|
-
}), a = `${
|
|
35
|
-
let n = await
|
|
36
|
-
if (!n.ok)
|
|
37
|
-
n.status === 401 && g && g(n);
|
|
38
|
-
let e = await n.text().catch(() => ""), t = `Request failed (${n.status})`;
|
|
39
|
-
try {
|
|
40
|
-
let n = JSON.parse(e);
|
|
41
|
-
t = n?.error?.message ?? n?.message ?? t;
|
|
42
|
-
} catch {}
|
|
43
|
-
throw Error(t);
|
|
44
|
-
}
|
|
67
|
+
search: F,
|
|
68
|
+
fixedFilter: g
|
|
69
|
+
}), a = `${_ ?? window.location.origin}${e}${r}`, o = async (e) => {
|
|
70
|
+
let n = await v(e, { signal: t.signal });
|
|
71
|
+
if (!n.ok) throw n.status === 401 && y && y(n), new p(await d(n));
|
|
45
72
|
return n.json();
|
|
46
73
|
};
|
|
47
74
|
return (async () => {
|
|
@@ -61,42 +88,42 @@ function d(e, r = {}) {
|
|
|
61
88
|
})().then(({ count: e, rows: n }) => {
|
|
62
89
|
if (t.signal.aborted) return;
|
|
63
90
|
let r = e ?? 0;
|
|
64
|
-
|
|
91
|
+
C(n), T(r), k(null);
|
|
65
92
|
let a = r === 0 ? 0 : Math.ceil(r / i) - 1;
|
|
66
|
-
|
|
93
|
+
j > a && M(a);
|
|
67
94
|
}).catch((e) => {
|
|
68
|
-
t.signal.aborted || e.name !== "AbortError" && (
|
|
95
|
+
t.signal.aborted || e.name !== "AbortError" && (k(m(e)), C([]), T(0));
|
|
69
96
|
}).finally(() => {
|
|
70
|
-
t.signal.aborted ||
|
|
97
|
+
t.signal.aborted || D(!1);
|
|
71
98
|
}), () => t.abort();
|
|
72
99
|
}, [
|
|
73
|
-
|
|
100
|
+
b,
|
|
74
101
|
e,
|
|
75
|
-
|
|
102
|
+
j,
|
|
76
103
|
i,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
104
|
+
N,
|
|
105
|
+
F,
|
|
106
|
+
x,
|
|
80
107
|
s,
|
|
81
|
-
|
|
82
|
-
|
|
108
|
+
L,
|
|
109
|
+
_
|
|
83
110
|
]), {
|
|
84
|
-
data:
|
|
85
|
-
totalCount:
|
|
86
|
-
loading:
|
|
87
|
-
error:
|
|
88
|
-
page:
|
|
89
|
-
setPage:
|
|
90
|
-
sortCriteria:
|
|
91
|
-
onSortChange:
|
|
92
|
-
search:
|
|
93
|
-
setSearch:
|
|
94
|
-
refresh:
|
|
111
|
+
data: S,
|
|
112
|
+
totalCount: w,
|
|
113
|
+
loading: E || !b,
|
|
114
|
+
error: O,
|
|
115
|
+
page: j,
|
|
116
|
+
setPage: M,
|
|
117
|
+
sortCriteria: N,
|
|
118
|
+
onSortChange: W,
|
|
119
|
+
search: F,
|
|
120
|
+
setSearch: U,
|
|
121
|
+
refresh: H
|
|
95
122
|
};
|
|
96
123
|
}
|
|
97
124
|
//#endregion
|
|
98
125
|
//#region src/array/use-array-source.ts
|
|
99
|
-
function
|
|
126
|
+
function g(e, n = {}) {
|
|
100
127
|
let { pageSize: i = 20, defaultOrderBy: o, initialPage: c = 0, initialSearch: u = "", initialSort: d, columns: f, searchFields: p } = n, m = t({
|
|
101
128
|
defaultOrderBy: o,
|
|
102
129
|
initialPage: c,
|
|
@@ -137,7 +164,7 @@ function f(e, n = {}) {
|
|
|
137
164
|
refresh: C
|
|
138
165
|
};
|
|
139
166
|
}
|
|
140
|
-
var
|
|
167
|
+
var _ = u({
|
|
141
168
|
tagName: "flex-table",
|
|
142
169
|
elementClass: e,
|
|
143
170
|
react: i,
|
|
@@ -176,4 +203,4 @@ var p = u({
|
|
|
176
203
|
}
|
|
177
204
|
});
|
|
178
205
|
//#endregion
|
|
179
|
-
export {
|
|
206
|
+
export { _ as FlexTableReact, g as useArraySource, h as useODataSource };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/flex-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"description": "A minimalist, input-centric data grid web component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/flex-table.js",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"build": "npm run typecheck && vite build && tsc --emitDeclarationOnly",
|
|
46
46
|
"build:demo": "vite build --config vite.config.demo.ts",
|
|
47
47
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.test.json",
|
|
48
|
+
"pretest": "node -e \"if(require('fs').existsSync('../../scripts/sibling-dist-check.js'))require('child_process').execFileSync('node',['../../scripts/sibling-dist-check.js'],{stdio:'inherit'})\"",
|
|
48
49
|
"test": "vitest run",
|
|
49
50
|
"test:watch": "vitest",
|
|
50
51
|
"lint": "eslint src/",
|
|
@@ -127,7 +127,7 @@ Server paging from OData or an in-memory array uses the same binding — see `re
|
|
|
127
127
|
- Styles for elements returned by `render` must be passed through the `stylesheets` property
|
|
128
128
|
(constructable `CSSStyleSheet[]`); document CSS does not cross the shadow boundary.
|
|
129
129
|
- `useODataSource` `fetcher` / `onUnauthorized` must be stable references (`useCallback`).
|
|
130
|
-
- Always render `error` from `useODataSource`; a failed request otherwise leaves the grid empty.
|
|
130
|
+
- Always render `error.message` from `useODataSource`; a failed request otherwise leaves the grid empty. Branch on `error.status` / `error.code` rather than parsing the message.
|
|
131
131
|
|
|
132
132
|
## References
|
|
133
133
|
|
|
@@ -73,7 +73,7 @@ function Orders() {
|
|
|
73
73
|
return (
|
|
74
74
|
<>
|
|
75
75
|
<input value={source.search} onChange={(e) => source.setSearch(e.target.value)} />
|
|
76
|
-
{source.error && <p role="alert">{source.error}</p>}
|
|
76
|
+
{source.error && <p role="alert">{source.error.message}</p>}
|
|
77
77
|
<FlexTableReact<Order>
|
|
78
78
|
dataMode="server"
|
|
79
79
|
columns={columns}
|
|
@@ -111,7 +111,7 @@ function Orders() {
|
|
|
111
111
|
|---|---|
|
|
112
112
|
| `data`, `totalCount` | Current page and `@odata.count`; `@odata.nextLink` is followed to fill a page |
|
|
113
113
|
| `loading` | Request in flight |
|
|
114
|
-
| `error` | `
|
|
114
|
+
| `error` | `SourceError \| null` — `{ message, status?, code?, details?, body? }`; render `error.message`, branch on `status` / `code` (OData `error.code`) |
|
|
115
115
|
| `page`, `setPage` | Zero-based |
|
|
116
116
|
| `sortCriteria`, `onSortChange` | Pass `onSortChange` to the table's `sort-change` (resets to page 0) |
|
|
117
117
|
| `search`, `setSearch` | Literal text (resets to page 0) |
|