cenitu-table 0.2.0 → 0.4.0-beta.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/README.md +226 -137
- package/README.tr.md +224 -126
- package/dist/cenitu-table.cjs +1 -1
- package/dist/cenitu-table.js +34 -31
- package/dist/index-BIH30fQ2.js +6571 -0
- package/dist/index-Bidvqh7P.cjs +197 -0
- package/dist/react.cjs +1 -1
- package/dist/react.js +67 -50
- package/dist/types/export/index.d.ts +2 -0
- package/dist/types/export/types.d.ts +1 -0
- package/dist/types/export/unzip.d.ts +21 -0
- package/dist/types/export/xlsxRead.d.ts +35 -0
- package/dist/types/export/xlsxStyles.d.ts +23 -0
- package/dist/types/export/xmlReader.d.ts +15 -0
- package/dist/types/grid/cellTypes.d.ts +10 -1
- package/dist/types/grid/clipboardHtml.d.ts +13 -0
- package/dist/types/grid/columnMenu.d.ts +11 -1
- package/dist/types/grid/filters.d.ts +3 -2
- package/dist/types/grid/grid.d.ts +162 -10
- package/dist/types/grid/messages.d.ts +28 -0
- package/dist/types/grid/search.d.ts +41 -0
- package/dist/types/grid/serverMode.d.ts +66 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/react/index.d.ts +8 -1
- package/package.json +1 -1
- package/dist/index-BJIaMXd1.cjs +0 -164
- package/dist/index-DG98ykBX.js +0 -5230
package/dist/react.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("react/jsx-runtime"),s=require("react"),h=require("./index-Bidvqh7P.cjs"),w=["fixedRowsTop","fixedColumnsStart","readOnly","columns","colHeaders","mergeCells","columnSorting","filters","fillHandle","locale","language","contextMenu","search","query","totalCount","loading","loadError"],H=s.forwardRef(function(e,C){const f=s.useRef(null),u=s.useRef(null),r=s.useRef(e);r.current=e,s.useLayoutEffect(()=>{const{className:a,style:y,onChange:m,onSelection:x,onSort:E,onFilter:D,onQueryChange:j,onRowClick:v,onRowDoubleClick:q,onColumnLayoutChange:L,..._}=r.current,c=new h.CenituGrid(f.current,_);return c.addHook("afterChange",(o,n)=>{var t,l;return(l=(t=r.current).onChange)==null?void 0:l.call(t,o,n)}),c.addHook("afterSelection",(o,n,t,l)=>{var R,S;return(S=(R=r.current).onSelection)==null?void 0:S.call(R,o,n,t,l)}),c.addHook("afterColumnSort",(o,n)=>{var t,l;return(l=(t=r.current).onSort)==null?void 0:l.call(t,o,n)}),c.addHook("afterFilter",o=>{var n,t;return(t=(n=r.current).onFilter)==null?void 0:t.call(n,o)}),c.addHook("afterQueryChange",(o,n)=>{var t,l;return(l=(t=r.current).onQueryChange)==null?void 0:l.call(t,o,n)}),c.addHook("afterRowClick",o=>{var n,t;return(t=(n=r.current).onRowClick)==null?void 0:t.call(n,o)}),c.addHook("afterRowDoubleClick",o=>{var n,t;return(t=(n=r.current).onRowDoubleClick)==null?void 0:t.call(n,o)}),c.addHook("afterColumnLayout",o=>{var n,t;return(t=(n=r.current).onColumnLayoutChange)==null?void 0:t.call(n,o)}),u.current=c,()=>{c.destroy(),u.current=null}},[]),s.useImperativeHandle(C,()=>u.current,[]);const g=s.useRef(!1);s.useEffect(()=>{if(!g.current)return;const a=u.current;!a||!e.data||(e.dataMode==="server"?a.setPageRows(e.data,e.totalCount):T(a,e.data)||a.loadData(e.data))},[e.data]);const d=w.map(a=>e[a]);return s.useEffect(()=>{var y;if(!g.current)return;const a={};w.forEach(m=>e[m]!==void 0&&(a[m]=e[m])),(y=u.current)==null||y.updateSettings(a)},d),s.useEffect(()=>{g.current=!0},[]),b.jsx("div",{ref:f,className:e.className,style:e.style})});function T(i,e){if(!h.isObjectData(e))return k(i.getSourceData(),e);if(i.getSourceObjects()===e)return!0;const C=Array.from({length:i.countCols()},(f,u)=>i.colToProp(u));return k(i.getBoundRows(),h.ObjectBinding.create(e,C).toRows())}function k(i,e){const C=Math.max(i.length,e.length);for(let f=0;f<C;f++){const u=i[f]??[],r=e[f]??[],g=Math.max(u.length,r.length);for(let d=0;d<g;d++)if((u[d]??null)!==(r[d]??null))return!1}return!0}exports.CenituGrid=h.CenituGrid;exports.CenituTable=H;
|
package/dist/react.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import { C as
|
|
4
|
-
const
|
|
1
|
+
import { jsx as H } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as x, useRef as g, useLayoutEffect as b, useImperativeHandle as D, useEffect as y } from "react";
|
|
3
|
+
import { C as E, i as T, O as v } from "./index-BIH30fQ2.js";
|
|
4
|
+
const k = [
|
|
5
5
|
"fixedRowsTop",
|
|
6
6
|
"fixedColumnsStart",
|
|
7
7
|
"readOnly",
|
|
@@ -13,58 +13,75 @@ const _ = [
|
|
|
13
13
|
"fillHandle",
|
|
14
14
|
"locale",
|
|
15
15
|
"language",
|
|
16
|
-
"contextMenu"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
"contextMenu",
|
|
17
|
+
"search",
|
|
18
|
+
"query",
|
|
19
|
+
"totalCount",
|
|
20
|
+
"loading",
|
|
21
|
+
"loadError"
|
|
22
|
+
], P = x(function(e, d) {
|
|
23
|
+
const i = g(null), a = g(null), r = g(e);
|
|
24
|
+
r.current = e, b(() => {
|
|
25
|
+
const { className: u, style: h, onChange: m, onSelection: O, onSort: j, onFilter: M, onQueryChange: N, onRowClick: F, onRowDoubleClick: I, onColumnLayoutChange: Q, ..._ } = r.current, l = new E(i.current, _);
|
|
26
|
+
return l.addHook("afterChange", (o, n) => {
|
|
27
|
+
var t, c;
|
|
28
|
+
return (c = (t = r.current).onChange) == null ? void 0 : c.call(t, o, n);
|
|
29
|
+
}), l.addHook("afterSelection", (o, n, t, c) => {
|
|
30
|
+
var w, S;
|
|
31
|
+
return (S = (w = r.current).onSelection) == null ? void 0 : S.call(w, o, n, t, c);
|
|
32
|
+
}), l.addHook("afterColumnSort", (o, n) => {
|
|
33
|
+
var t, c;
|
|
34
|
+
return (c = (t = r.current).onSort) == null ? void 0 : c.call(t, o, n);
|
|
35
|
+
}), l.addHook("afterFilter", (o) => {
|
|
36
|
+
var n, t;
|
|
37
|
+
return (t = (n = r.current).onFilter) == null ? void 0 : t.call(n, o);
|
|
38
|
+
}), l.addHook("afterQueryChange", (o, n) => {
|
|
39
|
+
var t, c;
|
|
40
|
+
return (c = (t = r.current).onQueryChange) == null ? void 0 : c.call(t, o, n);
|
|
41
|
+
}), l.addHook("afterRowClick", (o) => {
|
|
42
|
+
var n, t;
|
|
43
|
+
return (t = (n = r.current).onRowClick) == null ? void 0 : t.call(n, o);
|
|
44
|
+
}), l.addHook("afterRowDoubleClick", (o) => {
|
|
45
|
+
var n, t;
|
|
46
|
+
return (t = (n = r.current).onRowDoubleClick) == null ? void 0 : t.call(n, o);
|
|
47
|
+
}), l.addHook("afterColumnLayout", (o) => {
|
|
48
|
+
var n, t;
|
|
49
|
+
return (t = (n = r.current).onColumnLayoutChange) == null ? void 0 : t.call(n, o);
|
|
50
|
+
}), a.current = l, () => {
|
|
51
|
+
l.destroy(), a.current = null;
|
|
35
52
|
};
|
|
36
|
-
}, []),
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
if (!
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
}, [
|
|
43
|
-
const
|
|
44
|
-
return
|
|
53
|
+
}, []), D(d, () => a.current, []);
|
|
54
|
+
const C = g(!1);
|
|
55
|
+
y(() => {
|
|
56
|
+
if (!C.current) return;
|
|
57
|
+
const u = a.current;
|
|
58
|
+
!u || !e.data || (e.dataMode === "server" ? u.setPageRows(e.data, e.totalCount) : L(u, e.data) || u.loadData(e.data));
|
|
59
|
+
}, [e.data]);
|
|
60
|
+
const f = k.map((u) => e[u]);
|
|
61
|
+
return y(() => {
|
|
45
62
|
var h;
|
|
46
|
-
if (!
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
}, []), /* @__PURE__ */
|
|
63
|
+
if (!C.current) return;
|
|
64
|
+
const u = {};
|
|
65
|
+
k.forEach((m) => e[m] !== void 0 && (u[m] = e[m])), (h = a.current) == null || h.updateSettings(u);
|
|
66
|
+
}, f), y(() => {
|
|
67
|
+
C.current = !0;
|
|
68
|
+
}, []), /* @__PURE__ */ H("div", { ref: i, className: e.className, style: e.style });
|
|
52
69
|
});
|
|
53
|
-
function
|
|
54
|
-
if (!
|
|
55
|
-
if (
|
|
56
|
-
const d = Array.from({ length:
|
|
57
|
-
return
|
|
70
|
+
function L(s, e) {
|
|
71
|
+
if (!T(e)) return R(s.getSourceData(), e);
|
|
72
|
+
if (s.getSourceObjects() === e) return !0;
|
|
73
|
+
const d = Array.from({ length: s.countCols() }, (i, a) => s.colToProp(a));
|
|
74
|
+
return R(s.getBoundRows(), v.create(e, d).toRows());
|
|
58
75
|
}
|
|
59
|
-
function
|
|
60
|
-
const d = Math.max(
|
|
61
|
-
for (let
|
|
62
|
-
const
|
|
63
|
-
for (let
|
|
76
|
+
function R(s, e) {
|
|
77
|
+
const d = Math.max(s.length, e.length);
|
|
78
|
+
for (let i = 0; i < d; i++) {
|
|
79
|
+
const a = s[i] ?? [], r = e[i] ?? [], C = Math.max(a.length, r.length);
|
|
80
|
+
for (let f = 0; f < C; f++) if ((a[f] ?? null) !== (r[f] ?? null)) return !1;
|
|
64
81
|
}
|
|
65
82
|
return !0;
|
|
66
83
|
}
|
|
67
84
|
export {
|
|
68
|
-
|
|
69
|
-
|
|
85
|
+
E as CenituGrid,
|
|
86
|
+
P as CenituTable
|
|
70
87
|
};
|
|
@@ -4,3 +4,5 @@ export { toXLSX, toXLSXCompressed, xlsxParts, sanitizeSheetNames, pxToColWidth,
|
|
|
4
4
|
export { numberFormatFromMeta, isDateFormat, formatDateCode, dateCodeFromPattern } from './numberFormat.js';
|
|
5
5
|
export { downloadBlob, CSV_MIME } from './download.js';
|
|
6
6
|
export { crc32, zipStore, zipDeflate, type ZipEntry } from './zip.js';
|
|
7
|
+
export { readXLSX, workbookEngine, type ImportOptions, type ImportSheet, type ImportWorkbook } from './xlsxRead.js';
|
|
8
|
+
export { ZipReader, type UnzipOptions } from './unzip.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal ZIP reader (PKWARE APPNOTE 6.3), enough for spreadsheet packages: finds entries through
|
|
3
|
+
* the central directory and inflates them with the platform DecompressionStream. No ZIP64 and no
|
|
4
|
+
* encryption. Sizes are enforced while inflating, so a crafted archive cannot exhaust memory.
|
|
5
|
+
*/
|
|
6
|
+
export interface UnzipOptions {
|
|
7
|
+
/** Upper limit for the total uncompressed size in bytes (default 1 GiB). */
|
|
8
|
+
maxSize?: number;
|
|
9
|
+
}
|
|
10
|
+
/** Lists a package and gives access to its entries by path. */
|
|
11
|
+
export declare class ZipReader {
|
|
12
|
+
private readonly bytes;
|
|
13
|
+
private readonly entries;
|
|
14
|
+
private remaining;
|
|
15
|
+
constructor(bytes: Uint8Array, opts?: UnzipOptions);
|
|
16
|
+
has(path: string): boolean;
|
|
17
|
+
get paths(): string[];
|
|
18
|
+
/** Uncompressed content of an entry; undefined when the package has no such entry. */
|
|
19
|
+
read(path: string): Promise<Uint8Array | undefined>;
|
|
20
|
+
readText(path: string): Promise<string | undefined>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FormulaEngine } from '../formula/engine.js';
|
|
2
|
+
import type { ExportCellFormat, ExportSheet } from './types.js';
|
|
3
|
+
import { type UnzipOptions } from './unzip.js';
|
|
4
|
+
export interface ImportOptions extends UnzipOptions {
|
|
5
|
+
/** 'keep' (default) imports formulas; 'values' replaces them with the results stored in the file. */
|
|
6
|
+
formulas?: 'keep' | 'values';
|
|
7
|
+
}
|
|
8
|
+
/** One worksheet of a file; the same shape the exporters take, plus what only applies to imports. */
|
|
9
|
+
export interface ImportSheet extends ExportSheet {
|
|
10
|
+
hiddenColumns: number[];
|
|
11
|
+
/** Sheet is hidden in the file. */
|
|
12
|
+
hidden: boolean;
|
|
13
|
+
format: (row: number, col: number) => ExportCellFormat | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface ImportWorkbook {
|
|
16
|
+
sheets: ImportSheet[];
|
|
17
|
+
/** Workbook-level defined names: name -> expression (`=Sheet1!$A$1`). */
|
|
18
|
+
names: {
|
|
19
|
+
name: string;
|
|
20
|
+
expression: string;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
type Binary = ArrayBuffer | Uint8Array | Blob;
|
|
24
|
+
/**
|
|
25
|
+
* Reads an .xlsx file: values, formulas, number formats, fonts, fills, alignment, column widths,
|
|
26
|
+
* row heights, frozen panes, merges and defined names. Charts, images, comments, conditional
|
|
27
|
+
* formats and data validation are not read.
|
|
28
|
+
*/
|
|
29
|
+
export declare function readXLSX(file: Binary, opts?: ImportOptions): Promise<ImportWorkbook>;
|
|
30
|
+
/**
|
|
31
|
+
* Engine holding all sheets of a workbook (still empty) and its defined names. Create one grid per
|
|
32
|
+
* sheet on it and call `loadSheet`, so cross-sheet formulas find each other in any order.
|
|
33
|
+
*/
|
|
34
|
+
export declare function workbookEngine(workbook: ImportWorkbook): FormulaEngine;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CellMeta, NumericFormat } from '../grid/cellTypes.js';
|
|
2
|
+
import type { ExportCellFormat } from './types.js';
|
|
3
|
+
export declare function parseThemeColors(xml: string | undefined): string[];
|
|
4
|
+
/** Resolved cell formats of a workbook: cell `s` attribute -> grid-independent format. */
|
|
5
|
+
export declare class XlsxStyles {
|
|
6
|
+
private readonly theme;
|
|
7
|
+
private readonly codes;
|
|
8
|
+
private readonly fonts;
|
|
9
|
+
private readonly fills;
|
|
10
|
+
private readonly xfs;
|
|
11
|
+
private readonly cache;
|
|
12
|
+
constructor(xml: string | undefined, theme: string[]);
|
|
13
|
+
private parse;
|
|
14
|
+
numberFormat(style: number): string | undefined;
|
|
15
|
+
isDate(style: number): boolean;
|
|
16
|
+
format(style: number): ExportCellFormat | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** Date pattern for a format code, when every token has a grid equivalent. */
|
|
19
|
+
export declare function patternFromDateCode(code: string): string | undefined;
|
|
20
|
+
/** Number display settings for a simple format code; complex codes keep the default display. */
|
|
21
|
+
export declare function numericFormatFromCode(code: string): NumericFormat | undefined;
|
|
22
|
+
/** Cell settings that make the grid display a format like the file does. */
|
|
23
|
+
export declare function metaFromFormat(f: ExportCellFormat): CellMeta;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming XML scanner for package parts. Namespace prefixes are dropped from element and
|
|
3
|
+
* attribute names (`x:row` -> `row`), which is what spreadsheet parts need. DOCTYPE declarations
|
|
4
|
+
* are skipped and only the predefined and numeric entities are decoded, so a crafted file cannot
|
|
5
|
+
* expand entities or reach external resources.
|
|
6
|
+
*/
|
|
7
|
+
export type XmlAttrs = Record<string, string>;
|
|
8
|
+
export interface XmlHandler {
|
|
9
|
+
open?(name: string, attrs: XmlAttrs, selfClosing: boolean): void;
|
|
10
|
+
close?(name: string): void;
|
|
11
|
+
text?(text: string): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function decodeEntities(s: string): string;
|
|
14
|
+
/** Reports elements and text in document order; throws on an unterminated construct. */
|
|
15
|
+
export declare function scanXml(xml: string, h: XmlHandler): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ConditionOp } from './filters.js';
|
|
2
|
+
import type { ServerFilterDef } from './serverMode.js';
|
|
2
3
|
import { type CellValue, type RawCell } from '../formula/values.js';
|
|
3
4
|
export type CellType = 'text' | 'numeric' | 'date' | 'checkbox' | 'dropdown';
|
|
4
5
|
export interface NumericFormat {
|
|
@@ -43,6 +44,12 @@ export interface CellRenderContext {
|
|
|
43
44
|
}
|
|
44
45
|
/** Settings that can be given per column (`columns`) or per cell (`cells`). */
|
|
45
46
|
export interface CellMeta {
|
|
47
|
+
/** Stable column id used in server queries and change events; default `data`. */
|
|
48
|
+
id?: string;
|
|
49
|
+
/** Server mode: the server can sort this column. */
|
|
50
|
+
sortable?: boolean;
|
|
51
|
+
/** Server mode: what the server can filter this column by. */
|
|
52
|
+
serverFilter?: ServerFilterDef;
|
|
46
53
|
/** Object mode: property path bound to this column, e.g. "qty" or "customer.name". */
|
|
47
54
|
data?: string;
|
|
48
55
|
type?: CellType;
|
|
@@ -51,7 +58,9 @@ export interface CellMeta {
|
|
|
51
58
|
width?: number;
|
|
52
59
|
readOnly?: boolean;
|
|
53
60
|
numericFormat?: NumericFormat;
|
|
54
|
-
/**
|
|
61
|
+
/** Spreadsheet format code written to XLSX instead of one derived from these settings (set on import). */
|
|
62
|
+
formatCode?: string;
|
|
63
|
+
/** Tokens: DD, MM, YYYY, YY, HH, mm, ss (default "DD.MM.YYYY" for tr, "YYYY-MM-DD" otherwise). */
|
|
55
64
|
dateFormat?: string;
|
|
56
65
|
/** Allowed values of a dropdown cell. */
|
|
57
66
|
source?: string[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CellStyle } from './cellTypes.js';
|
|
2
|
+
/**
|
|
3
|
+
* The "text/html" clipboard flavour. Values always travel as tab-separated text; the HTML table
|
|
4
|
+
* only adds styling, which is what spreadsheet apps read from each other.
|
|
5
|
+
*/
|
|
6
|
+
export declare function styleToCss(s: CellStyle): string;
|
|
7
|
+
export declare function tableHtml(texts: string[][], styles: (CellStyle | undefined)[][]): string;
|
|
8
|
+
export interface HtmlTable {
|
|
9
|
+
texts: string[][];
|
|
10
|
+
styles: (CellStyle | undefined)[][];
|
|
11
|
+
}
|
|
12
|
+
/** First table of a clipboard document, with spans expanded; null when there is none. */
|
|
13
|
+
export declare function parseHtmlTable(html: string, view: Window & typeof globalThis): HtmlTable | null;
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
import type { ColumnFilter, SortOrder } from './filters.js';
|
|
2
2
|
import type { Messages } from './messages.js';
|
|
3
|
+
import { type ServerFilter, type ServerFilterDef } from './serverMode.js';
|
|
3
4
|
export interface ColumnMenuOptions {
|
|
4
5
|
anchor: HTMLElement;
|
|
5
6
|
messages: Messages;
|
|
7
|
+
locale?: string;
|
|
6
8
|
sort: SortOrder | null;
|
|
9
|
+
/** Another column is sorted, so this one can be added as a further key. */
|
|
10
|
+
sortedElsewhere: boolean;
|
|
7
11
|
filter: ColumnFilter | undefined;
|
|
8
12
|
/** Distinct display texts of the column ("" = blanks), already sorted. */
|
|
9
13
|
values: string[];
|
|
10
14
|
sortable: boolean;
|
|
11
15
|
filterable: boolean;
|
|
12
|
-
onSort(order: SortOrder | null): void;
|
|
16
|
+
onSort(order: SortOrder | null, add?: boolean): void;
|
|
13
17
|
onFilter(filter: ColumnFilter | null): void;
|
|
18
|
+
/** Server mode: replaces the local filter controls. */
|
|
19
|
+
server?: {
|
|
20
|
+
def: ServerFilterDef;
|
|
21
|
+
value: ServerFilter | undefined;
|
|
22
|
+
onFilter(filter: ServerFilter | null): void;
|
|
23
|
+
};
|
|
14
24
|
onClose(): void;
|
|
15
25
|
}
|
|
16
26
|
/** Excel-like column dropdown: sort buttons, a condition filter and a value checklist. */
|
|
@@ -9,6 +9,7 @@ export interface ColumnFilter {
|
|
|
9
9
|
values?: string[];
|
|
10
10
|
}
|
|
11
11
|
export type SortOrder = 'asc' | 'desc';
|
|
12
|
-
|
|
12
|
+
/** Text comparisons follow `locale`, so Turkish I/ı and İ/i pair up correctly. */
|
|
13
|
+
export declare function matchesFilter(value: CellValue, text: string, filter: ColumnFilter, locale?: string): boolean;
|
|
13
14
|
/** Spreadsheet sort order: numbers, text, booleans, errors; blanks always last. */
|
|
14
|
-
export declare function compareForSort(a: CellValue, b: CellValue, order: SortOrder): number;
|
|
15
|
+
export declare function compareForSort(a: CellValue, b: CellValue, order: SortOrder, locale?: string): number;
|