@iyulab/flex-table 0.62.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.
@@ -1,6 +1,7 @@
1
1
  import { LitElement, type PropertyValues } from 'lit';
2
2
  import '@iyulab/components/dist/components/date-picker/UDatePicker.js';
3
3
  import type { ExportFormat } from './export/export.js';
4
+ import type { ImportReport } from './export/import.js';
4
5
  import type { CellPosition, CellRange } from './core/selection.js';
5
6
  import type { SortCriteria } from './core/sorting.js';
6
7
  import type { FilterPredicate } from './core/filtering.js';
@@ -381,14 +382,14 @@ export declare class FlexTable extends LitElement {
381
382
  */
382
383
  clearComments(): void;
383
384
  /**
384
- * Import data from an xlsx or csv File.
385
- * Dispatches 'data-import' event with { count } on success.
385
+ * Imports an `.xlsx`, `.csv` or `.tsv` file — the first row is the header, matched to columns by `label` or
386
+ * `importAliases`, and each cell is read as its column's type. Replaces `data` (undoable) and fires `data-import`.
387
+ * Returns the report of what came in and what did not (headers no column matched, columns the file lacks, cells
388
+ * that are not their column's type — those keep their text); `null` for a file type it does not read.
389
+ * A CSV may be separated by commas or semicolons; a leading byte-order mark is not part of the first header.
386
390
  */
387
- importFromFile(file: File): Promise<void>;
391
+ importFromFile(file: File): Promise<ImportReport | null>;
388
392
  private _applyImportedSheet;
389
- private _applyImportedRows;
390
- /** Map header text → column key using exact header match (case-insensitive fallback). */
391
- private _buildHeaderColumnMap;
392
393
  private _onDragover;
393
394
  private _onDragleave;
394
395
  private _onDrop;
@@ -1,3 +1,4 @@
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-CbBVOhRQ.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 };
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-BufHlQ2v.js";
2
+ import { t as c } from "./locale-Covm8PfH.js";
3
+ import { i as l, r as u } from "./sorting-BJszwEHw.js";
4
+ 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, u as getCellValue, t as renderCell, l as setCellValue };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { FlexTable } from './flex-table.js';
2
2
  export type { TableExportOptions } from './flex-table.js';
3
3
  export type { ColumnDefinition, ColumnType, ColumnAlign, DataRow, CellRenderer, CellEditor, CellValidator, SelectionMode, DataMode, CellStyle, ConditionalRule } from './models/types.js';
4
4
  export { effectiveAlign } from './models/types.js';
5
+ export { getCellValue, setCellValue } from './core/cell-value.js';
5
6
  export type { CellPosition, CellRange } from './core/selection.js';
6
7
  export type { FlexTableEventMap, CellChange } from './events.js';
7
8
  export type { SortCriteria, SortDirection } from './core/sorting.js';
@@ -11,6 +12,7 @@ export { UndoStack } from './core/undo.js';
11
12
  export type { UndoAction } from './core/undo.js';
12
13
  export type { ExportFormat, ExportOptions } from './export/export.js';
13
14
  export { exportData, exportDataBlob, downloadBlob } from './export/export.js';
15
+ export type { ImportReport } from './export/import.js';
14
16
  export { renderCell } from './renderers/cell-renderer.js';
15
17
  export { flexTableLocale } from './locale.js';
16
18
  export type { FlexTableMessageKey } from './locale.js';
@@ -66,6 +66,8 @@ t.register("en", {
66
66
  deleteComment: "Delete Comment",
67
67
  booleanTrue: "True",
68
68
  booleanFalse: "False",
69
+ booleanTrueWords: "yes,y",
70
+ booleanFalseWords: "no,n",
69
71
  dropFileToImport: "Drop file to import (.xlsx / .csv)",
70
72
  notANumber: "Enter a number",
71
73
  notADate: "Enter a date as YYYY-MM-DD",
@@ -139,6 +141,8 @@ t.register("en", {
139
141
  deleteComment: "메모 삭제",
140
142
  booleanTrue: "참",
141
143
  booleanFalse: "거짓",
144
+ booleanTrueWords: "예,네,yes,y",
145
+ booleanFalseWords: "아니오,아니요,no,n",
142
146
  dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)",
143
147
  notANumber: "숫자를 입력하세요",
144
148
  notADate: "날짜를 YYYY-MM-DD 로 입력하세요",
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' | 'tooManyRows';
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' | 'booleanTrueWords' | 'booleanFalseWords' | '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
  /** 짧은 조회 별칭 — 렌더 코드가 읽히게 유지한다. */
@@ -108,6 +108,11 @@ export interface ColumnDefinition<T = DataRow> {
108
108
  * code shown as a label: `exportValue: (v) => statusLabel(v)`. A returned `Date` becomes a date cell in XLSX.
109
109
  */
110
110
  exportValue?: (value: unknown, row: T) => string | number | boolean | Date | null | undefined;
111
+ /**
112
+ * Other headers an imported file may give this column (`importFromFile`) — a template a person made says
113
+ * «관리 번호» where the label is «관리번호». Matched like the label: exactly, then ignoring case and surrounding spaces.
114
+ */
115
+ importAliases?: string[];
111
116
  /** Per-column conditional formatting rules applied during cell rendering */
112
117
  conditionalRules?: ConditionalRule<T>[];
113
118
  /**
@@ -1,5 +1,5 @@
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";
1
+ import { c as e, l as t, n, r, s as i, t as a } from "../fetch-all-DkdNzWrF.js";
2
+ import { t as o } from "../source-dm6qXFh1.js";
3
3
  //#region src/odata/controller.ts
4
4
  var s = class {
5
5
  constructor(e, t, n = {}) {
@@ -65,7 +65,13 @@ export interface ODataQueryState {
65
65
  search?: string;
66
66
  /** odata-query 의 필터 객체(`{ IsActive: true }` 등). */
67
67
  fixedFilter?: Record<string, unknown>;
68
+ /** `$expand` — 문자열(`'Customer($select=Name)'`) 또는 배열(쉼표로 잇는다). */
69
+ expand?: string | string[];
70
+ /** `$select` — 받을 속성 이름. */
71
+ select?: string[];
68
72
  }
73
+ /** 열 키(점 경로 `Customer.Name`)를 `$orderby` 의 속성 경로(`Customer/Name`)로. */
74
+ export declare function orderByPath(key: string): string;
69
75
  /**
70
76
  * 표 상태를 OData 쿼리 문자열(`?$top=…&$skip=…&$count=true…`)로 만든다.
71
77
  *
@@ -19,6 +19,13 @@ export interface ODataSourceOptions {
19
19
  initialSort?: SortCriteria[];
20
20
  /** 고정 필터. 값(직렬화)이 바뀌면 페이지가 첫 장으로 돌아간다 — 참조만 다른 같은 값은 아무 일도 없다. */
21
21
  fixedFilter?: Record<string, unknown>;
22
+ /**
23
+ * `$expand` — 참조(navigation)를 함께 받는다: `'Customer($select=Name),Owner'` 또는 `['Customer', 'Owner']`. 열은 점 경로
24
+ * 키(`Customer.Name`)로 그 값을 읽고, 그 열의 서버 정렬은 `$orderby=Customer/Name` 이 된다. 페이지 읽기와 `fetchAll` 이 같은 값을 낸다.
25
+ */
26
+ expand?: string | string[];
27
+ /** `$select` — 받을 속성 이름. 생략하면 `$select` 없이 전부. */
28
+ select?: string[];
22
29
  /** 기본값: `window.location.origin`. 프록시/BFF 등 다른 origin 으로 요청해야 할 때 지정. */
23
30
  baseUrl?: string;
24
31
  /** 커스텀 fetch transport(예: 인증 헤더를 주입하는 `HttpClient` 래퍼). 기본값: 전역 `fetch`. */
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
- import { t as e } from "./flex-table-CbBVOhRQ.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";
1
+ import { t as e } from "./flex-table-BufHlQ2v.js";
2
+ import { n as t, r as n, u as r } from "./fetch-all-DkdNzWrF.js";
3
+ import { t as i } from "./source-dm6qXFh1.js";
4
+ import { n as a, t as o } from "./view-DuDIMoXV.js";
5
5
  import s, { useCallback as c, useEffect as l, useMemo as u, useState as d, useSyncExternalStore as f } from "react";
6
6
  import { createComponent as p } from "@lit/react";
7
7
  //#region src/odata/use-odata-source.ts
@@ -0,0 +1,75 @@
1
+ //#region src/core/cell-value.ts
2
+ function e(e, t) {
3
+ if (e == null) return;
4
+ if (t in e || !t.includes(".")) return e[t];
5
+ let n = e;
6
+ for (let e of t.split(".")) {
7
+ if (typeof n != "object" || !n) return;
8
+ n = n[e];
9
+ }
10
+ return n;
11
+ }
12
+ function t(e, t, n) {
13
+ if (t in e || !t.includes(".")) {
14
+ e[t] = n;
15
+ return;
16
+ }
17
+ let r = t.split("."), i = e;
18
+ for (let e of r.slice(0, -1)) {
19
+ let t = i[e];
20
+ (typeof t != "object" || !t) && (i[e] = {}), i = i[e];
21
+ }
22
+ i[r[r.length - 1]] = n;
23
+ }
24
+ //#endregion
25
+ //#region src/core/sorting.ts
26
+ function n(t, n, i) {
27
+ let a = Array.from({ length: t.length }, (e, t) => t);
28
+ if (n.length === 0) return a;
29
+ let o = /* @__PURE__ */ new Map();
30
+ for (let e of i) o.set(e.key, e.type ?? "text");
31
+ return a.sort((i, a) => {
32
+ for (let { key: s, direction: c } of n) {
33
+ let n = e(t[i], s), l = e(t[a], s), u = n == null, d = l == null;
34
+ if (u && d) continue;
35
+ if (u) return 1;
36
+ if (d) return -1;
37
+ let f = r(n, l, o.get(s) ?? "text");
38
+ if (f !== 0) return c === "asc" ? f : -f;
39
+ }
40
+ return i - a;
41
+ }), a;
42
+ }
43
+ function r(e, t, n) {
44
+ switch (n) {
45
+ case "number": {
46
+ let n = Number(e), r = Number(t);
47
+ return isNaN(n) && isNaN(r) ? 0 : isNaN(n) ? 1 : isNaN(r) ? -1 : n - r;
48
+ }
49
+ case "boolean": return !!e - +!!t;
50
+ case "date":
51
+ case "datetime": {
52
+ let n = new Date(e).getTime(), r = new Date(t).getTime();
53
+ return (isNaN(n) ? 0 : n) - (isNaN(r) ? 0 : r);
54
+ }
55
+ default: return String(e).localeCompare(String(t));
56
+ }
57
+ }
58
+ function i(e, t, n) {
59
+ let r = e.find((e) => e.key === t);
60
+ return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
61
+ ...e,
62
+ direction: "desc"
63
+ } : e) : e.filter((e) => e.key !== t) : [...e, {
64
+ key: t,
65
+ direction: "asc"
66
+ }] : r ? r.direction === "asc" ? [{
67
+ key: t,
68
+ direction: "desc"
69
+ }] : [] : [{
70
+ key: t,
71
+ direction: "asc"
72
+ }];
73
+ }
74
+ //#endregion
75
+ export { t as i, i as n, e as r, n as t };
@@ -1,4 +1,4 @@
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";
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-DkdNzWrF.js";
2
2
  //#region src/odata/source.ts
3
3
  function c(e, t = {}) {
4
4
  let i = e, c = t, d = u(t.fixedFilter), f = s({
@@ -48,6 +48,8 @@ function c(e, t = {}) {
48
48
  b(),
49
49
  c.defaultOrderBy,
50
50
  d,
51
+ c.expand,
52
+ c.select,
51
53
  p.page,
52
54
  p.sortCriteria,
53
55
  p.search
@@ -82,7 +84,9 @@ function c(e, t = {}) {
82
84
  sortCriteria: n,
83
85
  defaultOrderBy: c.defaultOrderBy,
84
86
  search: o,
85
- fixedFilter: c.fixedFilter
87
+ fixedFilter: c.fixedFilter,
88
+ expand: c.expand,
89
+ select: c.select
86
90
  });
87
91
  l(`${c.baseUrl ?? window.location.origin}${i}${f}`, {
88
92
  fetcher: u,
@@ -147,7 +151,9 @@ function c(e, t = {}) {
147
151
  sortCriteria: s,
148
152
  defaultOrderBy: c.defaultOrderBy,
149
153
  search: u,
150
- fixedFilter: c.fixedFilter
154
+ fixedFilter: c.fixedFilter,
155
+ expand: c.expand,
156
+ select: c.select
151
157
  }), { rows: f } = await l(`${c.baseUrl ?? window.location.origin}${i}${d}`, {
152
158
  fetcher: c.fetcher ?? fetch,
153
159
  signal: t,
@@ -1,5 +1,5 @@
1
- import { t as e } from "./sorting-CjfjRxwL.js";
2
- import { n as t, t as n } from "./fetch-all-J37bOtgc.js";
1
+ import { t as e } from "./sorting-BJszwEHw.js";
2
+ import { n as t, t as n } from "./fetch-all-DkdNzWrF.js";
3
3
  //#region src/array/view.ts
4
4
  function r(t, { search: n, sortCriteria: r, page: i, pageSize: a, columns: o, searchFields: s }) {
5
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.62.0",
3
+ "version": "0.63.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.15.0",
77
+ "@iyulab/components": ">=2.18.0",
78
78
  "@lit/react": "^1.0.8",
79
79
  "react": "^18.0.0 || ^19.0.0"
80
80
  },
@@ -50,7 +50,7 @@ Replacing `data` with the same array reference does not trigger the clear-on-cha
50
50
 
51
51
  | Field | Type | Notes |
52
52
  |---|---|---|
53
- | `key` | `string` | Property name in the row (required) |
53
+ | `key` | `string` | Property name in the row, or a dot path into a nested record (`'Customer.Name'`) — display, sort, filter, copy, edit, import and export all read it the same way; a property named by the whole key (`'@odata.etag'`) wins over the path (required) |
54
54
  | `label` | `string` | Header text (required) |
55
55
  | `type` | `ColumnType` | `'text' \| 'number' \| 'boolean' \| 'date' \| 'datetime' \| 'select'`; other strings act as text |
56
56
  | `width` / `minWidth` | `number` | px; `minWidth` defaults to 40 |
@@ -130,7 +130,7 @@ Enter/Escape and blur-to-commit behavior.
130
130
  | `undo()` / `redo()` / `clearUndoHistory()` | |
131
131
  | `setComment(dataIndex, colKey, text)` | `null` or `''` removes; undoable |
132
132
  | `getComment(dataIndex, colKey)` / `clearComments()` | |
133
- | `importFromFile(file)` | `Promise<void>`; `.xlsx`, `.csv`, `.tsv`; fires `data-import` |
133
+ | `importFromFile(file)` | `Promise<ImportReport \| null>`; `.xlsx`, `.csv` (comma or semicolon), `.tsv`; headers match `label` or `importAliases`; fires `data-import` with the same report — `{ count, unmatchedHeaders, missingColumns, coercionFailures }`; a cell that is not its column's type keeps its text and is reported (an unread boolean is not `false`) |
134
134
  | `exportToString(format, { selectionOnly? } \| { rows })` | `string \| Uint8Array`; format `'csv' \| 'tsv' \| 'json' \| 'xlsx'` (xlsx returns uncompressed bytes — synchronous). `rows`: export these rows with the visible columns |
135
135
  | `exportToBlob(format, options?)` | `Promise<Blob>` typed with the format's MIME; xlsx is DEFLATE-compressed |
136
136
  | `exportToFile(format, filename?, options?)` | `Promise<void>` — triggers a download (xlsx compressed); CSV/TSV start with a UTF-8 BOM unless `{ bom: false }` |
@@ -176,7 +176,7 @@ cast, and the React `on*` props carry the same types.
176
176
  | `fill-handle-apply` | `{ sourceRange, targetRange, cells }` |
177
177
  | `find-replace` | `{ type: 'replace' \| 'replace-all', cells }` |
178
178
  | `comment-change` | `{ dataIndex, id, colKey, text }` |
179
- | `data-import` | `{ count }` |
179
+ | `data-import` | `ImportReport` — `{ count, unmatchedHeaders, missingColumns, coercionFailures }` |
180
180
  | `undo-state-change` | `{ canUndo, canRedo }` |
181
181
  | `context-menu` | `{ x, y, row, col, key, value, rowData }` — cancelable; `preventDefault()` suppresses the built-in menu |
182
182
  | `header-context-menu` | `{ key, label, x, y }` |
@@ -97,6 +97,8 @@ function Orders() {
97
97
  | `initialSearch` | `''` | First render only |
98
98
  | `initialSort` | — | `SortCriteria[]`; overrides `defaultOrderBy`; `[]` means no sort |
99
99
  | `fixedFilter` | — | odata-query filter object, always applied; value change resets to page 0 (compared by value) |
100
+ | `expand` | — | `$expand` string or array; columns read it with dot-path keys (`'Customer.Name'` → server sort `Customer/Name`); `fetchAll` sends it too |
101
+ | `select` | — | `$select` property names |
100
102
  | `baseUrl` | `window.location.origin` | For proxy/BFF setups |
101
103
  | `fetcher` | global `fetch` | `(input, init) => Promise<Response>`; read when each request starts |
102
104
  | `onUnauthorized` | — | `(response) => void` on 401 only (403 surfaces as `error`); read when each request starts |
@@ -1,51 +0,0 @@
1
- //#region src/core/sorting.ts
2
- function e(e, n, r) {
3
- let i = Array.from({ length: e.length }, (e, t) => t);
4
- if (n.length === 0) return i;
5
- let a = /* @__PURE__ */ new Map();
6
- for (let e of r) a.set(e.key, e.type ?? "text");
7
- return i.sort((r, i) => {
8
- for (let { key: o, direction: s } of n) {
9
- let n = e[r][o], c = e[i][o], l = n == null, u = c == null;
10
- if (l && u) continue;
11
- if (l) return 1;
12
- if (u) return -1;
13
- let d = t(n, c, a.get(o) ?? "text");
14
- if (d !== 0) return s === "asc" ? d : -d;
15
- }
16
- return r - i;
17
- }), i;
18
- }
19
- function t(e, t, n) {
20
- switch (n) {
21
- case "number": {
22
- let n = Number(e), r = Number(t);
23
- return isNaN(n) && isNaN(r) ? 0 : isNaN(n) ? 1 : isNaN(r) ? -1 : n - r;
24
- }
25
- case "boolean": return !!e - +!!t;
26
- case "date":
27
- case "datetime": {
28
- let n = new Date(e).getTime(), r = new Date(t).getTime();
29
- return (isNaN(n) ? 0 : n) - (isNaN(r) ? 0 : r);
30
- }
31
- default: return String(e).localeCompare(String(t));
32
- }
33
- }
34
- function n(e, t, n) {
35
- let r = e.find((e) => e.key === t);
36
- return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
37
- ...e,
38
- direction: "desc"
39
- } : e) : e.filter((e) => e.key !== t) : [...e, {
40
- key: t,
41
- direction: "asc"
42
- }] : r ? r.direction === "asc" ? [{
43
- key: t,
44
- direction: "desc"
45
- }] : [] : [{
46
- key: t,
47
- direction: "asc"
48
- }];
49
- }
50
- //#endregion
51
- export { n, e as t };