@iyulab/flex-table 0.61.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,63 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.63.0] - 2026-10-08
4
+
5
+ ### Added
6
+
7
+ - **Dot-path column keys** — `{ key: 'Customer.Name' }` reads `row.Customer.Name`, so a referenced record's name is a
8
+ column. Display, `format`, sorting, filtering, copying, editing, import and export read and write the cell through the
9
+ same path (`getCellValue` / `setCellValue`, now exported); a property named by the whole key (`'@odata.etag'`) still
10
+ wins. The server sort of such a column is the OData path (`$orderby=Customer/Name`), and `parseOrderBy` reads it back
11
+ as the column key.
12
+ - **`createODataSource` / `useODataSource` `expand` and `select`** — `$expand` (a string or an array) and `$select`,
13
+ sent by the page reads and by `fetchAll` alike; changing either re-reads. `buildODataQuery` takes them too.
14
+
15
+ - **`importFromFile` reports what did not come in.** It returns an `ImportReport` — and `data-import` now carries the
16
+ same object — `{ count, unmatchedHeaders, missingColumns, coercionFailures }`: file headers no column matched (their
17
+ values were dropped without a trace before), columns the file lacks, and cells that are not their column's type
18
+ (`{ row, key, raw }` — the cell keeps its text). `null` for a file type it does not read.
19
+ - **`ColumnDefinition.importAliases`** — other headers a file may give the column (a template a person made says
20
+ «관리 번호» where the label is «관리번호»). Headers now also match ignoring surrounding spaces.
21
+ - `flexTableLocale` keys `booleanTrueWords` / `booleanFalseWords` — the words a boolean column reads as true and false
22
+ (`yes,y` / `no,n`; Korean `예,네` / `아니오,아니요`), besides `true`/`false`/`1`/`0` and the locale's labels.
23
+
24
+ ### Changed
25
+
26
+ - **A boolean column keeps text it cannot read** — on import and on paste — instead of turning it into `false`.
27
+ «예», «Y» or «yes» became «no»; now the words above are read and anything else stays as written (and is reported on
28
+ import), as `number` and `date` columns already did.
29
+
30
+ ### Fixed
31
+
32
+ - **A comma-separated `.csv` imports.** It was read as tab-separated, so each line became one cell under an unmatched
33
+ header and the whole file came in as empty rows. A CSV may now be separated by commas or semicolons (Excel on
34
+ comma-decimal locales), detected from the header line.
35
+ - A CSV that starts with a byte-order mark — as `exportToFile` writes it — reads back: the mark was part of the first
36
+ header, so that column did not match.
37
+ - Two file headers that match the same column no longer both write into it; the second is reported as unmatched.
38
+
39
+ - **A hidden `flex-table` is hidden.** Its host's `display: block` outranked the browser's `[hidden]` rule, so
40
+ `hidden` did nothing — a list that switches between a table and a card view (which hides the view it is not
41
+ showing) drew both.
42
+
43
+ ## [0.62.0] - 2026-10-08
44
+
45
+ ### Added
46
+
47
+ - **`ColumnDefinition.exportValue(value, row)`** — what export writes for the column (CSV, TSV, JSON, XLSX). Without
48
+ it export writes the raw value as before; a column that shows a label for a code can now say so once instead of the
49
+ consumer rewriting the rows before `{ rows }`. A returned `Date` is a date cell in XLSX.
50
+ - **CSV/TSV byte order mark** — `{ bom: true }` on `exportToString`/`exportToBlob`/`exportData`/`exportDataBlob`, and
51
+ `exportToFile` adds it by default (a downloaded file is opened in a spreadsheet; Excel on a non-UTF-8 system code page
52
+ garbled Korean without it). `{ bom: false }` turns it off.
53
+
54
+ ### Fixed
55
+
56
+ - XLSX: an ISO string in a `date`/`datetime` column is a date cell — JSON sources (OData) send dates as strings, so the
57
+ file had text where the list showed dates. Strings that do not read as a date stay text.
58
+ - XLSX: date serials are the wall-clock time the table shows. They were counted from UTC, so a local-midnight date in
59
+ a timezone ahead of UTC (Korea, +09) went in as the afternoon of the day before and a date format showed that day.
60
+
3
61
  ## [0.61.0] - 2026-10-07
4
62
 
5
63
  ### Added
package/README.md CHANGED
@@ -134,7 +134,7 @@ guarantee about a *constrained* host. `height-model.browser.test.ts` pins both s
134
134
 
135
135
  ```typescript
136
136
  interface ColumnDefinition {
137
- key: string; // Unique key matching data property names
137
+ key: string; // The row property, or a dot path into a nested record ('Customer.Name' — see below)
138
138
  label: string; // Column header text
139
139
  type?: ColumnType; // 'text' | 'number' | 'boolean' | 'date' | 'datetime' | 'select' (any other string falls back to 'text')
140
140
  width?: number; // Column width in pixels (default: auto)
@@ -148,6 +148,7 @@ interface ColumnDefinition {
148
148
  options?: string[] | SelectOption[]; // Allowed values for type: 'select' (SelectOption = { label, value })
149
149
  autocomplete?: boolean | 'strict'; // Suggest existing column values while editing; 'strict' rejects values not in the list
150
150
  format?: string | ((value, row, col) => string); // Display format, see "format vs render" below
151
+ exportValue?: (value, row) => string | number | boolean | Date | null; // What export writes for this column (default: the raw value)
151
152
  render?: CellRenderer; // Custom cell render: (value, row, col) => TemplateResult | string
152
153
  editor?: CellEditor; // Custom cell editor: (value, row, col) => TemplateResult
153
154
  validator?: CellValidator; // Validate before commit: (value, row, col) => string | null
@@ -165,11 +166,28 @@ A `number` column's built-in editor reads numbers the way people type them in th
165
166
 
166
167
  A `date` column's built-in editor is `u-date-picker` from `@iyulab/components`: a text box that shows and takes `YYYY-MM-DD` in every browser language (the native date input would show the browser's UI language, e.g. `10/02/2026`), with a calendar beside it — click the box or press ArrowDown, and a picked day is the new value. It also reads `2026/10/2`, `20261002` and `10-02` (this year), stores the ISO date string, and rejects text that is not a date (`error` is the localized "Enter a date as YYYY-MM-DD"). Pasted dates are read the same way. A `datetime` column's editor works the same with a time: it shows `YYYY-MM-DD HH:mm` in local time, reads `2026-10-02 14:05` (a date alone is midnight), and stores the local `YYYY-MM-DDTHH:mm` string; in its calendar a day and a time are applied together with Apply. While the calendar is open, Escape closes the calendar; the next Escape cancels the edit.
167
168
 
169
+ ### Nested values — dot-path keys
170
+
171
+ A `key` may be a path into a nested record: `{ key: 'Customer.Name', label: 'Customer' }` reads `row.Customer.Name` —
172
+ what a server list gets from OData `$expand` (the source's `expand` option). Display, `format`, sorting, filtering,
173
+ copying, editing, import and export all read and write the cell through the same path, and the server sort of that
174
+ column is `$orderby=Customer/Name`. A row that has a property named by the whole key (`'@odata.etag'`) gives that
175
+ property; the path is read only when the name is not there. `getCellValue(row, key)` / `setCellValue(row, key, value)`
176
+ (root entry) are the functions the table uses.
177
+
178
+ ```typescript
179
+ const source = createODataSource('/api/orders', { expand: 'Customer($select=Name)' });
180
+ const columns: ColumnDefinition[] = [
181
+ { key: 'Number', label: 'Order' },
182
+ { key: 'Customer.Name', label: 'Customer' }, // sortable on the server, exported as shown
183
+ ];
184
+ ```
185
+
168
186
  ### `format` vs `render`
169
187
 
170
188
  Both control how a cell's raw value is displayed, but they differ in what they replace:
171
189
 
172
- - **`format`**: a plain string pattern (Excel-style, e.g. `'#,##0.00'`, `'0.00%'`, `'$#,##0'`, `'yyyy-MM-dd'`) or a `(value, row, col) => 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.
190
+ - **`format`**: a plain string pattern (Excel-style, e.g. `'#,##0.00'`, `'0.00%'`, `'$#,##0'`, `'yyyy-MM-dd'`) or a `(value, row, col) => string` function. Only the *displayed text* changes — editing, sorting, filtering, and export all keep operating on the raw underlying value (give the column an `exportValue` when the file should carry what the list shows, see Export). Use this for number/date/currency display formatting.
173
191
  - **`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.
174
192
 
175
193
  ```typescript
@@ -290,7 +308,17 @@ Default is `false`, matching `clear-undo-on-data-change`.
290
308
  |--------|---------|-------------|
291
309
  | `exportToString(format, options?)` | `string \| Uint8Array` | Export to `'csv'` / `'tsv'` / `'json'` (a string) or `'xlsx'` (bytes, uncompressed). Pass `{ selectionOnly: true }` for selection range, or `{ rows }` to export rows the table does not hold (see below) |
292
310
  | `exportToBlob(format, options?)` | `Promise<Blob>` | The same export as a `Blob` of the format's MIME type — `'xlsx'` is DEFLATE-compressed |
293
- | `exportToFile(format, filename?, options?)` | `Promise<void>` | Export and trigger browser file download (`'xlsx'` compressed) |
311
+ | `exportToFile(format, filename?, options?)` | `Promise<void>` | Export and trigger browser file download (`'xlsx'` compressed). CSV/TSV start with a UTF-8 BOM by default — pass `{ bom: false }` for a file another program loads |
312
+
313
+ What goes into the file:
314
+
315
+ - **Values**: the raw value of each visible column, or the column's `exportValue(value, row)` when it has one — e.g. a
316
+ status code shown as a label: `{ key: 'status', render: …, exportValue: (v) => statusLabel(v) }`.
317
+ - **Dates**: in XLSX a `date`/`datetime` column is a date cell — a `Date`, or an ISO string as JSON sources (OData) send
318
+ it (`YYYY-MM-DD` is that day; a full ISO string is read with its offset), the same rule the cells display with. The
319
+ cell holds the wall-clock time the table shows. A string that does not read as a date stays text.
320
+ - **BOM**: `{ bom: true }` starts CSV/TSV with a UTF-8 byte order mark so Excel on a non-UTF-8 system code page reads
321
+ non-ASCII text correctly — the default for `exportToFile`, off for `exportToString`/`exportToBlob`.
294
322
 
295
323
  The table exports the rows it holds — the filtered rows in sort order, or the selection. **A server-paged table
296
324
  (`data-mode="server"`) holds one page**, so its export is one page. To export what the list shows — the whole result
@@ -312,6 +340,32 @@ try {
312
340
  Without a table, `exportDataBlob(rows, columns, format)` and `downloadBlob(blob, filename)` (root entry) do the same
313
341
  — `exportData` stays synchronous and writes XLSX uncompressed.
314
342
 
343
+ ### Import
344
+
345
+ `importFromFile(file)` reads an `.xlsx`, `.csv` or `.tsv` file into `data` (undoable) — also what dropping a file on a
346
+ table with `import-enabled` does. The first row is the header: each header goes to the column whose `label` — or one
347
+ of its `importAliases` — it matches, exactly first, then ignoring case and surrounding spaces. Each cell is read as its
348
+ column's type, the same way pasting reads it. A CSV may be separated by commas or semicolons; the byte-order mark an
349
+ export starts with is not part of the first header, so an exported file reads back as it was.
350
+
351
+ Nothing is dropped silently. The returned report — the same object `data-import` carries — says what did not come in:
352
+
353
+ ```ts
354
+ const report = await table.importFromFile(file); // null for a file type it does not read
355
+ // { count: 120,
356
+ // unmatchedHeaders: ['비고2'], // their values were not imported
357
+ // missingColumns: ['since'], // empty in every imported row
358
+ // coercionFailures: [{ row: 4, key: 'qty', raw: 'many' }] } // the cell keeps its text
359
+ ```
360
+
361
+ A boolean column reads `true`/`false`/`1`/`0`, the locale's true/false labels and its words (`flexTableLocale` keys
362
+ `booleanTrueWords`/`booleanFalseWords` — `yes,y`/`no,n` in English, `예,네`/`아니오,아니요` in Korean); any other text
363
+ stays text and is reported, rather than becoming `false`.
364
+
365
+ ```ts
366
+ { key: 'code', label: '관리번호', importAliases: ['관리 번호', 'Asset no.'] } // a template a person made
367
+ ```
368
+
315
369
  ## Events
316
370
 
317
371
  All events use `CustomEvent` with `bubbles: true, composed: true`. They are typed: `FlexTableEventMap` maps
@@ -338,7 +392,7 @@ type-checks without a cast. The React wrapper's `on*` props carry the same types
338
392
  | `row-activate` | `{ row, id, via, index, col, key }` | "Open this row" (e.g. navigate to a detail view): a plain click on a body cell (`via: 'click'`), or Enter on a non-editable cell (`via: 'keyboard'`). Not a Shift / Ctrl / Cmd click (those extend the selection), the click that ends a drag, or a click on a control the cell renders (a link, a button). The grid's own contract — its Enter handler keeps the keystroke from reliably reaching a listener the host attaches to the same element |
339
393
  | `batch-update` | `{ changes: [{ row, key, oldValue, newValue }] }` | Batch update applied |
340
394
  | `row-reorder` | `{ from, to }` | Row dragged to a new place (data indices) |
341
- | `data-import` | `{ count }` | Rows imported from a file |
395
+ | `data-import` | `ImportReport` — `{ count, unmatchedHeaders, missingColumns, coercionFailures }` | Rows imported from a file (see Import) |
342
396
  | `fill-handle-apply` | `{ sourceRange, targetRange, cells }` | Fill handle wrote `cells` (`{ dataRow, key, oldValue, newValue }`) |
343
397
  | `find-replace` | `{ type, cells }` | Replace (`type: 'replace'`) or replace-all from the find panel; `cells` are `{ row, col, oldValue, newValue }` with `col` the column key |
344
398
  | `comment-change` | `{ dataIndex, id, colKey, text }` | Cell comment set, changed or removed (`text: null`). Comments stay on their rows (`id`) when rows move |
@@ -785,6 +839,8 @@ const source = useODataSource('/api/orders', {
785
839
  | `initialSearch` | `''` | Initial search term |
786
840
  | `initialSort` | — | Initial sort as `SortCriteria[]`. Takes precedence over `defaultOrderBy` — it is the shape `onSortChange` hands you, so a stored sort round-trips without re-serializing it |
787
841
  | `fixedFilter` | — | Filter always applied in addition to search. Changing it resets the page to 0 — see below |
842
+ | `expand` | — | `$expand` — referenced records to fetch with each row: `'Customer($select=Name),Owner'` or `['Customer', 'Owner']`. A column reads one with a dot-path key (`key: 'Customer.Name'`), and its server sort is `$orderby=Customer/Name`. The page reads and `fetchAll` send the same value |
843
+ | `select` | — | `$select` — the properties to fetch; all when omitted |
788
844
  | `baseUrl` | `window.location.origin` | Override the request origin (proxy/BFF setups) |
789
845
  | `fetcher` | global `fetch` | Custom transport — pass a wrapper that injects auth headers |
790
846
  | `onUnauthorized` | — | Called on `401` responses, before the generic error is set. A `403` (signed in, not permitted) does not call it — it surfaces as `error` |
@@ -1,5 +1,5 @@
1
- import { n as e, t, u as n } from "../fetch-all-J37bOtgc.js";
2
- import { n as r, t as i } from "../view-BtoXdUGF.js";
1
+ import { n as e, t, u as n } from "../fetch-all-DkdNzWrF.js";
2
+ import { n as r, t as i } from "../view-DuDIMoXV.js";
3
3
  //#region src/array/source.ts
4
4
  function a(e, t = {}) {
5
5
  let a = e, o = t, s = n({
@@ -6,6 +6,17 @@ import type { ColumnDefinition, DataRow } from '../models/types.js';
6
6
  */
7
7
  export declare function copyToClipboard(data: DataRow[], columns: ColumnDefinition[], range: CellRange): string;
8
8
  export declare function parseValueForColumn(raw: string, col: ColumnDefinition): unknown;
9
+ /**
10
+ * {@link parseValueForColumn} with the outcome: `failed` is true when the column has a type (`number`, `boolean`,
11
+ * `date`, `datetime`) and the text is not one — the value is then the text itself, unchanged. An importer reports
12
+ * those cells instead of losing them.
13
+ */
14
+ export declare function parseCellForColumn(raw: string, col: ColumnDefinition): {
15
+ value: unknown;
16
+ failed: boolean;
17
+ };
18
+ /** A boolean as a spreadsheet writes it, or `null` when the text is not one. */
19
+ export declare function parseBoolean(raw: string): boolean | null;
9
20
  /**
10
21
  * A number as a person edits it: the active locale's decimal separator, no grouping, every digit
11
22
  * kept (`1234.5` → `1234,5` on a German page). The inverse is {@link parseValueForColumn}.
@@ -0,0 +1,13 @@
1
+ import type { DataRow } from '../models/types.js';
2
+ /**
3
+ * A column's value in a row. `key` is a property name, or a dot path into nested objects — `'Customer.Name'` reads
4
+ * `row.Customer.Name` (an OData `$expand`, a joined record). A row that has a property by the whole name (`'a.b'`,
5
+ * `'@odata.etag'`) gives that property: the path is only read when the name is not there. Every place the table reads
6
+ * a cell — display, format, sort, filter, copy, export — goes through this, so they agree.
7
+ */
8
+ export declare function getCellValue(row: DataRow | null | undefined, key: string): unknown;
9
+ /**
10
+ * Writes a column's value — the inverse of {@link getCellValue}: the property by the whole name when the row has it
11
+ * (or the key has no dot), otherwise the path, creating the objects along it that are missing.
12
+ */
13
+ export declare function setCellValue(row: DataRow, key: string, value: unknown): void;
package/dist/events.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ImportReport } from './export/import.js';
1
2
  import type { CellPosition, CellRange } from './core/selection.js';
2
3
  import type { SortCriteria } from './core/sorting.js';
3
4
  import type { ColumnDefinition, DataRow } from './models/types.js';
@@ -143,10 +144,8 @@ export interface FlexTableEventMap {
143
144
  colKey: string;
144
145
  text: string | null;
145
146
  }>;
146
- /** Rows were imported from a file; `count` is how many. */
147
- 'data-import': CustomEvent<{
148
- count: number;
149
- }>;
147
+ /** Rows were imported from a file — the same report `importFromFile` returns: `count`, and what did not come in. */
148
+ 'data-import': CustomEvent<ImportReport>;
150
149
  'sort-change': CustomEvent<{
151
150
  criteria: SortCriteria[];
152
151
  }>;
@@ -0,0 +1,11 @@
1
+ import type { ImportedSheet } from './xlsx-reader.js';
2
+ /**
3
+ * The separator a CSV file uses — `,` or, as Excel writes it on locales whose decimal mark is a comma, `;` (a tab
4
+ * also counts). Counted on the first line outside quotes; the most frequent wins, and `,` when none appears.
5
+ */
6
+ export declare function detectDelimiter(text: string): string;
7
+ /**
8
+ * A CSV or TSV file as a header row and data rows. The byte-order mark a spreadsheet-bound export starts with
9
+ * (`exportToFile` writes one) is not part of the first header.
10
+ */
11
+ export declare function readDelimited(text: string, kind: 'csv' | 'tsv'): ImportedSheet;
@@ -1,15 +1,24 @@
1
1
  import type { ColumnDefinition, DataRow } from '../models/types.js';
2
2
  export type ExportFormat = 'csv' | 'tsv' | 'json' | 'xlsx';
3
+ /** Options for `exportData` / `exportDataBlob`. */
4
+ export interface ExportOptions {
5
+ /**
6
+ * CSV/TSV only — start the text with a UTF-8 byte order mark. Spreadsheet apps (Excel on a non-UTF-8 system
7
+ * code page, e.g. Korean Windows) read a CSV without one in the system code page and garble non-ASCII text.
8
+ * Leave it off for files another program loads. Default: `false`.
9
+ */
10
+ bom?: boolean;
11
+ }
3
12
  /**
4
13
  * Export data to the specified format.
5
14
  * Returns string for text formats (csv/tsv/json) or Uint8Array for xlsx.
6
15
  */
7
- export declare function exportData(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat): string | Uint8Array<ArrayBuffer>;
16
+ export declare function exportData(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat, options?: ExportOptions): string | Uint8Array<ArrayBuffer>;
8
17
  /**
9
18
  * Export data as a `Blob` of the format's MIME type. XLSX is DEFLATE-compressed (unlike `exportData`,
10
19
  * which stays synchronous and therefore stores the workbook uncompressed).
11
20
  */
12
- export declare function exportDataBlob(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat): Promise<Blob>;
21
+ export declare function exportDataBlob(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat, options?: ExportOptions): Promise<Blob>;
13
22
  /**
14
23
  * Trigger a file download in the browser.
15
24
  */
@@ -0,0 +1,30 @@
1
+ import type { ColumnDefinition, DataRow } from '../models/types.js';
2
+ import type { ImportedSheet } from './xlsx-reader.js';
3
+ /**
4
+ * What an import took in and what it could not — `importFromFile` returns it and `data-import` carries it, so a
5
+ * preview can show «what will not come in» before anything is saved.
6
+ */
7
+ export interface ImportReport {
8
+ /** Rows imported. */
9
+ count: number;
10
+ /** File headers no column matched (by `label` or `importAliases`) — their values were not imported. */
11
+ unmatchedHeaders: string[];
12
+ /** Keys of the columns no file header matched — those cells are empty in every imported row. */
13
+ missingColumns: string[];
14
+ /**
15
+ * Cells whose text is not a value of the column's type (`number`, `boolean`, `date`, `datetime`). The cell keeps the
16
+ * text as it was. `row` is the 0-based index among the imported rows.
17
+ */
18
+ coercionFailures: {
19
+ row: number;
20
+ key: string;
21
+ raw: string;
22
+ }[];
23
+ }
24
+ /** File header → column key: the label or an alias, exactly first, then ignoring case and surrounding spaces. */
25
+ export declare function matchHeaders(headers: string[], columns: ColumnDefinition[]): Map<number, string>;
26
+ /** A parsed sheet as table rows, with the report of what did not come in. */
27
+ export declare function buildImport(sheet: ImportedSheet, columns: ColumnDefinition[]): {
28
+ rows: DataRow[];
29
+ report: ImportReport;
30
+ };
@@ -0,0 +1,17 @@
1
+ import type { ColumnDefinition, DataRow } from '../models/types.js';
2
+ /**
3
+ * 내보낼 셀 값 — 열이 `exportValue` 를 주면 그 결과, 아니면 원시값. 표시 규칙(`format`·`render`)은 쓰지 않는다:
4
+ * 원시값이 맞는 내보내기(다시 적재)가 있고, 라벨이 맞는 열은 그것을 열 스스로 말한다.
5
+ */
6
+ export declare function exportCellValue(row: DataRow, col: ColumnDefinition): unknown;
7
+ /**
8
+ * 날짜로 내보낼 값이면 `Date` — 표시 경로(`@iyulab/components` `formatDate`)와 같은 규칙이다: `Date` 는 그대로, 날짜 열의
9
+ * 문자열은 `YYYY-MM-DD` 면 그 날(로컬 달력), 아니면 ISO 로 읽는다. 읽지 못하면 `null`(글자로 남긴다 — 버리지 않는다).
10
+ * JSON 으로 오는 소스(OData 포함)는 날짜가 문자열이라, 종전에는 날짜 열이어도 XLSX 에 글자 셀로 들어갔다.
11
+ */
12
+ export declare function exportDate(value: unknown, col: ColumnDefinition): Date | null;
13
+ /**
14
+ * Excel 직렬값 — **벽시계 시각**으로 센다(표가 보여 주는 로컬 날짜·시각과 같은 칸). 직렬값에는 시간대가 없어, UTC 시각으로
15
+ * 세면 로컬 자정의 날짜가 UTC 와 다른 시간대(한국 +09)에서 전날 오후로 들어가 날짜 서식에 전날이 보였다.
16
+ */
17
+ export declare function excelSerial(d: Date): number;
@@ -1,4 +1,4 @@
1
- import { n as e } from "./locale-D9g0ksXq.js";
1
+ import { n as e } from "./locale-Covm8PfH.js";
2
2
  import t from "odata-query";
3
3
  //#region src/odata/query.ts
4
4
  function n(e) {
@@ -17,26 +17,29 @@ function i(e) {
17
17
  return e.split(",").map((e) => {
18
18
  let t = e.trim().split(/\s+/);
19
19
  return {
20
- key: t[0],
20
+ key: t[0].replace(/\//g, "."),
21
21
  direction: t[1]?.toLowerCase() === "desc" ? "desc" : "asc"
22
22
  };
23
23
  });
24
24
  }
25
25
  function a(e) {
26
- let { page: r = 0, pageSize: i, sortCriteria: a = [], defaultOrderBy: o, search: s, fixedFilter: c } = e, l = a.length > 0 ? a.map((e) => `${e.key} ${e.direction}`).join(", ") : o, u = i === void 0 ? { count: !0 } : {
26
+ return e.replace(/\./g, "/");
27
+ }
28
+ function o(e) {
29
+ let { page: r = 0, pageSize: i, sortCriteria: o = [], defaultOrderBy: s, search: c, fixedFilter: l, expand: u, select: d } = e, f = o.length > 0 ? o.map((e) => `${a(e.key)} ${e.direction}`).join(", ") : s, p = i === void 0 ? { count: !0 } : {
27
30
  top: i,
28
31
  skip: r * i,
29
32
  count: !0
30
33
  };
31
- if (l && (u.orderBy = l), c && (u.filter = c), s) {
32
- let e = n(s);
33
- e && (u.search = e);
34
+ if (f && (p.orderBy = f), l && (p.filter = l), u && u.length > 0 && (p.expand = u), d && d.length > 0 && (p.select = d), c) {
35
+ let e = n(c);
36
+ e && (p.search = e);
34
37
  }
35
- return t(u);
38
+ return t(p);
36
39
  }
37
40
  //#endregion
38
41
  //#region src/core/source-error.ts
39
- async function o(t) {
42
+ async function s(t) {
40
43
  let n = await t.text().catch(() => ""), r = {
41
44
  message: e("requestFailed", { status: t.status }),
42
45
  status: t.status
@@ -49,10 +52,10 @@ async function o(t) {
49
52
  if (r.body = i, !i || typeof i != "object") return r;
50
53
  let a = i, o = a.error && typeof a.error == "object" ? a.error : a;
51
54
  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);
52
- let c = s(o.details);
53
- return c && (r.details = c), r;
55
+ let s = c(o.details);
56
+ return s && (r.details = s), r;
54
57
  }
55
- function s(e) {
58
+ function c(e) {
56
59
  if (!Array.isArray(e)) return;
57
60
  let t = e.filter((e) => {
58
61
  if (!e || typeof e != "object") return !1;
@@ -61,26 +64,26 @@ function s(e) {
61
64
  });
62
65
  return t.length > 0 ? t : void 0;
63
66
  }
64
- var c = class extends Error {
67
+ var l = class extends Error {
65
68
  constructor(e) {
66
69
  super(e.message), this.name = "SourceRequestError", this.failure = e;
67
70
  }
68
- }, l = class extends c {
71
+ }, u = class extends l {
69
72
  constructor(t, n) {
70
73
  super({ message: e("tooManyRows", { maxRows: t }) }), this.name = "RowLimitError", this.total = n, this.maxRows = t;
71
74
  }
72
75
  };
73
- function u(t) {
74
- return new c({
76
+ function d(t) {
77
+ return new l({
75
78
  message: e("networkFailed"),
76
79
  cause: t
77
80
  });
78
81
  }
79
- function d(e) {
80
- return e instanceof c ? e.failure : e instanceof Error ? { message: e.message } : { message: String(e) };
82
+ function f(e) {
83
+ return e instanceof l ? e.failure : e instanceof Error ? { message: e.message } : { message: String(e) };
81
84
  }
82
85
  //#endregion
83
86
  //#region src/core/fetch-all.ts
84
- var f = 1e5;
87
+ var p = 1e5;
85
88
  //#endregion
86
- export { o as a, n as c, u as i, i as l, l as n, d as o, c as r, a as s, f as t, r as u };
89
+ export { s as a, n as c, d as i, i as l, u as n, f as o, l as r, o as s, p as t, r as u };