@iyulab/flex-table 0.50.4 → 0.52.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 +28 -0
- package/dist/core/source-error.d.ts +8 -1
- package/dist/{flex-table-Hx-xTm0e.js → flex-table-CtlqiwD8.js} +14 -10
- package/dist/flex-table.d.ts +4 -0
- package/dist/flex-table.js +2 -2
- package/dist/locale.d.ts +1 -1
- package/dist/react.js +101 -90
- package/package.json +2 -2
- package/skills/iyulab-flex-table/references/react.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.52.0] - 2026-10-07
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Requires `@iyulab/components` 2.8.0** (peer `>=2.8.0`) — for its locale change notification.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`flex-table` follows a runtime locale switch.** `Locale.set()` or registering strings (`flexTableLocale.register`)
|
|
12
|
+
re-renders the table at once — menus, filters, empty states and a cell's error marker (now looked up when drawn). It
|
|
13
|
+
kept the old language until a scroll or data change redrew it. A table detached during the switch catches up when
|
|
14
|
+
attached again.
|
|
15
|
+
|
|
16
|
+
## [0.51.0] - 2026-10-06
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **A data-source failure the server said nothing about is described in the table's language.** With no message in
|
|
21
|
+
the response, `SourceError.message` was a fixed English `Request failed (<status>)`; with no response at all it was
|
|
22
|
+
the transport's exception text, which differs by browser (`Failed to fetch`, `NetworkError when attempting to fetch
|
|
23
|
+
resource.`). Both rendered in English in any locale, and telling them from a server sentence meant matching the
|
|
24
|
+
string's shape. They now come from `flexTableLocale` — `requestFailed` (`{status}` parameter) and `networkFailed`
|
|
25
|
+
(en and ko built in, others via `register`). A server sentence still wins.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `SourceError.cause` — on a failure with no response, the exception the transport threw (for diagnostics).
|
|
30
|
+
|
|
3
31
|
## [0.50.4] - 2026-10-06
|
|
4
32
|
|
|
5
33
|
### Fixed
|
|
@@ -13,7 +13,10 @@ export interface SourceErrorDetail {
|
|
|
13
13
|
* 엿보는 것 말고는 길이 없다.
|
|
14
14
|
*/
|
|
15
15
|
export interface SourceError {
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* 보여 줄 문장 — 서버가 준 메시지가 있으면 그것. 없으면 이 패키지가 채우는 문장이고 로케일(`flexTableLocale`)을
|
|
18
|
+
* 따른다: 응답은 있었으면 `requestFailed`(`Request failed ({status})`), 응답이 없었으면 `networkFailed`.
|
|
19
|
+
*/
|
|
17
20
|
message: string;
|
|
18
21
|
/** HTTP 상태. 응답이 없던 실패(네트워크 오류 · `@odata.nextLink` 검사)에는 없다. */
|
|
19
22
|
status?: number;
|
|
@@ -23,6 +26,8 @@ export interface SourceError {
|
|
|
23
26
|
details?: SourceErrorDetail[];
|
|
24
27
|
/** 응답 본문 — JSON 이면 파싱한 값, 아니면 텍스트. 비어 있으면 없다. */
|
|
25
28
|
body?: unknown;
|
|
29
|
+
/** 응답이 없던 실패에서 전송(`fetcher`)이 던진 예외 — 진단용. 화면에는 `message` 를 그린다. */
|
|
30
|
+
cause?: unknown;
|
|
26
31
|
}
|
|
27
32
|
/** 실패 응답을 `SourceError` 로 읽는다. 본문을 읽을 수 없어도 상태와 기본 문장은 남긴다. */
|
|
28
33
|
export declare function readFailedResponse(res: Response): Promise<SourceError>;
|
|
@@ -31,5 +36,7 @@ export declare class SourceRequestError extends Error {
|
|
|
31
36
|
readonly failure: SourceError;
|
|
32
37
|
constructor(failure: SourceError);
|
|
33
38
|
}
|
|
39
|
+
/** 전송이 응답 없이 던진 실패(네트워크 · 오프라인)를 `SourceError` 로 — 브라우저마다 다른 예외 문구 대신 로케일 문장. */
|
|
40
|
+
export declare function networkFailure(cause: unknown): SourceRequestError;
|
|
34
41
|
/** 잡힌 예외를 `SourceError` 로 — 응답이 있던 실패는 그 구조 그대로, 나머지는 메시지만. */
|
|
35
42
|
export declare function toSourceError(err: unknown): SourceError;
|
|
@@ -1159,7 +1159,9 @@ O.register("en", {
|
|
|
1159
1159
|
notANumber: "Enter a number",
|
|
1160
1160
|
notADate: "Enter a date as YYYY-MM-DD",
|
|
1161
1161
|
notADateTime: "Enter a date and time as YYYY-MM-DD HH:mm",
|
|
1162
|
-
notInList: "Value must be from the existing list"
|
|
1162
|
+
notInList: "Value must be from the existing list",
|
|
1163
|
+
requestFailed: "Request failed ({status})",
|
|
1164
|
+
networkFailed: "Could not reach the server."
|
|
1163
1165
|
}), O.register("ko", {
|
|
1164
1166
|
showHiddenColumns: "숨긴 열 보기",
|
|
1165
1167
|
columnMenu: "열 메뉴",
|
|
@@ -1227,7 +1229,9 @@ O.register("en", {
|
|
|
1227
1229
|
notANumber: "숫자를 입력하세요",
|
|
1228
1230
|
notADate: "날짜를 YYYY-MM-DD 로 입력하세요",
|
|
1229
1231
|
notADateTime: "날짜와 시간을 YYYY-MM-DD HH:mm 으로 입력하세요",
|
|
1230
|
-
notInList: "목록에 있는 값이어야 합니다"
|
|
1232
|
+
notInList: "목록에 있는 값이어야 합니다",
|
|
1233
|
+
requestFailed: "요청이 실패했습니다 ({status})",
|
|
1234
|
+
networkFailed: "서버에 연결하지 못했습니다."
|
|
1231
1235
|
});
|
|
1232
1236
|
var k = (e, t) => O.text(e, t);
|
|
1233
1237
|
//#endregion
|
|
@@ -2439,10 +2443,10 @@ var K = {
|
|
|
2439
2443
|
};
|
|
2440
2444
|
}
|
|
2441
2445
|
connectedCallback() {
|
|
2442
|
-
super.connectedCallback(), this._onScroll = this._onScroll.bind(this), this._onKeyDown = this._onKeyDown.bind(this), this._onDocumentClick = this._onDocumentClick.bind(this), this._onContextMenu = this._onContextMenu.bind(this), this._onDragover = this._onDragover.bind(this), this._onDragleave = this._onDragleave.bind(this), this._onDrop = this._onDrop.bind(this), this.addEventListener("scroll", this._onScroll, { passive: !0 }), this.addEventListener("keydown", this._onKeyDown), this.addEventListener("focus", this._onHostFocus), this.renderRoot.addEventListener("focusin", this._onFocusIn), this.renderRoot.addEventListener("focusout", this._onFocusOut), this.addEventListener("contextmenu", this._onContextMenu), this.addEventListener("dragover", this._onDragover), this.addEventListener("dragleave", this._onDragleave), this.addEventListener("drop", this._onDrop), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "grid"), typeof ResizeObserver < "u" && (this._hostResizeObserver = new ResizeObserver(() => this._measureViewport()), this._hostResizeObserver.observe(this));
|
|
2446
|
+
super.connectedCallback(), this._unsubscribeLocale = l.subscribe(() => this.requestUpdate()), this._detachedLocaleRevision !== void 0 && this._detachedLocaleRevision !== l.revision && this.requestUpdate(), this._detachedLocaleRevision = void 0, this._onScroll = this._onScroll.bind(this), this._onKeyDown = this._onKeyDown.bind(this), this._onDocumentClick = this._onDocumentClick.bind(this), this._onContextMenu = this._onContextMenu.bind(this), this._onDragover = this._onDragover.bind(this), this._onDragleave = this._onDragleave.bind(this), this._onDrop = this._onDrop.bind(this), this.addEventListener("scroll", this._onScroll, { passive: !0 }), this.addEventListener("keydown", this._onKeyDown), this.addEventListener("focus", this._onHostFocus), this.renderRoot.addEventListener("focusin", this._onFocusIn), this.renderRoot.addEventListener("focusout", this._onFocusOut), this.addEventListener("contextmenu", this._onContextMenu), this.addEventListener("dragover", this._onDragover), this.addEventListener("dragleave", this._onDragleave), this.addEventListener("drop", this._onDrop), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "grid"), typeof ResizeObserver < "u" && (this._hostResizeObserver = new ResizeObserver(() => this._measureViewport()), this._hostResizeObserver.observe(this));
|
|
2443
2447
|
}
|
|
2444
2448
|
disconnectedCallback() {
|
|
2445
|
-
super.disconnectedCallback(), this.removeEventListener("scroll", this._onScroll), this.removeEventListener("keydown", this._onKeyDown), this.removeEventListener("focus", this._onHostFocus), this.renderRoot.removeEventListener("focusin", this._onFocusIn), this.renderRoot.removeEventListener("focusout", this._onFocusOut), this.removeEventListener("contextmenu", this._onContextMenu), this.removeEventListener("dragover", this._onDragover), this.removeEventListener("dragleave", this._onDragleave), this.removeEventListener("drop", this._onDrop), document.removeEventListener("click", this._onDocumentClick), document.removeEventListener("mousedown", this._onCommentPopupOutsideClick), this._isDragging = !1, this._wasDrag = !1, this._resizeCleanup &&= (this._resizeCleanup(), null), this._hostResizeObserver &&= (this._hostResizeObserver.disconnect(), null);
|
|
2449
|
+
super.disconnectedCallback(), this._unsubscribeLocale?.(), this._unsubscribeLocale = void 0, this._detachedLocaleRevision = l.revision, this.removeEventListener("scroll", this._onScroll), this.removeEventListener("keydown", this._onKeyDown), this.removeEventListener("focus", this._onHostFocus), this.renderRoot.removeEventListener("focusin", this._onFocusIn), this.renderRoot.removeEventListener("focusout", this._onFocusOut), this.removeEventListener("contextmenu", this._onContextMenu), this.removeEventListener("dragover", this._onDragover), this.removeEventListener("dragleave", this._onDragleave), this.removeEventListener("drop", this._onDrop), document.removeEventListener("click", this._onDocumentClick), document.removeEventListener("mousedown", this._onCommentPopupOutsideClick), this._isDragging = !1, this._wasDrag = !1, this._resizeCleanup &&= (this._resizeCleanup(), null), this._hostResizeObserver &&= (this._hostResizeObserver.disconnect(), null);
|
|
2446
2450
|
}
|
|
2447
2451
|
firstUpdated() {
|
|
2448
2452
|
this._readDensityTokens(), this._measureViewport(), this.shadowRoot && Array.isArray(this.shadowRoot.adoptedStyleSheets) && (this._baseStyleSheets = [...this.shadowRoot.adoptedStyleSheets]), this._syncStylesheets();
|
|
@@ -2689,7 +2693,7 @@ var K = {
|
|
|
2689
2693
|
let { row: n, col: r } = t.position, i = this._toDataIndex(n), a = this.visibleColumns[r], o = t.originalValue;
|
|
2690
2694
|
if (a.autocomplete === "strict" && e != null && e !== "" && !this._getAutocompleteCandidates(a, "").includes(String(e))) {
|
|
2691
2695
|
let t = k("notInList");
|
|
2692
|
-
this._markCellInvalid(n, r,
|
|
2696
|
+
this._markCellInvalid(n, r, () => k("notInList")), this._emit("validation-error", {
|
|
2693
2697
|
row: i,
|
|
2694
2698
|
col: r,
|
|
2695
2699
|
key: a.key,
|
|
@@ -2699,13 +2703,13 @@ var K = {
|
|
|
2699
2703
|
return;
|
|
2700
2704
|
}
|
|
2701
2705
|
if (a.type === "number" && typeof e == "string" || a.type === "date" && typeof e == "string" && f(e) === null || a.type === "datetime" && typeof e == "string" && p(e) === null) {
|
|
2702
|
-
let t =
|
|
2703
|
-
this._markCellInvalid(n, r, t), this._emit("validation-error", {
|
|
2706
|
+
let t = a.type === "number" ? "notANumber" : a.type === "date" ? "notADate" : "notADateTime", o = k(t);
|
|
2707
|
+
this._markCellInvalid(n, r, () => k(t)), this._emit("validation-error", {
|
|
2704
2708
|
row: i,
|
|
2705
2709
|
col: r,
|
|
2706
2710
|
key: a.key,
|
|
2707
2711
|
value: e,
|
|
2708
|
-
error:
|
|
2712
|
+
error: o
|
|
2709
2713
|
});
|
|
2710
2714
|
return;
|
|
2711
2715
|
}
|
|
@@ -3805,7 +3809,7 @@ var K = {
|
|
|
3805
3809
|
}
|
|
3806
3810
|
_isCellInvalid(e, t) {
|
|
3807
3811
|
let n = this._invalidCells.get(this._cellKey(e, t));
|
|
3808
|
-
return n ? n.error : null;
|
|
3812
|
+
return n ? typeof n.error == "function" ? n.error() : n.error : null;
|
|
3809
3813
|
}
|
|
3810
3814
|
_renderDateFilter(e) {
|
|
3811
3815
|
let t = e.type === "datetime", n = this._dateFilterState.get(e.key) ?? {}, r = (e) => e?.slice(0, 10), o = (e) => {
|
|
@@ -4624,4 +4628,4 @@ function $(e) {
|
|
|
4624
4628
|
}
|
|
4625
4629
|
}
|
|
4626
4630
|
//#endregion
|
|
4627
|
-
export { A as a, j as i, W as n, O as o, B as r,
|
|
4631
|
+
export { A as a, T as c, j as i, W as n, O as o, B as r, k as s, Q as t };
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -345,6 +345,9 @@ export declare class FlexTable extends LitElement {
|
|
|
345
345
|
private _rowBoundaryViewportY;
|
|
346
346
|
private get totalBodyHeight();
|
|
347
347
|
private get visibleRange();
|
|
348
|
+
/** 런타임 로캘 전환 구독 — 이 요소는 `LitElement` 를 직접 잇기에 `@iyulab/components` 의 `UElement` 구독을 받지 못한다. */
|
|
349
|
+
private _unsubscribeLocale?;
|
|
350
|
+
private _detachedLocaleRevision?;
|
|
348
351
|
connectedCallback(): void;
|
|
349
352
|
disconnectedCallback(): void;
|
|
350
353
|
protected firstUpdated(): void;
|
|
@@ -556,6 +559,7 @@ export declare class FlexTable extends LitElement {
|
|
|
556
559
|
private _defaultNumState;
|
|
557
560
|
private _renderNumCondRow;
|
|
558
561
|
private _renderNumberFilter;
|
|
562
|
+
/** 셀 오류 표시 — 우리 문장은 «그릴 때 찾는» 함수로(로캘 전환에 따라오게), 소비자 `validator` 문장은 그대로. */
|
|
559
563
|
private _invalidCells;
|
|
560
564
|
private _cellKey;
|
|
561
565
|
private _markCellInvalid;
|
package/dist/flex-table.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e,
|
|
2
|
-
export { o as FlexTable, e as RowSelectionState,
|
|
1
|
+
import { a as e, c as t, i as n, n as r, o as i, r as a, t as o } from "./flex-table-CtlqiwD8.js";
|
|
2
|
+
export { o as FlexTable, e as RowSelectionState, n as UndoStack, r as effectiveAlign, a as exportData, i as flexTableLocale, t as renderCell };
|
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' | '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';
|
|
28
|
+
export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | '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';
|
|
29
29
|
/** 이 패키지의 chrome 문자열 묶음. 소비자가 `register()` 로 언어를 더하거나 문구를 덮을 수 있다. */
|
|
30
30
|
export declare const flexTableLocale: import("@iyulab/components/dist/utilities/Locale.js").LocaleNamespace<FlexTableMessageKey>;
|
|
31
31
|
/** 짧은 조회 별칭 — 렌더 코드가 읽히게 유지한다. */
|
package/dist/react.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as
|
|
3
|
-
import { t as
|
|
4
|
-
import
|
|
5
|
-
import { createComponent as
|
|
1
|
+
import { s as e, t } from "./flex-table-CtlqiwD8.js";
|
|
2
|
+
import { i as n, t as r } from "./query-Dw4iO0ir.js";
|
|
3
|
+
import { t as i } from "./view-DiLr-TdY.js";
|
|
4
|
+
import a, { useCallback as o, useEffect as s, useMemo as c, useRef as l, useState as u } from "react";
|
|
5
|
+
import { createComponent as d } from "@lit/react";
|
|
6
6
|
//#region src/core/source-error.ts
|
|
7
|
-
async function
|
|
8
|
-
let
|
|
9
|
-
message:
|
|
10
|
-
status:
|
|
7
|
+
async function f(t) {
|
|
8
|
+
let n = await t.text().catch(() => ""), r = {
|
|
9
|
+
message: e("requestFailed", { status: t.status }),
|
|
10
|
+
status: t.status
|
|
11
11
|
};
|
|
12
|
-
if (!
|
|
13
|
-
let
|
|
12
|
+
if (!n) return r;
|
|
13
|
+
let i = n;
|
|
14
14
|
try {
|
|
15
|
-
|
|
15
|
+
i = JSON.parse(n);
|
|
16
16
|
} catch {}
|
|
17
|
-
if (
|
|
18
|
-
let
|
|
19
|
-
typeof
|
|
20
|
-
let
|
|
21
|
-
return
|
|
17
|
+
if (r.body = i, !i || typeof i != "object") return r;
|
|
18
|
+
let a = i, o = a.error && typeof a.error == "object" ? a.error : a;
|
|
19
|
+
typeof o.message == "string" && o.message ? r.message = o.message : typeof a.message == "string" && a.message && (r.message = a.message), typeof o.code == "string" && o.code && (r.code = o.code);
|
|
20
|
+
let s = p(o.details);
|
|
21
|
+
return s && (r.details = s), r;
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function p(e) {
|
|
24
24
|
if (!Array.isArray(e)) return;
|
|
25
25
|
let t = e.filter((e) => {
|
|
26
26
|
if (!e || typeof e != "object") return !1;
|
|
@@ -29,56 +29,67 @@ function f(e) {
|
|
|
29
29
|
});
|
|
30
30
|
return t.length > 0 ? t : void 0;
|
|
31
31
|
}
|
|
32
|
-
var
|
|
32
|
+
var m = class extends Error {
|
|
33
33
|
constructor(e) {
|
|
34
34
|
super(e.message), this.name = "SourceRequestError", this.failure = e;
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
function
|
|
38
|
-
return
|
|
37
|
+
function h(t) {
|
|
38
|
+
return new m({
|
|
39
|
+
message: e("networkFailed"),
|
|
40
|
+
cause: t
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function g(e) {
|
|
44
|
+
return e instanceof m ? e.failure : e instanceof Error ? { message: e.message } : { message: String(e) };
|
|
39
45
|
}
|
|
40
46
|
//#endregion
|
|
41
47
|
//#region src/odata/use-odata-source.ts
|
|
42
|
-
function
|
|
43
|
-
let { pageSize: i = 20, defaultOrderBy:
|
|
44
|
-
defaultOrderBy:
|
|
45
|
-
initialPage:
|
|
46
|
-
initialSearch:
|
|
47
|
-
initialSort:
|
|
48
|
-
}), [
|
|
49
|
-
|
|
50
|
-
let
|
|
51
|
-
|
|
52
|
-
}, []),
|
|
53
|
-
|
|
54
|
-
}, []),
|
|
48
|
+
function _(e, t = {}) {
|
|
49
|
+
let { pageSize: i = 20, defaultOrderBy: a, initialPage: c = 0, initialSearch: d = "", initialSort: p, fixedFilter: _, baseUrl: v, fetcher: y = fetch, onUnauthorized: b, enabled: x = !0 } = t, S = _ ? JSON.stringify(_) : "", [C, w] = u([]), [T, E] = u(0), [D, O] = u(!0), [k, A] = u(null), j = n({
|
|
50
|
+
defaultOrderBy: a,
|
|
51
|
+
initialPage: c,
|
|
52
|
+
initialSearch: d,
|
|
53
|
+
initialSort: p
|
|
54
|
+
}), [M, N] = u(j.page), [P, F] = u(j.sortCriteria), [I, L] = u(j.search), [R, z] = u(0), [B, V] = u(S);
|
|
55
|
+
S !== B && (V(S), N(0));
|
|
56
|
+
let H = l(null), U = o(() => {
|
|
57
|
+
z((e) => e + 1);
|
|
58
|
+
}, []), W = o((e) => {
|
|
59
|
+
L(e), N(0);
|
|
60
|
+
}, []), G = o((e) => {
|
|
55
61
|
let t = e.detail?.criteria;
|
|
56
|
-
t && (
|
|
62
|
+
t && (F(t), N(0));
|
|
57
63
|
}, []);
|
|
58
|
-
return
|
|
59
|
-
if (
|
|
64
|
+
return s(() => {
|
|
65
|
+
if (H.current?.abort(), !x) return;
|
|
60
66
|
let t = new AbortController();
|
|
61
|
-
|
|
62
|
-
let
|
|
63
|
-
page:
|
|
67
|
+
H.current = t, O(!0), A(null);
|
|
68
|
+
let n = r({
|
|
69
|
+
page: M,
|
|
64
70
|
pageSize: i,
|
|
65
|
-
sortCriteria:
|
|
66
|
-
defaultOrderBy:
|
|
67
|
-
search:
|
|
68
|
-
fixedFilter:
|
|
69
|
-
}),
|
|
70
|
-
let n
|
|
71
|
-
|
|
71
|
+
sortCriteria: P,
|
|
72
|
+
defaultOrderBy: a,
|
|
73
|
+
search: I,
|
|
74
|
+
fixedFilter: _
|
|
75
|
+
}), o = `${v ?? window.location.origin}${e}${n}`, s = async (e) => {
|
|
76
|
+
let n;
|
|
77
|
+
try {
|
|
78
|
+
n = await y(e, { signal: t.signal });
|
|
79
|
+
} catch (e) {
|
|
80
|
+
throw e?.name === "AbortError" ? e : h(e);
|
|
81
|
+
}
|
|
82
|
+
if (!n.ok) throw n.status === 401 && b && b(n), new m(await f(n));
|
|
72
83
|
return n.json();
|
|
73
84
|
};
|
|
74
85
|
return (async () => {
|
|
75
|
-
let e = await o
|
|
86
|
+
let e = await s(o), t = [...e.value ?? e], n = new URL(o).origin, r = /* @__PURE__ */ new Set([o]), a = o, c = e["@odata.nextLink"];
|
|
76
87
|
for (; typeof c == "string" && c && t.length < i;) {
|
|
77
|
-
let e = new URL(c,
|
|
88
|
+
let e = new URL(c, a);
|
|
78
89
|
if (e.origin !== n) throw Error(`OData nextLink points outside the source origin (${e.origin})`);
|
|
79
|
-
if (
|
|
80
|
-
r.add(
|
|
81
|
-
let i = await
|
|
90
|
+
if (a = e.toString(), r.has(a)) throw Error(`OData nextLink repeats an already-read page (${a})`);
|
|
91
|
+
r.add(a);
|
|
92
|
+
let i = await s(a);
|
|
82
93
|
t.push(...i.value ?? []), c = i["@odata.nextLink"];
|
|
83
94
|
}
|
|
84
95
|
return {
|
|
@@ -88,57 +99,57 @@ function h(e, r = {}) {
|
|
|
88
99
|
})().then(({ count: e, rows: n }) => {
|
|
89
100
|
if (t.signal.aborted) return;
|
|
90
101
|
let r = e ?? 0;
|
|
91
|
-
|
|
102
|
+
w(n), E(r), A(null);
|
|
92
103
|
let a = r === 0 ? 0 : Math.ceil(r / i) - 1;
|
|
93
|
-
|
|
104
|
+
M > a && N(a);
|
|
94
105
|
}).catch((e) => {
|
|
95
|
-
t.signal.aborted || e.name !== "AbortError" && (
|
|
106
|
+
t.signal.aborted || e.name !== "AbortError" && (A(g(e)), w([]), E(0));
|
|
96
107
|
}).finally(() => {
|
|
97
|
-
t.signal.aborted ||
|
|
108
|
+
t.signal.aborted || O(!1);
|
|
98
109
|
}), () => t.abort();
|
|
99
110
|
}, [
|
|
100
|
-
|
|
111
|
+
x,
|
|
101
112
|
e,
|
|
102
|
-
|
|
113
|
+
M,
|
|
103
114
|
i,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
115
|
+
P,
|
|
116
|
+
I,
|
|
117
|
+
S,
|
|
118
|
+
a,
|
|
119
|
+
R,
|
|
120
|
+
v
|
|
110
121
|
]), {
|
|
111
|
-
data:
|
|
112
|
-
totalCount:
|
|
113
|
-
loading:
|
|
114
|
-
error:
|
|
115
|
-
page:
|
|
116
|
-
setPage:
|
|
117
|
-
sortCriteria:
|
|
118
|
-
onSortChange:
|
|
119
|
-
search:
|
|
120
|
-
setSearch:
|
|
121
|
-
refresh:
|
|
122
|
+
data: C,
|
|
123
|
+
totalCount: T,
|
|
124
|
+
loading: D || !x,
|
|
125
|
+
error: k,
|
|
126
|
+
page: M,
|
|
127
|
+
setPage: N,
|
|
128
|
+
sortCriteria: P,
|
|
129
|
+
onSortChange: G,
|
|
130
|
+
search: I,
|
|
131
|
+
setSearch: W,
|
|
132
|
+
refresh: U
|
|
122
133
|
};
|
|
123
134
|
}
|
|
124
135
|
//#endregion
|
|
125
136
|
//#region src/array/use-array-source.ts
|
|
126
|
-
function
|
|
127
|
-
let { pageSize:
|
|
128
|
-
defaultOrderBy:
|
|
129
|
-
initialPage:
|
|
130
|
-
initialSearch:
|
|
137
|
+
function v(e, t = {}) {
|
|
138
|
+
let { pageSize: r = 20, defaultOrderBy: a, initialPage: s = 0, initialSearch: l = "", initialSort: d, columns: f, searchFields: p } = t, m = n({
|
|
139
|
+
defaultOrderBy: a,
|
|
140
|
+
initialPage: s,
|
|
141
|
+
initialSearch: l,
|
|
131
142
|
initialSort: d
|
|
132
|
-
}), [h, g] =
|
|
143
|
+
}), [h, g] = u(m.page), [_, v] = u(m.sortCriteria), [y, b] = u(m.search), x = o((e) => {
|
|
133
144
|
b(e), g(0);
|
|
134
|
-
}, []), S =
|
|
145
|
+
}, []), S = o((e) => {
|
|
135
146
|
let t = e.detail?.criteria;
|
|
136
147
|
t && (v(t), g(0));
|
|
137
|
-
}, []), C =
|
|
148
|
+
}, []), C = o(() => {}, []), { data: w, totalCount: T } = c(() => i(e, {
|
|
138
149
|
search: y,
|
|
139
150
|
sortCriteria: _,
|
|
140
151
|
page: h,
|
|
141
|
-
pageSize:
|
|
152
|
+
pageSize: r,
|
|
142
153
|
columns: f,
|
|
143
154
|
searchFields: p
|
|
144
155
|
}), [
|
|
@@ -146,10 +157,10 @@ function g(e, n = {}) {
|
|
|
146
157
|
y,
|
|
147
158
|
_,
|
|
148
159
|
h,
|
|
149
|
-
|
|
160
|
+
r,
|
|
150
161
|
f,
|
|
151
162
|
p
|
|
152
|
-
]), E = T === 0 ? 0 : Math.ceil(T /
|
|
163
|
+
]), E = T === 0 ? 0 : Math.ceil(T / r) - 1;
|
|
153
164
|
return h > E && g(E), {
|
|
154
165
|
data: w,
|
|
155
166
|
totalCount: T,
|
|
@@ -164,10 +175,10 @@ function g(e, n = {}) {
|
|
|
164
175
|
refresh: C
|
|
165
176
|
};
|
|
166
177
|
}
|
|
167
|
-
var
|
|
178
|
+
var y = d({
|
|
168
179
|
tagName: "flex-table",
|
|
169
|
-
elementClass:
|
|
170
|
-
react:
|
|
180
|
+
elementClass: t,
|
|
181
|
+
react: a,
|
|
171
182
|
events: {
|
|
172
183
|
onCellSelect: "cell-select",
|
|
173
184
|
onCellEditCommit: "cell-edit-commit",
|
|
@@ -203,4 +214,4 @@ var _ = u({
|
|
|
203
214
|
}
|
|
204
215
|
});
|
|
205
216
|
//#endregion
|
|
206
|
-
export {
|
|
217
|
+
export { y as FlexTableReact, v as useArraySource, _ as useODataSource };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/flex-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.52.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.8.0",
|
|
78
78
|
"@lit/react": "^1.0.8",
|
|
79
79
|
"react": "^18.0.0 || ^19.0.0"
|
|
80
80
|
},
|
|
@@ -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, or no answer yet (true from the first render until the first response settles, and while `enabled: false`) — so `!loading && totalCount === 0` means "no results" |
|
|
114
|
-
| `error` | `SourceError \| null` — `{ message, status?, code?, details?, body? }`; render `error.message`, branch on `status` / `code` (OData `error.code`) |
|
|
114
|
+
| `error` | `SourceError \| null` — `{ message, status?, code?, details?, body?, cause? }`; render `error.message`, branch on `status` / `code` (OData `error.code`). `message` is the server's sentence when it sent one; otherwise this package's, in the `flexTableLocale` language — `requestFailed` (`Request failed ({status})`) when a response came back, `networkFailed` when none did (the transport's exception is in `cause`) |
|
|
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) |
|