@iyulab/flex-table 0.58.0 → 0.60.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 +39 -0
- package/README.md +28 -6
- package/dist/array/index.d.ts +3 -0
- package/dist/array/index.js +46 -38
- package/dist/array/source.d.ts +3 -0
- package/dist/array/types.d.ts +3 -0
- package/dist/array/view.d.ts +6 -0
- package/dist/core/fetch-all.d.ts +14 -0
- package/dist/core/source-error.d.ts +13 -1
- package/dist/events.d.ts +14 -4
- package/dist/fetch-all-J37bOtgc.js +86 -0
- package/dist/{flex-table-B1W8VEBa.js → flex-table-kM69-hSo.js} +157 -145
- package/dist/flex-table.d.ts +22 -9
- package/dist/flex-table.js +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/{locale-Cfm-vJji.js → locale-D9g0ksXq.js} +4 -2
- package/dist/locale.d.ts +1 -1
- package/dist/odata/index.d.ts +4 -0
- package/dist/odata/index.js +5 -5
- package/dist/odata/query.d.ts +7 -3
- package/dist/odata/source.d.ts +9 -0
- package/dist/odata/types.d.ts +3 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +75 -62
- package/dist/source-DNPtWmC3.js +202 -0
- package/dist/{view-DiLr-TdY.js → view-BtoXdUGF.js} +13 -2
- package/package.json +2 -2
- package/skills/iyulab-flex-table/SKILL.md +2 -1
- package/skills/iyulab-flex-table/references/api.md +9 -5
- package/skills/iyulab-flex-table/references/react.md +2 -1
- package/dist/query-Dw4iO0ir.js +0 -37
- package/dist/source-DOue0Ti3.js +0 -223
package/dist/flex-table.d.ts
CHANGED
|
@@ -7,6 +7,17 @@ import type { FilterPredicate } from './core/filtering.js';
|
|
|
7
7
|
import type { ColumnDefinition, DataRow, SelectionMode, DataMode } from './models/types.js';
|
|
8
8
|
import type { FlexTableEventMap } from './events.js';
|
|
9
9
|
import type { TemplateResult } from 'lit';
|
|
10
|
+
/**
|
|
11
|
+
* 표 내보내기의 대상 — 선택 범위(`selectionOnly`) 또는 바깥에서 준 행(`rows`, 예: `await source.fetchAll()`). 둘은
|
|
12
|
+
* 함께 쓰지 않는다(바깥 행에는 표의 선택 범위가 없다).
|
|
13
|
+
*/
|
|
14
|
+
export type TableExportOptions = {
|
|
15
|
+
selectionOnly?: boolean;
|
|
16
|
+
rows?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
rows: DataRow[];
|
|
19
|
+
selectionOnly?: undefined;
|
|
20
|
+
};
|
|
10
21
|
export declare class FlexTable extends LitElement {
|
|
11
22
|
static styles: import("lit").CSSResult;
|
|
12
23
|
columns: ColumnDefinition[];
|
|
@@ -313,23 +324,25 @@ export declare class FlexTable extends LitElement {
|
|
|
313
324
|
* Export table data to string in the specified format. Synchronous — XLSX comes back as an
|
|
314
325
|
* uncompressed workbook; use `exportToBlob` for a compressed one.
|
|
315
326
|
* @param options.selectionOnly - Export only the currently selected range
|
|
327
|
+
* @param options.rows - Export these rows with the table's visible columns instead of the rows it holds —
|
|
328
|
+
* a server-paged table holds one page, so pass `await source.fetchAll()` for the whole result
|
|
316
329
|
*/
|
|
317
|
-
exportToString(format: ExportFormat, options?:
|
|
318
|
-
selectionOnly?: boolean;
|
|
319
|
-
}): string | Uint8Array<ArrayBuffer>;
|
|
330
|
+
exportToString(format: ExportFormat, options?: TableExportOptions): string | Uint8Array<ArrayBuffer>;
|
|
320
331
|
/**
|
|
321
332
|
* Export table data as a `Blob` of the format's MIME type. XLSX is DEFLATE-compressed.
|
|
322
|
-
* @param options
|
|
333
|
+
* @param options - `selectionOnly` or `rows`, as for `exportToString`
|
|
323
334
|
*/
|
|
324
|
-
exportToBlob(format: ExportFormat, options?:
|
|
325
|
-
selectionOnly?: boolean;
|
|
326
|
-
}): Promise<Blob>;
|
|
335
|
+
exportToBlob(format: ExportFormat, options?: TableExportOptions): Promise<Blob>;
|
|
327
336
|
/**
|
|
328
337
|
* Export table data and trigger file download. XLSX is DEFLATE-compressed; the promise settles
|
|
329
338
|
* once the download has been handed to the browser.
|
|
339
|
+
* @param options - `selectionOnly` or `rows`, as for `exportToString`
|
|
340
|
+
*/
|
|
341
|
+
exportToFile(format: ExportFormat, filename?: string, options?: TableExportOptions): Promise<void>;
|
|
342
|
+
/**
|
|
343
|
+
* 내보낼 행·열 — 행을 받았으면 그 행 · 보이는 열(서버 페이지 표가 «조회 결과 전체» 를 내보내는 길 — 열과 형식은 표,
|
|
344
|
+
* 질의는 소스가 안다), 선택만이면 선택 범위(없으면 `null`), 아니면 정렬 순서의 전체 행 · 보이는 열.
|
|
330
345
|
*/
|
|
331
|
-
exportToFile(format: ExportFormat, filename?: string): Promise<void>;
|
|
332
|
-
/** 내보낼 행·열 — 선택만이면 선택 범위(없으면 `null`), 아니면 정렬 순서의 전체 행 · 보이는 열. */
|
|
333
346
|
private _exportSlice;
|
|
334
347
|
/**
|
|
335
348
|
* Set a comment on the cell at the given data index and column key.
|
package/dist/flex-table.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as e,
|
|
2
|
-
import { t as
|
|
3
|
-
export {
|
|
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-kM69-hSo.js";
|
|
2
|
+
import { t as c } from "./locale-D9g0ksXq.js";
|
|
3
|
+
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, t as renderCell };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { FlexTable } from './flex-table.js';
|
|
2
|
+
export type { TableExportOptions } from './flex-table.js';
|
|
2
3
|
export type { ColumnDefinition, ColumnType, ColumnAlign, DataRow, CellRenderer, CellEditor, CellValidator, SelectionMode, DataMode, CellStyle, ConditionalRule } from './models/types.js';
|
|
3
4
|
export { effectiveAlign } from './models/types.js';
|
|
4
5
|
export type { CellPosition, CellRange } from './core/selection.js';
|
|
@@ -9,7 +10,7 @@ export { RowSelectionState } from './core/row-selection.js';
|
|
|
9
10
|
export { UndoStack } from './core/undo.js';
|
|
10
11
|
export type { UndoAction } from './core/undo.js';
|
|
11
12
|
export type { ExportFormat } from './export/export.js';
|
|
12
|
-
export { exportData } from './export/export.js';
|
|
13
|
+
export { exportData, exportDataBlob, downloadBlob } from './export/export.js';
|
|
13
14
|
export { renderCell } from './renderers/cell-renderer.js';
|
|
14
15
|
export { flexTableLocale } from './locale.js';
|
|
15
16
|
export type { FlexTableMessageKey } from './locale.js';
|
|
@@ -72,7 +72,8 @@ t.register("en", {
|
|
|
72
72
|
notADateTime: "Enter a date and time as YYYY-MM-DD HH:mm",
|
|
73
73
|
notInList: "Value must be from the existing list",
|
|
74
74
|
requestFailed: "Request failed ({status})",
|
|
75
|
-
networkFailed: "Could not reach the server."
|
|
75
|
+
networkFailed: "Could not reach the server.",
|
|
76
|
+
tooManyRows: "More than {maxRows} rows match — narrow the search or filter first."
|
|
76
77
|
}), t.register("ko", {
|
|
77
78
|
showHiddenColumns: "숨긴 열 보기",
|
|
78
79
|
columnMenu: "열 메뉴",
|
|
@@ -144,7 +145,8 @@ t.register("en", {
|
|
|
144
145
|
notADateTime: "날짜와 시간을 YYYY-MM-DD HH:mm 으로 입력하세요",
|
|
145
146
|
notInList: "목록에 있는 값이어야 합니다",
|
|
146
147
|
requestFailed: "요청이 실패했습니다 ({status})",
|
|
147
|
-
networkFailed: "서버에 연결하지 못했습니다."
|
|
148
|
+
networkFailed: "서버에 연결하지 못했습니다.",
|
|
149
|
+
tooManyRows: "조건에 맞는 행이 {maxRows}개를 넘습니다 — 검색이나 필터로 먼저 좁혀 주세요."
|
|
148
150
|
});
|
|
149
151
|
var n = (e, n) => t.text(e, n);
|
|
150
152
|
//#endregion
|
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';
|
|
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';
|
|
29
29
|
/** 이 패키지의 chrome 문자열 묶음. 소비자가 `register()` 로 언어를 더하거나 문구를 덮을 수 있다. */
|
|
30
30
|
export declare const flexTableLocale: import("@iyulab/components/dist/utilities/Locale.js").LocaleNamespace<FlexTableMessageKey>;
|
|
31
31
|
/** 짧은 조회 별칭 — 렌더 코드가 읽히게 유지한다. */
|
package/dist/odata/index.d.ts
CHANGED
|
@@ -3,3 +3,7 @@ export type { ODataQueryState } from './query.js';
|
|
|
3
3
|
export { createODataSource } from './source.js';
|
|
4
4
|
export type { ODataSource, ODataSourceOptions, ODataSourceState } from './source.js';
|
|
5
5
|
export { ODataSourceController } from './controller.js';
|
|
6
|
+
export { DEFAULT_MAX_ROWS } from '../core/fetch-all.js';
|
|
7
|
+
export type { FetchAllOptions } from '../core/fetch-all.js';
|
|
8
|
+
export { SourceRequestError, RowLimitError } from '../core/source-error.js';
|
|
9
|
+
export type { SourceError, SourceErrorDetail } from '../core/source-error.js';
|
package/dist/odata/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { c as e, l as t, n, r, s as i, t as a } from "../fetch-all-J37bOtgc.js";
|
|
2
|
+
import { t as o } from "../source-DNPtWmC3.js";
|
|
3
3
|
//#region src/odata/controller.ts
|
|
4
|
-
var
|
|
4
|
+
var s = class {
|
|
5
5
|
constructor(e, t, n = {}) {
|
|
6
|
-
this.host = e, this.source = typeof t == "string" ?
|
|
6
|
+
this.host = e, this.source = typeof t == "string" ? o(t, n) : t, e.addController(this);
|
|
7
7
|
}
|
|
8
8
|
get state() {
|
|
9
9
|
return this.source.getState();
|
|
@@ -16,4 +16,4 @@ var i = class {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
|
-
export {
|
|
19
|
+
export { a as DEFAULT_MAX_ROWS, s as ODataSourceController, n as RowLimitError, r as SourceRequestError, i as buildODataQuery, e as buildSearchExpression, o as createODataSource, t as parseOrderBy };
|
package/dist/odata/query.d.ts
CHANGED
|
@@ -51,9 +51,13 @@ export declare function resolveInitialState(options: InitialSourceStateOptions):
|
|
|
51
51
|
export declare function parseOrderBy(orderBy: string): SortCriteria[];
|
|
52
52
|
/** `buildODataQuery` 가 읽는 표 상태 — `useODataSource` 가 요청마다 넘기는 것과 같은 모양. */
|
|
53
53
|
export interface ODataQueryState {
|
|
54
|
-
/** 0부터 세는 페이지 번호. */
|
|
55
|
-
page
|
|
56
|
-
|
|
54
|
+
/** 0부터 세는 페이지 번호. `pageSize` 와 함께 `$skip` 이 된다. */
|
|
55
|
+
page?: number;
|
|
56
|
+
/**
|
|
57
|
+
* 한 페이지의 행 수(`$top`). **생략하면 `$top`·`$skip` 없이** 조회 결과 전체를 묻는다 — 서버가 응답을 나누면
|
|
58
|
+
* (`@odata.nextLink`) 끝까지 따라가는 것은 부르는 쪽 몫이다(`ODataSource.fetchAll`).
|
|
59
|
+
*/
|
|
60
|
+
pageSize?: number;
|
|
57
61
|
sortCriteria?: SortCriteria[];
|
|
58
62
|
/** 정렬 기준이 비었을 때 쓰는 `$orderby` 문자열. */
|
|
59
63
|
defaultOrderBy?: string;
|
package/dist/odata/source.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SortCriteria } from '../core/sorting.js';
|
|
2
2
|
import { type SourceError } from '../core/source-error.js';
|
|
3
|
+
import { type FetchAllOptions } from '../core/fetch-all.js';
|
|
3
4
|
/** OData 소스의 설정 — `useODataSource` 의 옵션과 같다(`initial*` 은 만들 때만 읽는다). */
|
|
4
5
|
export interface ODataSourceOptions {
|
|
5
6
|
pageSize?: number;
|
|
@@ -78,6 +79,14 @@ export interface ODataSource<T> {
|
|
|
78
79
|
refresh(): void;
|
|
79
80
|
/** 설정을 바꾼다 — 요청 조건이 바뀌면 다시 읽고(`fixedFilter` 값이 바뀌면 첫 장으로), `fetcher`·`onUnauthorized` 는 다음 요청부터. */
|
|
80
81
|
update(url: string, options?: ODataSourceOptions): void;
|
|
82
|
+
/**
|
|
83
|
+
* **지금 조건(정렬 · 검색 · 고정 필터)의 결과 전체**를 읽는다 — 페이지 없이, 서버가 응답을 나누면(`@odata.nextLink`)
|
|
84
|
+
* 끝까지 따라가서. 내보내기처럼 «이 목록이 보여 주는 조회 결과 전부» 가 필요할 때 쓴다. 상태(`data`·`page` …)는
|
|
85
|
+
* 건드리지 않고 구독도 요구하지 않는다(`enabled: false` 여도 읽는다 — 부르는 것이 곧 요청이다).
|
|
86
|
+
*
|
|
87
|
+
* 실패는 `SourceRequestError`(`failure` 가 `SourceError`)로, 상한을 넘으면 그 하위 `RowLimitError` 로 거절한다.
|
|
88
|
+
*/
|
|
89
|
+
fetchAll(options?: FetchAllOptions): Promise<T[]>;
|
|
81
90
|
}
|
|
82
91
|
/** OData v4 서버 사이드 데이터 소스를 만든다. flex-table 의 `dataMode="server"` 와 함께 쓴다. */
|
|
83
92
|
export declare function createODataSource<T = Record<string, unknown>>(url: string, options?: ODataSourceOptions): ODataSource<T>;
|
package/dist/odata/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SortCriteria } from '../core/sorting.js';
|
|
2
2
|
import type { ODataSourceOptions, ODataSourceState } from './source.js';
|
|
3
|
+
import type { FetchAllOptions } from '../core/fetch-all.js';
|
|
3
4
|
/** `useODataSource` 의 옵션 — 프레임워크 중립 소스(`createODataSource`)의 설정과 같다. `initial*` 은 첫 렌더에서만 읽힌다. */
|
|
4
5
|
export type UseODataSourceOptions = ODataSourceOptions;
|
|
5
6
|
export interface UseODataSourceResult<T> extends ODataSourceState<T> {
|
|
@@ -11,5 +12,7 @@ export interface UseODataSourceResult<T> extends ODataSourceState<T> {
|
|
|
11
12
|
/** 검색어를 바꾸고 첫 장으로 간다. */
|
|
12
13
|
setSearch: (term: string) => void;
|
|
13
14
|
refresh: () => void;
|
|
15
|
+
/** 지금 조건의 결과 전체 — 페이지 없이, `@odata.nextLink` 를 끝까지(`ODataSource.fetchAll`). 내보내기에 쓴다. */
|
|
16
|
+
fetchAll: (options?: FetchAllOptions) => Promise<T[]>;
|
|
14
17
|
}
|
|
15
18
|
export type { SortCriteria };
|
package/dist/react.d.ts
CHANGED
|
@@ -71,3 +71,5 @@ export type { UseODataSourceOptions, UseODataSourceResult } from './odata/types.
|
|
|
71
71
|
export { useArraySource } from './array/use-array-source.js';
|
|
72
72
|
export type { UseArraySourceOptions, UseArraySourceResult } from './array/types.js';
|
|
73
73
|
export type { SourceError, SourceErrorDetail } from './core/source-error.js';
|
|
74
|
+
export { SourceRequestError, RowLimitError } from './core/source-error.js';
|
|
75
|
+
export type { FetchAllOptions } from './core/fetch-all.js';
|
package/dist/react.js
CHANGED
|
@@ -1,81 +1,94 @@
|
|
|
1
|
-
import { t as e } from "./flex-table-
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as
|
|
5
|
-
import
|
|
6
|
-
import { createComponent as
|
|
1
|
+
import { t as e } from "./flex-table-kM69-hSo.js";
|
|
2
|
+
import { n as t, r as n, u as r } from "./fetch-all-J37bOtgc.js";
|
|
3
|
+
import { t as i } from "./source-DNPtWmC3.js";
|
|
4
|
+
import { n as a, t as o } from "./view-BtoXdUGF.js";
|
|
5
|
+
import s, { useCallback as c, useEffect as l, useMemo as u, useState as d, useSyncExternalStore as f } from "react";
|
|
6
|
+
import { createComponent as p } from "@lit/react";
|
|
7
7
|
//#region src/odata/use-odata-source.ts
|
|
8
|
-
function
|
|
9
|
-
let [
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
function m(e, t = {}) {
|
|
9
|
+
let [n] = d(() => i(e, t));
|
|
10
|
+
l(() => {
|
|
11
|
+
n.update(e, t);
|
|
12
12
|
});
|
|
13
|
-
let
|
|
13
|
+
let r = f(n.subscribe, n.getState, n.getState), a = c((e) => {
|
|
14
14
|
let t = e.detail?.criteria;
|
|
15
|
-
t &&
|
|
16
|
-
}, [
|
|
15
|
+
t && n.setSort(t);
|
|
16
|
+
}, [n]);
|
|
17
17
|
return {
|
|
18
|
-
...
|
|
19
|
-
setPage:
|
|
20
|
-
setPageSize:
|
|
21
|
-
onSortChange:
|
|
22
|
-
setSearch:
|
|
23
|
-
refresh:
|
|
18
|
+
...r,
|
|
19
|
+
setPage: n.setPage,
|
|
20
|
+
setPageSize: n.setPageSize,
|
|
21
|
+
onSortChange: a,
|
|
22
|
+
setSearch: n.setSearch,
|
|
23
|
+
refresh: n.refresh,
|
|
24
|
+
fetchAll: n.fetchAll
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
//#endregion
|
|
27
28
|
//#region src/array/use-array-source.ts
|
|
28
|
-
function
|
|
29
|
-
let { pageSize:
|
|
30
|
-
defaultOrderBy:
|
|
31
|
-
initialPage:
|
|
32
|
-
initialSearch:
|
|
33
|
-
initialSort:
|
|
34
|
-
}), [
|
|
35
|
-
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
}, []),
|
|
39
|
-
|
|
40
|
-
}, []),
|
|
29
|
+
function h(e, t = {}) {
|
|
30
|
+
let { pageSize: n = 20, defaultOrderBy: i, initialPage: s = 0, initialSearch: l = "", initialSort: f, columns: p, searchFields: m } = t, h = r({
|
|
31
|
+
defaultOrderBy: i,
|
|
32
|
+
initialPage: s,
|
|
33
|
+
initialSearch: l,
|
|
34
|
+
initialSort: f
|
|
35
|
+
}), [g, _] = d(h.page), [v, y] = d(h.sortCriteria), [b, x] = d(h.search), [S, C] = d(n), [w, T] = d(n);
|
|
36
|
+
n !== w && (T(n), C(n), _(0));
|
|
37
|
+
let E = c((e) => {
|
|
38
|
+
C(e), _(0);
|
|
39
|
+
}, []), D = c((e) => {
|
|
40
|
+
x(e), _(0);
|
|
41
|
+
}, []), O = c((e) => {
|
|
41
42
|
let t = e.detail?.criteria;
|
|
42
|
-
t && (
|
|
43
|
-
}, []),
|
|
44
|
-
search:
|
|
45
|
-
sortCriteria:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
t && (y(t), _(0));
|
|
44
|
+
}, []), k = c(() => {}, []), A = c((t) => a(e, {
|
|
45
|
+
search: b,
|
|
46
|
+
sortCriteria: v,
|
|
47
|
+
columns: p,
|
|
48
|
+
searchFields: m
|
|
49
|
+
}, t), [
|
|
50
|
+
e,
|
|
51
|
+
b,
|
|
52
|
+
v,
|
|
53
|
+
p,
|
|
54
|
+
m
|
|
55
|
+
]), { data: j, totalCount: M } = u(() => o(e, {
|
|
56
|
+
search: b,
|
|
57
|
+
sortCriteria: v,
|
|
58
|
+
page: g,
|
|
59
|
+
pageSize: S,
|
|
60
|
+
columns: p,
|
|
61
|
+
searchFields: m
|
|
50
62
|
}), [
|
|
51
63
|
e,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
]),
|
|
59
|
-
return
|
|
60
|
-
data:
|
|
61
|
-
totalCount:
|
|
64
|
+
b,
|
|
65
|
+
v,
|
|
66
|
+
g,
|
|
67
|
+
S,
|
|
68
|
+
p,
|
|
69
|
+
m
|
|
70
|
+
]), N = M === 0 ? 0 : Math.ceil(M / S) - 1;
|
|
71
|
+
return g > N && _(N), {
|
|
72
|
+
data: j,
|
|
73
|
+
totalCount: M,
|
|
62
74
|
loading: !1,
|
|
63
75
|
error: null,
|
|
64
|
-
page:
|
|
65
|
-
setPage:
|
|
66
|
-
pageSize:
|
|
67
|
-
setPageSize:
|
|
68
|
-
sortCriteria:
|
|
69
|
-
onSortChange:
|
|
70
|
-
search:
|
|
71
|
-
setSearch:
|
|
72
|
-
refresh:
|
|
76
|
+
page: g,
|
|
77
|
+
setPage: _,
|
|
78
|
+
pageSize: S,
|
|
79
|
+
setPageSize: E,
|
|
80
|
+
sortCriteria: v,
|
|
81
|
+
onSortChange: O,
|
|
82
|
+
search: b,
|
|
83
|
+
setSearch: D,
|
|
84
|
+
refresh: k,
|
|
85
|
+
fetchAll: A
|
|
73
86
|
};
|
|
74
87
|
}
|
|
75
|
-
var
|
|
88
|
+
var g = p({
|
|
76
89
|
tagName: "flex-table",
|
|
77
90
|
elementClass: e,
|
|
78
|
-
react:
|
|
91
|
+
react: s,
|
|
79
92
|
events: {
|
|
80
93
|
onCellSelect: "cell-select",
|
|
81
94
|
onCellEditCommit: "cell-edit-commit",
|
|
@@ -111,4 +124,4 @@ var p = u({
|
|
|
111
124
|
}
|
|
112
125
|
});
|
|
113
126
|
//#endregion
|
|
114
|
-
export {
|
|
127
|
+
export { g as FlexTableReact, t as RowLimitError, n as SourceRequestError, h as useArraySource, m as useODataSource };
|
|
@@ -0,0 +1,202 @@
|
|
|
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-J37bOtgc.js";
|
|
2
|
+
//#region src/odata/source.ts
|
|
3
|
+
function c(e, t = {}) {
|
|
4
|
+
let i = e, c = t, d = u(t.fixedFilter), f = s({
|
|
5
|
+
defaultOrderBy: t.defaultOrderBy,
|
|
6
|
+
initialPage: t.initialPage ?? 0,
|
|
7
|
+
initialSearch: t.initialSearch ?? "",
|
|
8
|
+
initialSort: t.initialSort
|
|
9
|
+
}), p = {
|
|
10
|
+
data: [],
|
|
11
|
+
totalCount: 0,
|
|
12
|
+
loading: !0,
|
|
13
|
+
error: null,
|
|
14
|
+
page: f.page,
|
|
15
|
+
pageSize: t.pageSize ?? 20,
|
|
16
|
+
sortCriteria: f.sortCriteria,
|
|
17
|
+
search: f.search
|
|
18
|
+
}, m = x(), h = /* @__PURE__ */ new Set(), g = null, _ = !1, v = null;
|
|
19
|
+
function y() {
|
|
20
|
+
return c.enabled ?? !0;
|
|
21
|
+
}
|
|
22
|
+
function b() {
|
|
23
|
+
return p.pageSize;
|
|
24
|
+
}
|
|
25
|
+
function x() {
|
|
26
|
+
return {
|
|
27
|
+
...p,
|
|
28
|
+
loading: p.loading || !y()
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function S(e) {
|
|
32
|
+
p = {
|
|
33
|
+
...p,
|
|
34
|
+
...e
|
|
35
|
+
}, C();
|
|
36
|
+
}
|
|
37
|
+
function C() {
|
|
38
|
+
let e = x();
|
|
39
|
+
if (!Object.keys(e).every((t) => e[t] === m[t])) {
|
|
40
|
+
m = e;
|
|
41
|
+
for (let e of [...h]) e();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function w() {
|
|
45
|
+
return JSON.stringify([
|
|
46
|
+
i,
|
|
47
|
+
c.baseUrl,
|
|
48
|
+
b(),
|
|
49
|
+
c.defaultOrderBy,
|
|
50
|
+
d,
|
|
51
|
+
p.page,
|
|
52
|
+
p.sortCriteria,
|
|
53
|
+
p.search
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
function T() {
|
|
57
|
+
_ || (_ = !0, queueMicrotask(() => {
|
|
58
|
+
_ = !1, E();
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
function E() {
|
|
62
|
+
if (h.size === 0) return;
|
|
63
|
+
if (!y()) {
|
|
64
|
+
g?.abort(), g = null, v = null, C();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let e = w();
|
|
68
|
+
e !== v && (v = e, D());
|
|
69
|
+
}
|
|
70
|
+
function D() {
|
|
71
|
+
g?.abort();
|
|
72
|
+
let e = new AbortController();
|
|
73
|
+
g = e;
|
|
74
|
+
let { page: t, sortCriteria: n, search: o } = p, s = b(), u = c.fetcher ?? fetch, d = c.onUnauthorized;
|
|
75
|
+
S({
|
|
76
|
+
loading: !0,
|
|
77
|
+
error: null
|
|
78
|
+
});
|
|
79
|
+
let f = a({
|
|
80
|
+
page: t,
|
|
81
|
+
pageSize: s,
|
|
82
|
+
sortCriteria: n,
|
|
83
|
+
defaultOrderBy: c.defaultOrderBy,
|
|
84
|
+
search: o,
|
|
85
|
+
fixedFilter: c.fixedFilter
|
|
86
|
+
});
|
|
87
|
+
l(`${c.baseUrl ?? window.location.origin}${i}${f}`, {
|
|
88
|
+
fetcher: u,
|
|
89
|
+
signal: e.signal,
|
|
90
|
+
onUnauthorized: d
|
|
91
|
+
}, (e) => e.length < s).then(({ count: n, rows: r }) => {
|
|
92
|
+
if (e.signal.aborted) return;
|
|
93
|
+
let i = n ?? 0, a = i === 0 ? 0 : Math.ceil(i / s) - 1;
|
|
94
|
+
t > a ? (S({
|
|
95
|
+
data: r,
|
|
96
|
+
totalCount: i,
|
|
97
|
+
error: null,
|
|
98
|
+
page: a
|
|
99
|
+
}), T()) : S({
|
|
100
|
+
data: r,
|
|
101
|
+
totalCount: i,
|
|
102
|
+
error: null
|
|
103
|
+
});
|
|
104
|
+
}).catch((t) => {
|
|
105
|
+
e.signal.aborted || t?.name !== "AbortError" && S({
|
|
106
|
+
error: r(t),
|
|
107
|
+
data: [],
|
|
108
|
+
totalCount: 0
|
|
109
|
+
});
|
|
110
|
+
}).finally(() => {
|
|
111
|
+
e.signal.aborted || S({ loading: !1 });
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
getState: () => m,
|
|
116
|
+
subscribe(e) {
|
|
117
|
+
return h.add(e), h.size === 1 && T(), () => {
|
|
118
|
+
!h.delete(e) || h.size > 0 || (g?.abort(), g = null, v = null);
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
setPage(e) {
|
|
122
|
+
S({ page: e }), T();
|
|
123
|
+
},
|
|
124
|
+
setPageSize(e) {
|
|
125
|
+
e !== p.pageSize && (S({
|
|
126
|
+
pageSize: e,
|
|
127
|
+
page: 0
|
|
128
|
+
}), T());
|
|
129
|
+
},
|
|
130
|
+
setSort(e) {
|
|
131
|
+
S({
|
|
132
|
+
sortCriteria: e,
|
|
133
|
+
page: 0
|
|
134
|
+
}), T();
|
|
135
|
+
},
|
|
136
|
+
setSearch(e) {
|
|
137
|
+
S({
|
|
138
|
+
search: e,
|
|
139
|
+
page: 0
|
|
140
|
+
}), T();
|
|
141
|
+
},
|
|
142
|
+
refresh() {
|
|
143
|
+
y() && (v = null, T());
|
|
144
|
+
},
|
|
145
|
+
async fetchAll({ maxRows: e = o, signal: t, onProgress: r } = {}) {
|
|
146
|
+
let { sortCriteria: s, search: u } = p, d = a({
|
|
147
|
+
sortCriteria: s,
|
|
148
|
+
defaultOrderBy: c.defaultOrderBy,
|
|
149
|
+
search: u,
|
|
150
|
+
fixedFilter: c.fixedFilter
|
|
151
|
+
}), { rows: f } = await l(`${c.baseUrl ?? window.location.origin}${i}${d}`, {
|
|
152
|
+
fetcher: c.fetcher ?? fetch,
|
|
153
|
+
signal: t,
|
|
154
|
+
onUnauthorized: c.onUnauthorized
|
|
155
|
+
}, (t, i) => {
|
|
156
|
+
if (i !== void 0 && i > e || t.length > e) throw new n(e, i);
|
|
157
|
+
return r?.(t.length, i), !0;
|
|
158
|
+
});
|
|
159
|
+
return f;
|
|
160
|
+
},
|
|
161
|
+
update(e, t = {}) {
|
|
162
|
+
let n = u(t.fixedFilter), r = n !== d, a = t.pageSize !== void 0 && t.pageSize !== c.pageSize;
|
|
163
|
+
i = e, c = t, d = n, r && (p = {
|
|
164
|
+
...p,
|
|
165
|
+
page: 0
|
|
166
|
+
}), a && t.pageSize !== p.pageSize && (p = {
|
|
167
|
+
...p,
|
|
168
|
+
pageSize: t.pageSize,
|
|
169
|
+
page: 0
|
|
170
|
+
}), C(), T();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async function l(n, { fetcher: r, signal: a, onUnauthorized: o }, s) {
|
|
175
|
+
let c = async (n) => {
|
|
176
|
+
let s;
|
|
177
|
+
try {
|
|
178
|
+
s = await r(n, { signal: a });
|
|
179
|
+
} catch (e) {
|
|
180
|
+
throw e?.name === "AbortError" ? e : t(e);
|
|
181
|
+
}
|
|
182
|
+
if (!s.ok) throw s.status === 401 && o && o(s), new i(await e(s));
|
|
183
|
+
return s.json();
|
|
184
|
+
}, l = await c(n), u = typeof l["@odata.count"] == "number" ? l["@odata.count"] : void 0, d = [...l.value ?? l], f = new URL(n).origin, p = /* @__PURE__ */ new Set([n]), m = n, h = l["@odata.nextLink"];
|
|
185
|
+
for (; s(d, u) && typeof h == "string" && h;) {
|
|
186
|
+
let e = new URL(h, m);
|
|
187
|
+
if (e.origin !== f) throw new i({ message: `OData nextLink points outside the source origin (${e.origin})` });
|
|
188
|
+
if (m = e.toString(), p.has(m)) throw new i({ message: `OData nextLink repeats an already-read page (${m})` });
|
|
189
|
+
p.add(m);
|
|
190
|
+
let t = await c(m);
|
|
191
|
+
d.push(...t.value ?? []), h = t["@odata.nextLink"];
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
count: u,
|
|
195
|
+
rows: d
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function u(e) {
|
|
199
|
+
return e ? JSON.stringify(e) : "";
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
export { c as t };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as e } from "./sorting-CjfjRxwL.js";
|
|
2
|
+
import { n as t, t as n } from "./fetch-all-J37bOtgc.js";
|
|
2
3
|
//#region src/array/view.ts
|
|
3
|
-
function
|
|
4
|
+
function r(t, { search: n, sortCriteria: r, page: i, pageSize: a, columns: o, searchFields: s }) {
|
|
4
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;
|
|
5
6
|
r.length > 0 && (u = e(l, r, o ?? []).map((e) => l[e]));
|
|
6
7
|
let d = u.length, f = d === 0 ? 0 : Math.ceil(d / a) - 1, p = Math.min(Math.max(i, 0), f) * a;
|
|
@@ -9,5 +10,15 @@ function t(t, { search: n, sortCriteria: r, page: i, pageSize: a, columns: o, se
|
|
|
9
10
|
totalCount: d
|
|
10
11
|
};
|
|
11
12
|
}
|
|
13
|
+
async function i(e, i, { maxRows: a = n, signal: o, onProgress: s } = {}) {
|
|
14
|
+
o?.throwIfAborted();
|
|
15
|
+
let { data: c, totalCount: l } = r(e, {
|
|
16
|
+
...i,
|
|
17
|
+
page: 0,
|
|
18
|
+
pageSize: Math.max(e.length, 1)
|
|
19
|
+
});
|
|
20
|
+
if (l > a) throw new t(a, l);
|
|
21
|
+
return s?.(c.length, l), c;
|
|
22
|
+
}
|
|
12
23
|
//#endregion
|
|
13
|
-
export { t };
|
|
24
|
+
export { i as n, r as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/flex-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.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.15.0",
|
|
78
78
|
"@lit/react": "^1.0.8",
|
|
79
79
|
"react": "^18.0.0 || ^19.0.0"
|
|
80
80
|
},
|
|
@@ -76,7 +76,8 @@ Use `updateRows([{ row, key, value }])` for programmatic edits (undoable, fires
|
|
|
76
76
|
|
|
77
77
|
**Editing and read-only.** `editable` defaults to `true`. For a read-only grid set
|
|
78
78
|
`table.editable = false` (a property, since a boolean attribute cannot express `false`) — Enter on a non-editable cell then fires
|
|
79
|
-
`row-activate`, the grid's "open this row" contract.
|
|
79
|
+
`row-activate`, the grid's "open this row" contract; a plain click on a cell fires it too (`via: 'click'`).
|
|
80
|
+
Open a row's detail on `row-activate`, never on `cell-select` — that one is focus and fires when Tab arrives on the grid.
|
|
80
81
|
|
|
81
82
|
**Row selection is kept by row id.** Enable with `selectable` (`selection-mode="single|multi"`).
|
|
82
83
|
The id is the row's `row-key` field (`_id` by default, as in `u-rich-table`) or a `rowKey` function, so
|