@iyulab/flex-table 0.39.0 โ 0.40.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 +43 -28
- package/dist/array/index.d.ts +2 -3
- package/dist/array/index.js +2 -56
- package/dist/array/use-array-source.d.ts +1 -24
- package/dist/array/view.d.ts +24 -0
- package/dist/{flex-table-JGaGcJTl.js โ flex-table-CDEu8YQE.js} +106 -101
- package/dist/flex-table.d.ts +1 -1
- package/dist/flex-table.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/models/types.d.ts +20 -8
- package/dist/odata/index.d.ts +2 -2
- package/dist/odata/index.js +2 -2
- package/dist/odata/query.d.ts +72 -0
- package/dist/odata/use-odata-source.d.ts +0 -51
- package/dist/query-Dw4iO0ir.js +37 -0
- package/dist/react.d.ts +8 -4
- package/dist/react.js +142 -6
- package/dist/view-DiLr-TdY.js +13 -0
- package/package.json +1 -1
- package/dist/use-odata-source-BiZrIEVV.js +0 -118
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.40.0] - 2026-09-28
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- ๐ด **Breaking โ the React hooks moved to `./react`.** `useODataSource` and `useArraySource` (and
|
|
8
|
+
their option/result types) are now exported from `@iyulab/flex-table/react`, next to
|
|
9
|
+
`FlexTableReact`. `./odata` and `./array` keep only the pure functions โ `buildSearchExpression`,
|
|
10
|
+
`parseOrderBy`, `computeArrayView`, and the new `buildODataQuery` โ and no longer load React, so an
|
|
11
|
+
app without React (a typeahead that is not a table, a Lit app) can use them without installing it.
|
|
12
|
+
Before, importing `buildSearchExpression` from `./odata` required `react` statically.
|
|
13
|
+
Migration: `import { useODataSource } from '@iyulab/flex-table/odata'` โ
|
|
14
|
+
`import { useODataSource } from '@iyulab/flex-table/react'` (same for `useArraySource` from
|
|
15
|
+
`./array`).
|
|
16
|
+
|
|
17
|
+
- ๐ด **Breaking โ column definitions use the same words as `u-rich-table`.** `header` โ `label` and
|
|
18
|
+
`renderer` โ `render`, so one column list reads the same in either table (`header-context-menu`'s detail likewise carries
|
|
19
|
+
`label` instead of `header`). Migration: rename the two keys
|
|
20
|
+
in your `ColumnDefinition` objects; the types reject the old names.
|
|
21
|
+
- **Headers follow their values.** A header's default alignment is now the column's cell alignment,
|
|
22
|
+
so a `number` column's header is right-aligned over its right-aligned values instead of sitting
|
|
23
|
+
at the left edge (on a wide column it read as the neighbour's header). Set `headerAlign` to keep
|
|
24
|
+
a different header alignment. Cell alignment uses logical values (`text-align: end`), so
|
|
25
|
+
right-to-left locales mirror.
|
|
26
|
+
|
|
27
|
+
- **The column menu, the cell context menu and the drag ghost read the shared stacking tokens.**
|
|
28
|
+
The menus sit on `--u-layer-floating` (1000 โ they were at 200, below every other floating
|
|
29
|
+
surface) and the drag ghost on `--u-layer-overlay` (9999, as before), so they stack the same way
|
|
30
|
+
as popovers and dialogs from `@iyulab/components`.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **`align` on `ColumnDefinition`** (`'start' | 'center' | 'end'`) โ cell alignment. Default comes
|
|
35
|
+
from `type` as before (`number` โ end, `boolean` โ center, otherwise start); set it for a code or
|
|
36
|
+
Y/N column that is text but should center. `effectiveAlign(col)` returns what a column renders with.
|
|
37
|
+
- **`buildODataQuery(state)` on `./odata`** โ the step `useODataSource` runs on every request (page,
|
|
38
|
+
page size, sort, search, fixed filter โ OData query string), now callable without React. A Lit
|
|
39
|
+
table or a non-table list doing server paging can send exactly the query the hook would, instead
|
|
40
|
+
of re-deriving `$top`/`$skip`/`$orderby`/`$search`. The hook now calls it.
|
|
41
|
+
|
|
3
42
|
## [0.39.0] - 2026-09-27
|
|
4
43
|
|
|
5
44
|
### Added
|
package/README.md
CHANGED
|
@@ -28,9 +28,9 @@ npm install @iyulab/flex-table
|
|
|
28
28
|
const table = document.getElementById('table');
|
|
29
29
|
|
|
30
30
|
table.columns = [
|
|
31
|
-
{ key: 'name',
|
|
32
|
-
{ key: 'age',
|
|
33
|
-
{ key: 'active',
|
|
31
|
+
{ key: 'name', label: 'Name', type: 'text', width: 200 },
|
|
32
|
+
{ key: 'age', label: 'Age', type: 'number', width: 100 },
|
|
33
|
+
{ key: 'active', label: 'Active', type: 'boolean', width: 80 },
|
|
34
34
|
];
|
|
35
35
|
|
|
36
36
|
table.data = [
|
|
@@ -113,7 +113,7 @@ guarantee about a *constrained* host. `height-model.browser.test.ts` pins both s
|
|
|
113
113
|
| `footerData` | `footer-data` | `Record<string, string>` | `null` | Footer/summary row data (keys match column keys) |
|
|
114
114
|
| `emptyMessage` | `empty-message` | `string` | `'No data'` | Shown when `data` is empty |
|
|
115
115
|
| `noMatchingMessage` | `no-matching-message` | `string` | `'No matching data'` | Shown when `data` has rows but every one is hidden by an active column filter |
|
|
116
|
-
| `stylesheets` | โ | `CSSStyleSheet[]` | `[]` | Constructable stylesheets adopted into the shadow root alongside the grid's own styles โ the escape hatch for styling content a `
|
|
116
|
+
| `stylesheets` | โ | `CSSStyleSheet[]` | `[]` | Constructable stylesheets adopted into the shadow root alongside the grid's own styles โ the escape hatch for styling content a `render` function inserts, since document CSS doesn't cross the shadow boundary. Reassigning swaps the previous set, it doesn't accumulate |
|
|
117
117
|
|
|
118
118
|
### Read-only Properties
|
|
119
119
|
|
|
@@ -133,19 +133,20 @@ guarantee about a *constrained* host. `height-model.browser.test.ts` pins both s
|
|
|
133
133
|
```typescript
|
|
134
134
|
interface ColumnDefinition {
|
|
135
135
|
key: string; // Unique key matching data property names
|
|
136
|
-
|
|
136
|
+
label: string; // Column header text
|
|
137
137
|
type?: ColumnType; // 'text' | 'number' | 'boolean' | 'date' | 'datetime' | 'select' (any other string falls back to 'text')
|
|
138
138
|
width?: number; // Column width in pixels (default: auto)
|
|
139
139
|
minWidth?: number; // Minimum width in pixels (default: 40, enforced in rendering)
|
|
140
140
|
hidden?: boolean; // Hide column from view
|
|
141
141
|
sortable?: boolean; // Enable sorting (default: true)
|
|
142
|
-
|
|
142
|
+
align?: 'start' | 'center' | 'end'; // Cell alignment (default from type: number โ end, boolean โ center, else start)
|
|
143
|
+
headerAlign?: 'start' | 'center' | 'end'; // Header alignment (default: the cell alignment above)
|
|
143
144
|
editable?: boolean; // Per-column edit control (follows global editable)
|
|
144
145
|
pinned?: 'left' | 'right'; // Freeze column during horizontal scroll
|
|
145
146
|
options?: string[] | SelectOption[]; // Allowed values for type: 'select' (SelectOption = { label, value })
|
|
146
147
|
autocomplete?: boolean | 'strict'; // Suggest existing column values while editing; 'strict' rejects values not in the list
|
|
147
|
-
format?: string | ((value, row, col) => string); // Display format, see "format vs
|
|
148
|
-
|
|
148
|
+
format?: string | ((value, row, col) => string); // Display format, see "format vs render" below
|
|
149
|
+
render?: CellRenderer; // Custom cell render: (value, row, col) => TemplateResult | string
|
|
149
150
|
editor?: CellEditor; // Custom cell editor: (value, row, col) => TemplateResult
|
|
150
151
|
validator?: CellValidator; // Validate before commit: (value, row, col) => string | null
|
|
151
152
|
conditionalRules?: ConditionalRule[]; // Per-cell style rules, see below
|
|
@@ -156,32 +157,32 @@ The `editor` callback must return a Lit `TemplateResult` containing an input ele
|
|
|
156
157
|
|
|
157
158
|
The `validator` callback returns `null` if valid, or an error message string. On failure, the cell shows a red border for 3 seconds and a `validation-error` event is dispatched.
|
|
158
159
|
|
|
159
|
-
### `format` vs `
|
|
160
|
+
### `format` vs `render`
|
|
160
161
|
|
|
161
162
|
Both control how a cell's raw value is displayed, but they differ in what they replace:
|
|
162
163
|
|
|
163
164
|
- **`format`**: a plain string pattern (Excel-style, e.g. `'#,##0.00'`, `'0.00%'`, `'$#,##0'`, `'yyyy-MM-dd'`) or a `(value) => string` function. Only the *displayed text* changes โ editing, sorting, filtering, and export all keep operating on the raw underlying value. Use this for number/date/currency display formatting.
|
|
164
|
-
- **`
|
|
165
|
+
- **`render`**: a `(value, row, col) => TemplateResult | string` function that replaces the cell's rendered content entirely โ badges, links, icons, multi-field composites. Sorting/filtering still use the raw value, but the visual output is fully custom.
|
|
165
166
|
|
|
166
167
|
```typescript
|
|
167
168
|
const columns: ColumnDefinition<Order>[] = [
|
|
168
|
-
{ key: 'total',
|
|
169
|
-
{ key: 'placedAt',
|
|
170
|
-
{ key: 'status',
|
|
169
|
+
{ key: 'total', label: 'Total', format: '#,##0.00' }, // "1,234.50"
|
|
170
|
+
{ key: 'placedAt', label: 'Placed', format: 'yyyy-MM-dd' }, // date pattern
|
|
171
|
+
{ key: 'status', label: 'Status', render: (v) => html`<span class="badge badge-${v}">${v}</span>` },
|
|
171
172
|
];
|
|
172
173
|
```
|
|
173
174
|
|
|
174
|
-
If both are set on the same column, `
|
|
175
|
+
If both are set on the same column, `render` takes precedence โ `format` has no effect once a custom `render` fully controls the cell's output.
|
|
175
176
|
|
|
176
177
|
### Conditional Formatting
|
|
177
178
|
|
|
178
|
-
`conditionalRules` applies a style to a cell when its `when` predicate matches โ a declarative alternative to writing a `
|
|
179
|
+
`conditionalRules` applies a style to a cell when its `when` predicate matches โ a declarative alternative to writing a `render` function just to color-code status/threshold values:
|
|
179
180
|
|
|
180
181
|
```typescript
|
|
181
182
|
const columns: ColumnDefinition<Order>[] = [
|
|
182
183
|
{
|
|
183
184
|
key: 'status',
|
|
184
|
-
|
|
185
|
+
label: 'Status',
|
|
185
186
|
conditionalRules: [
|
|
186
187
|
{ when: (v) => v === 'overdue', style: { color: '#dc2626', fontWeight: 'bold' } },
|
|
187
188
|
{ when: (v) => v === 'paid', style: { color: '#16a34a' } },
|
|
@@ -489,8 +490,8 @@ import { FlexTableReact } from '@iyulab/flex-table/react';
|
|
|
489
490
|
|
|
490
491
|
function App() {
|
|
491
492
|
const columns = [
|
|
492
|
-
{ key: 'name',
|
|
493
|
-
{ key: 'age',
|
|
493
|
+
{ key: 'name', label: 'Name', type: 'text' },
|
|
494
|
+
{ key: 'age', label: 'Age', type: 'number' },
|
|
494
495
|
];
|
|
495
496
|
|
|
496
497
|
const data = [
|
|
@@ -547,8 +548,8 @@ interface Order {
|
|
|
547
548
|
}
|
|
548
549
|
|
|
549
550
|
const columns: ColumnDefinition<Order>[] = [
|
|
550
|
-
{ key: 'id',
|
|
551
|
-
{ key: 'total',
|
|
551
|
+
{ key: 'id', label: 'ID' },
|
|
552
|
+
{ key: 'total', label: 'Total', render: (_value, row) => `${row.total} ${row.currency}` },
|
|
552
553
|
];
|
|
553
554
|
|
|
554
555
|
<FlexTableReact<Order> data={orders} columns={columns} />
|
|
@@ -566,7 +567,7 @@ import { html } from 'lit';
|
|
|
566
567
|
table.columns = [
|
|
567
568
|
{
|
|
568
569
|
key: 'color',
|
|
569
|
-
|
|
570
|
+
label: 'Color',
|
|
570
571
|
type: 'text',
|
|
571
572
|
editor: (value) => html`
|
|
572
573
|
<input class="ft-editor" type="color" .value=${String(value ?? '#000000')}
|
|
@@ -593,7 +594,7 @@ Use the `validator` callback to validate input before committing. Returns `null`
|
|
|
593
594
|
table.columns = [
|
|
594
595
|
{
|
|
595
596
|
key: 'age',
|
|
596
|
-
|
|
597
|
+
label: 'Age',
|
|
597
598
|
type: 'number',
|
|
598
599
|
validator: (value) => {
|
|
599
600
|
const n = Number(value);
|
|
@@ -612,10 +613,10 @@ Freeze columns on either side during horizontal scroll:
|
|
|
612
613
|
|
|
613
614
|
```typescript
|
|
614
615
|
table.columns = [
|
|
615
|
-
{ key: 'id',
|
|
616
|
-
{ key: 'name',
|
|
616
|
+
{ key: 'id', label: 'ID', pinned: 'left' },
|
|
617
|
+
{ key: 'name', label: 'Name' },
|
|
617
618
|
// ... many columns ...
|
|
618
|
-
{ key: 'actions',
|
|
619
|
+
{ key: 'actions', label: 'Actions', pinned: 'right' },
|
|
619
620
|
];
|
|
620
621
|
```
|
|
621
622
|
|
|
@@ -668,7 +669,7 @@ table.addEventListener('sort-change', (e) => {
|
|
|
668
669
|
`useODataSource(url, options)` fetches paginated/sorted/filtered data from an OData v4 endpoint and returns props ready to bind to `<FlexTableReact dataMode="server" ...>`.
|
|
669
670
|
|
|
670
671
|
```tsx
|
|
671
|
-
import { useODataSource } from '@iyulab/flex-table/
|
|
672
|
+
import { useODataSource } from '@iyulab/flex-table/react';
|
|
672
673
|
|
|
673
674
|
const source = useODataSource('/api/orders', {
|
|
674
675
|
pageSize: 20,
|
|
@@ -760,7 +761,7 @@ The hook returns:
|
|
|
760
761
|
|
|
761
762
|
Terms are always quoted because OData 4.0 only allows letters in an unquoted `searchWord`, so `2026` or `ZT-E2E-A` would be rejected by servers that follow it (4.01 relaxed this, but [Microsoft.OData still lexes as 4.0](https://github.com/OData/odata.net/issues/2445)). Quoting keeps any term valid regardless of server version. Since a `$search` phrase cannot contain `"` and OData defines no escape for it, double quotes are stripped from the term.
|
|
762
763
|
|
|
763
|
-
The quoting/escaping logic above is also available standalone as `buildSearchExpression(term)`, for consumers that need the same `$search` encoding without the pagination hook (e.g. a typeahead/combobox that isn't a table). `parseOrderBy(orderBy)` (`'a asc, b desc'` โ `SortCriteria[]`) is exported the same way, for consumers driving a sort UI that isn't `useODataSource` either:
|
|
764
|
+
The quoting/escaping logic above is also available standalone as `buildSearchExpression(term)`, for consumers that need the same `$search` encoding without the pagination hook (e.g. a typeahead/combobox that isn't a table). `parseOrderBy(orderBy)` (`'a asc, b desc'` โ `SortCriteria[]`) is exported the same way, for consumers driving a sort UI that isn't `useODataSource` either. The `./odata` entry holds only pure functions and does not load React, so an app without React can use it (the hooks live on `./react`):
|
|
764
765
|
|
|
765
766
|
```ts
|
|
766
767
|
import { buildSearchExpression, parseOrderBy } from '@iyulab/flex-table/odata';
|
|
@@ -770,6 +771,20 @@ buildSearchExpression(''); // undefined
|
|
|
770
771
|
parseOrderBy('name desc'); // [{ key: 'name', direction: 'desc' }]
|
|
771
772
|
```
|
|
772
773
|
|
|
774
|
+
`buildODataQuery(state)` is the step the hook runs on every request โ table state in, OData query string out. Use it to drive server paging without React (a Lit table, a list that is not a table) with exactly the query the hook would send:
|
|
775
|
+
|
|
776
|
+
```ts
|
|
777
|
+
import { buildODataQuery } from '@iyulab/flex-table/odata';
|
|
778
|
+
|
|
779
|
+
buildODataQuery({
|
|
780
|
+
page: 2, pageSize: 20, // 0-based page โ $skip=40
|
|
781
|
+
sortCriteria: [{ key: 'name', direction: 'desc' }], // else defaultOrderBy
|
|
782
|
+
search: 'red shirt', // encoded by buildSearchExpression
|
|
783
|
+
fixedFilter: { IsActive: true }, // odata-query filter object
|
|
784
|
+
});
|
|
785
|
+
// '?$filter=IsActive eq true&$orderby=name desc&$count=true&$top=20&$skip=40&$search=%22red%22%20AND%20%22shirt%22'
|
|
786
|
+
```
|
|
787
|
+
|
|
773
788
|
### Array Source Hook (React)
|
|
774
789
|
|
|
775
790
|
`useArraySource(data, options)` runs search/sort/pagination over an in-memory array and
|
|
@@ -788,7 +803,7 @@ e.g. a lookup table whose display name lives on a different endpoint than the ro
|
|
|
788
803
|
so search/sort has to run after the join, in memory:
|
|
789
804
|
|
|
790
805
|
```tsx
|
|
791
|
-
import { useArraySource } from '@iyulab/flex-table/
|
|
806
|
+
import { useArraySource } from '@iyulab/flex-table/react';
|
|
792
807
|
|
|
793
808
|
const joined = useMemo(
|
|
794
809
|
() => seasonPrices.map(p => ({ ...p, productName: productsById[p.productId]?.name ?? '' })),
|
package/dist/array/index.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
3
|
-
export type { ComputeArrayViewOptions } from './use-array-source.js';
|
|
1
|
+
export { computeArrayView } from './view.js';
|
|
2
|
+
export type { ComputeArrayViewOptions } from './view.js';
|
package/dist/array/index.js
CHANGED
|
@@ -1,56 +1,2 @@
|
|
|
1
|
-
import { t as e } from "../
|
|
2
|
-
|
|
3
|
-
import { useCallback as n, useMemo as r, useState as i } from "react";
|
|
4
|
-
//#region src/array/use-array-source.ts
|
|
5
|
-
function a(t, { search: n, sortCriteria: r, page: i, pageSize: a, columns: o, searchFields: s }) {
|
|
6
|
-
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;
|
|
7
|
-
r.length > 0 && (u = e(l, r, o ?? []).map((e) => l[e]));
|
|
8
|
-
let d = u.length, f = d === 0 ? 0 : Math.ceil(d / a) - 1, p = Math.min(Math.max(i, 0), f) * a;
|
|
9
|
-
return {
|
|
10
|
-
data: u.slice(p, p + a),
|
|
11
|
-
totalCount: d
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
function o(e, o = {}) {
|
|
15
|
-
let { pageSize: s = 20, defaultOrderBy: c, initialPage: l = 0, initialSearch: u = "", initialSort: d, columns: f, searchFields: p } = o, m = t({
|
|
16
|
-
defaultOrderBy: c,
|
|
17
|
-
initialPage: l,
|
|
18
|
-
initialSearch: u,
|
|
19
|
-
initialSort: d
|
|
20
|
-
}), [h, g] = i(m.page), [_, v] = i(m.sortCriteria), [y, b] = i(m.search), x = n((e) => {
|
|
21
|
-
b(e), g(0);
|
|
22
|
-
}, []), S = n((e) => {
|
|
23
|
-
let t = e.detail?.criteria;
|
|
24
|
-
t && (v(t), g(0));
|
|
25
|
-
}, []), C = n(() => {}, []), { data: w, totalCount: T } = r(() => a(e, {
|
|
26
|
-
search: y,
|
|
27
|
-
sortCriteria: _,
|
|
28
|
-
page: h,
|
|
29
|
-
pageSize: s,
|
|
30
|
-
columns: f,
|
|
31
|
-
searchFields: p
|
|
32
|
-
}), [
|
|
33
|
-
e,
|
|
34
|
-
y,
|
|
35
|
-
_,
|
|
36
|
-
h,
|
|
37
|
-
s,
|
|
38
|
-
f,
|
|
39
|
-
p
|
|
40
|
-
]), E = T === 0 ? 0 : Math.ceil(T / s) - 1;
|
|
41
|
-
return h > E && g(E), {
|
|
42
|
-
data: w,
|
|
43
|
-
totalCount: T,
|
|
44
|
-
loading: !1,
|
|
45
|
-
error: null,
|
|
46
|
-
page: h,
|
|
47
|
-
setPage: g,
|
|
48
|
-
sortCriteria: _,
|
|
49
|
-
onSortChange: S,
|
|
50
|
-
search: y,
|
|
51
|
-
setSearch: x,
|
|
52
|
-
refresh: C
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
export { a as computeArrayView, o as useArraySource };
|
|
1
|
+
import { t as e } from "../view-DiLr-TdY.js";
|
|
2
|
+
export { e as computeArrayView };
|
|
@@ -1,28 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ColumnDefinition, DataRow } from '../models/types.js';
|
|
1
|
+
import type { DataRow } from '../models/types.js';
|
|
3
2
|
import type { UseArraySourceOptions, UseArraySourceResult } from './types.js';
|
|
4
|
-
export interface ComputeArrayViewOptions<T> {
|
|
5
|
-
search: string;
|
|
6
|
-
sortCriteria: SortCriteria[];
|
|
7
|
-
page: number;
|
|
8
|
-
pageSize: number;
|
|
9
|
-
columns?: ColumnDefinition<T>[];
|
|
10
|
-
searchFields?: (row: T) => Array<string | number | boolean | null | undefined>;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* `useArraySource`์ ๊ฒ์โ์ ๋ ฌโํ์ด์ง ํ์ดํ๋ผ์ธ์ React ์์ด ์์ํ๊ฒ ๊ณ์ฐํ๋ค
|
|
14
|
-
* (ํ
์ ์ด ํจ์๋ฅผ `useMemo`๋ก ๊ฐ์ธ๊ธฐ๋ง ํ๋ค) โ React ํ
๋ ๋ ์ธํ๋ผ ์์ด ์ด ํจํค์ง์
|
|
15
|
-
* ๋ค๋ฅธ ์์ ํฌํผ(`buildSearchExpression`/`parseOrderBy`)์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋จ์
|
|
16
|
-
* ํ
์คํธํ๊ธฐ ์ํด ๋ถ๋ฆฌํ๋ค.
|
|
17
|
-
*
|
|
18
|
-
* ์ ๋ ฌ์ ๊ทธ๋ฆฌ๋ ์์ ์ ํด๋ผ์ด์ธํธ ์ ๋ ฌ ํ์ดํ๋ผ์ธ์ด ์ฐ๋ `computeSortedIndices`๋ฅผ
|
|
19
|
-
* ๊ทธ๋๋ก ์ฌ์ฌ์ฉํ๋ค โ `columns`๋ฅผ ๋๊ธฐ๋ฉด ์ซ์/๋ ์ง/๋ถ๋ฆฌ์ธ๋ ๊ฐ ๊ธฐ์ค์ผ๋ก ๋น๊ต๋๊ณ ,
|
|
20
|
-
* ์๋ตํ๋ฉด ์ ๋ถ ํ
์คํธ ๋น๊ต๋ก ๋ฎ์์ง๋ค.
|
|
21
|
-
*/
|
|
22
|
-
export declare function computeArrayView<T extends DataRow>(data: T[], { search, sortCriteria, page, pageSize, columns, searchFields }: ComputeArrayViewOptions<T>): {
|
|
23
|
-
data: T[];
|
|
24
|
-
totalCount: number;
|
|
25
|
-
};
|
|
26
3
|
/**
|
|
27
4
|
* ํด๋ผ์ด์ธํธ ๋ฐฐ์ด(์ด๋ฏธ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ๋ฐ์ดํฐ, ํํ ์ฌ๋ฌ ์ถ์ฒ๋ฅผ ์กฐ์ธํด ๋ง๋ ํ์
|
|
28
5
|
* ํ ๋ฐฐ์ด) ์ ์ฉ React ํ
. `useODataSource`์ **๊ฐ์ ๋ฐํ ํํ**(`data`/`totalCount`/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SortCriteria } from '../core/sorting.js';
|
|
2
|
+
import type { ColumnDefinition, DataRow } from '../models/types.js';
|
|
3
|
+
export interface ComputeArrayViewOptions<T> {
|
|
4
|
+
search: string;
|
|
5
|
+
sortCriteria: SortCriteria[];
|
|
6
|
+
page: number;
|
|
7
|
+
pageSize: number;
|
|
8
|
+
columns?: ColumnDefinition<T>[];
|
|
9
|
+
searchFields?: (row: T) => Array<string | number | boolean | null | undefined>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `useArraySource`์ ๊ฒ์โ์ ๋ ฌโํ์ด์ง ํ์ดํ๋ผ์ธ์ React ์์ด ์์ํ๊ฒ ๊ณ์ฐํ๋ค
|
|
13
|
+
* (ํ
์ ์ด ํจ์๋ฅผ `useMemo`๋ก ๊ฐ์ธ๊ธฐ๋ง ํ๋ค) โ React ํ
๋ ๋ ์ธํ๋ผ ์์ด ์ด ํจํค์ง์
|
|
14
|
+
* ๋ค๋ฅธ ์์ ํฌํผ(`buildSearchExpression`/`parseOrderBy`)์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋จ์
|
|
15
|
+
* ํ
์คํธํ๊ธฐ ์ํด ๋ถ๋ฆฌํ๋ค.
|
|
16
|
+
*
|
|
17
|
+
* ์ ๋ ฌ์ ๊ทธ๋ฆฌ๋ ์์ ์ ํด๋ผ์ด์ธํธ ์ ๋ ฌ ํ์ดํ๋ผ์ธ์ด ์ฐ๋ `computeSortedIndices`๋ฅผ
|
|
18
|
+
* ๊ทธ๋๋ก ์ฌ์ฌ์ฉํ๋ค โ `columns`๋ฅผ ๋๊ธฐ๋ฉด ์ซ์/๋ ์ง/๋ถ๋ฆฌ์ธ๋ ๊ฐ ๊ธฐ์ค์ผ๋ก ๋น๊ต๋๊ณ ,
|
|
19
|
+
* ์๋ตํ๋ฉด ์ ๋ถ ํ
์คํธ ๋น๊ต๋ก ๋ฎ์์ง๋ค.
|
|
20
|
+
*/
|
|
21
|
+
export declare function computeArrayView<T extends DataRow>(data: T[], { search, sortCriteria, page, pageSize, columns, searchFields }: ComputeArrayViewOptions<T>): {
|
|
22
|
+
data: T[];
|
|
23
|
+
totalCount: number;
|
|
24
|
+
};
|