@vuu-ui/vuu-utils 0.5.4 → 0.5.6
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/cjs/index.js +1 -628
- package/cjs/index.js.map +7 -0
- package/esm/index.js +2 -0
- package/esm/index.js.map +7 -0
- package/package.json +6 -10
- package/types/DataWindow.d.ts +39 -0
- package/types/array-utils.d.ts +3 -0
- package/types/column-utils.d.ts +27 -0
- package/types/data-utils.d.ts +9 -0
- package/types/date-utils.d.ts +1 -0
- package/types/event-emitter.d.ts +19 -0
- package/types/getUniqueId.d.ts +1 -0
- package/{src/index.ts → types/index.d.ts} +0 -0
- package/types/input-utils.d.ts +2 -0
- package/types/invariant.d.ts +1 -0
- package/types/nanoid/index.d.ts +1 -0
- package/types/range-utils.d.ts +21 -0
- package/types/round-decimal.d.ts +1 -0
- package/types/row-utils.d.ts +10 -0
- package/types/text-utils.d.ts +1 -0
- package/src/DataWindow.ts +0 -111
- package/src/array-utils.ts +0 -22
- package/src/column-utils.ts +0 -133
- package/src/data-utils.ts +0 -60
- package/src/date-utils.ts +0 -4
- package/src/event-emitter.ts +0 -139
- package/src/getUniqueId.ts +0 -1
- package/src/input-utils.ts +0 -50
- package/src/invariant.ts +0 -10
- package/src/nanoid/index.ts +0 -30
- package/src/range-utils.ts +0 -72
- package/src/round-decimal.ts +0 -126
- package/src/row-utils.ts +0 -44
- package/src/text-utils.ts +0 -9
package/src/column-utils.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ColumnDescriptor,
|
|
3
|
-
KeyedColumnDescriptor,
|
|
4
|
-
} from "@vuu-ui/vuu-datagrid/src/grid-model/gridModelTypes";
|
|
5
|
-
import { Row } from "./row-utils";
|
|
6
|
-
|
|
7
|
-
export interface ColumnMap {
|
|
8
|
-
[columnName: string]: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const SORT_ASC = "asc";
|
|
12
|
-
|
|
13
|
-
export type SortCriteriaItem = string | [string, "asc"]; // TODO where is 'desc'?
|
|
14
|
-
|
|
15
|
-
export function mapSortCriteria(
|
|
16
|
-
sortCriteria: SortCriteriaItem[],
|
|
17
|
-
columnMap: ColumnMap,
|
|
18
|
-
metadataOffset = 0
|
|
19
|
-
): [number, "asc"][] {
|
|
20
|
-
return sortCriteria.map((s) => {
|
|
21
|
-
if (typeof s === "string") {
|
|
22
|
-
return [columnMap[s] + metadataOffset, "asc"];
|
|
23
|
-
} else if (Array.isArray(s)) {
|
|
24
|
-
const [columnName, sortDir] = s;
|
|
25
|
-
return [columnMap[columnName] + metadataOffset, sortDir || SORT_ASC];
|
|
26
|
-
} else {
|
|
27
|
-
throw Error("columnUtils.mapSortCriteria invalid input");
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function isKeyedColumn(
|
|
33
|
-
column: ColumnDescriptor
|
|
34
|
-
): column is KeyedColumnDescriptor {
|
|
35
|
-
return typeof (column as KeyedColumnDescriptor).key === "number";
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const toColumnDescriptor = (name: string): ColumnDescriptor => ({
|
|
39
|
-
name,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
export const toKeyedColumn = (
|
|
43
|
-
column: string | ColumnDescriptor,
|
|
44
|
-
key: number
|
|
45
|
-
): KeyedColumnDescriptor => {
|
|
46
|
-
if (typeof column === "string") {
|
|
47
|
-
return { key, name: column };
|
|
48
|
-
}
|
|
49
|
-
if (isKeyedColumn(column)) {
|
|
50
|
-
return column;
|
|
51
|
-
}
|
|
52
|
-
return { ...column, key };
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const EMPTY_COLUMN_MAP = {} as const;
|
|
56
|
-
|
|
57
|
-
export function buildColumnMap(columns?: (Column | string)[]): ColumnMap {
|
|
58
|
-
const start = metadataKeys.count;
|
|
59
|
-
if (columns) {
|
|
60
|
-
return columns.reduce((map, column, i) => {
|
|
61
|
-
if (typeof column === "string") {
|
|
62
|
-
map[column] = start + i;
|
|
63
|
-
} else if (typeof column.key === "number") {
|
|
64
|
-
map[column.name] = column.key;
|
|
65
|
-
} else {
|
|
66
|
-
map[column.name] = start + i;
|
|
67
|
-
}
|
|
68
|
-
return map;
|
|
69
|
-
}, {} as ColumnMap);
|
|
70
|
-
} else {
|
|
71
|
-
return EMPTY_COLUMN_MAP;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function projectUpdates(updates: number[]): number[] {
|
|
76
|
-
const results: number[] = [];
|
|
77
|
-
const metadataOffset = metadataKeys.count - 2;
|
|
78
|
-
for (let i = 0; i < updates.length; i += 3) {
|
|
79
|
-
results[i] = updates[i] + metadataOffset;
|
|
80
|
-
results[i + 1] = updates[i + 1];
|
|
81
|
-
results[i + 2] = updates[i + 2];
|
|
82
|
-
}
|
|
83
|
-
return results;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function projectColumns(
|
|
87
|
-
tableRowColumnMap: ColumnMap,
|
|
88
|
-
columns: ColumnDescriptor[]
|
|
89
|
-
) {
|
|
90
|
-
const columnCount = columns.length;
|
|
91
|
-
const { IDX, RENDER_IDX, DEPTH, COUNT, KEY, SELECTED, count } = metadataKeys;
|
|
92
|
-
return (startIdx: number, offset: number, selectedRows: Row[] = []) =>
|
|
93
|
-
(row: Row, i: number) => {
|
|
94
|
-
// selectedRows are indices of rows within underlying dataset (not sorted or filtered)
|
|
95
|
-
// row is the original row from this set, with original index in IDX pos, which might
|
|
96
|
-
// be overwritten with a different value below if rows are sorted/filtered
|
|
97
|
-
const baseRowIdx: any = row[IDX]; // TODO
|
|
98
|
-
const out = [];
|
|
99
|
-
for (let i = 0; i < columnCount; i++) {
|
|
100
|
-
const colIdx = tableRowColumnMap[columns[i].name];
|
|
101
|
-
out[count + i] = row[colIdx];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
out[IDX] = startIdx + i + offset;
|
|
105
|
-
out[RENDER_IDX] = 0;
|
|
106
|
-
out[DEPTH] = 0;
|
|
107
|
-
out[COUNT] = 0;
|
|
108
|
-
out[KEY] = row[tableRowColumnMap.KEY];
|
|
109
|
-
out[SELECTED] = selectedRows.includes(baseRowIdx) ? 1 : 0;
|
|
110
|
-
return out;
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export type Meta = {
|
|
115
|
-
[key: string]: any;
|
|
116
|
-
} & any[];
|
|
117
|
-
|
|
118
|
-
export const metadataKeys = {
|
|
119
|
-
IDX: 0,
|
|
120
|
-
RENDER_IDX: 1,
|
|
121
|
-
IS_LEAF: 2,
|
|
122
|
-
IS_EXPANDED: 3,
|
|
123
|
-
DEPTH: 4,
|
|
124
|
-
COUNT: 5,
|
|
125
|
-
KEY: 6,
|
|
126
|
-
SELECTED: 7,
|
|
127
|
-
count: 8,
|
|
128
|
-
// TODO following only used in datamodel
|
|
129
|
-
PARENT_IDX: "parent_idx",
|
|
130
|
-
IDX_POINTER: "idx_pointer",
|
|
131
|
-
FILTER_COUNT: "filter_count",
|
|
132
|
-
NEXT_FILTER_IDX: "next_filter_idx",
|
|
133
|
-
} as const;
|
package/src/data-utils.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
export type valueChangeDirection = "up1" | "up2" | "down1" | "down2" | "";
|
|
2
|
-
|
|
3
|
-
export const UP1 = "up1";
|
|
4
|
-
export const UP2 = "up2";
|
|
5
|
-
export const DOWN1 = "down1";
|
|
6
|
-
export const DOWN2 = "down2";
|
|
7
|
-
|
|
8
|
-
export const isValidNumber = (n: unknown): n is number =>
|
|
9
|
-
typeof n === "number" && isFinite(n);
|
|
10
|
-
|
|
11
|
-
export function getMovingValueDirection(
|
|
12
|
-
newValue: number,
|
|
13
|
-
direction?: valueChangeDirection,
|
|
14
|
-
prevValue?: number,
|
|
15
|
-
/** the number of decimal places to take into account when highlighting a change */
|
|
16
|
-
decimalPlaces?: number
|
|
17
|
-
): valueChangeDirection {
|
|
18
|
-
if (
|
|
19
|
-
!isFinite(newValue) ||
|
|
20
|
-
prevValue === undefined ||
|
|
21
|
-
direction === undefined
|
|
22
|
-
) {
|
|
23
|
-
return "";
|
|
24
|
-
} else {
|
|
25
|
-
let diff = newValue - prevValue;
|
|
26
|
-
if (diff) {
|
|
27
|
-
// make sure there is still a diff when reduced to number of decimals to be displayed
|
|
28
|
-
if (typeof decimalPlaces === "number") {
|
|
29
|
-
diff =
|
|
30
|
-
+newValue.toFixed(decimalPlaces) - +prevValue.toFixed(decimalPlaces);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (diff) {
|
|
35
|
-
if (direction === "") {
|
|
36
|
-
if (diff < 0) {
|
|
37
|
-
return DOWN1;
|
|
38
|
-
} else {
|
|
39
|
-
return UP1;
|
|
40
|
-
}
|
|
41
|
-
} else if (diff > 0) {
|
|
42
|
-
if (direction === DOWN1 || direction === DOWN2 || direction === UP2) {
|
|
43
|
-
return UP1;
|
|
44
|
-
} else {
|
|
45
|
-
return UP2;
|
|
46
|
-
}
|
|
47
|
-
} else if (
|
|
48
|
-
direction === UP1 ||
|
|
49
|
-
direction === UP2 ||
|
|
50
|
-
direction === DOWN2
|
|
51
|
-
) {
|
|
52
|
-
return DOWN1;
|
|
53
|
-
} else {
|
|
54
|
-
return DOWN2;
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
return "";
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
package/src/date-utils.ts
DELETED
package/src/event-emitter.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
export interface Event {}
|
|
2
|
-
|
|
3
|
-
export type EventListener = (evtName: string, ...args: any[]) => void;
|
|
4
|
-
|
|
5
|
-
export type EventListenerMap = {
|
|
6
|
-
[eventName: string]: EventListener[] | EventListener;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
function isArrayOfListeners(
|
|
10
|
-
listeners: EventListener | EventListener[]
|
|
11
|
-
): listeners is EventListener[] {
|
|
12
|
-
return Array.isArray(listeners);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function isOnlyListener(
|
|
16
|
-
listeners: EventListener | EventListener[]
|
|
17
|
-
): listeners is EventListener {
|
|
18
|
-
return !Array.isArray(listeners);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface IEventEmitter {
|
|
22
|
-
emit: (type: string, ...args: unknown[]) => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class EventEmitter implements IEventEmitter {
|
|
26
|
-
private _events?: EventListenerMap;
|
|
27
|
-
|
|
28
|
-
constructor() {
|
|
29
|
-
this._events = {};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
addListener(type: string, listener: EventListener) {
|
|
33
|
-
if (!this._events) {
|
|
34
|
-
this._events = {};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const listeners = this._events[type];
|
|
38
|
-
|
|
39
|
-
if (!listeners) {
|
|
40
|
-
this._events[type] = listener;
|
|
41
|
-
} else if (isArrayOfListeners(listeners)) {
|
|
42
|
-
listeners.push(listener);
|
|
43
|
-
} else if (isOnlyListener(listeners)) {
|
|
44
|
-
this._events[type] = [listeners, listener];
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
removeListener(type: string, listener: EventListener) {
|
|
49
|
-
if (!this._events || !this._events[type]) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const listenerOrListeners = this._events[type];
|
|
54
|
-
let position = -1;
|
|
55
|
-
|
|
56
|
-
if (listenerOrListeners === listener) {
|
|
57
|
-
delete this._events[type];
|
|
58
|
-
} else if (Array.isArray(listenerOrListeners)) {
|
|
59
|
-
for (let i = length; i-- > 0; ) {
|
|
60
|
-
if (listenerOrListeners[i] === listener) {
|
|
61
|
-
position = i;
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (position < 0) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (listenerOrListeners.length === 1) {
|
|
71
|
-
listenerOrListeners.length = 0;
|
|
72
|
-
delete this._events[type];
|
|
73
|
-
} else {
|
|
74
|
-
listenerOrListeners.splice(position, 1);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
removeAllListeners(type: string) {
|
|
80
|
-
if (!this._events) {
|
|
81
|
-
return;
|
|
82
|
-
} else if (type === undefined) {
|
|
83
|
-
delete this._events;
|
|
84
|
-
} else {
|
|
85
|
-
delete this._events[type];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
emit(type: string, ...args: unknown[]) {
|
|
90
|
-
if (this._events) {
|
|
91
|
-
const handler = this._events[type];
|
|
92
|
-
if (handler) {
|
|
93
|
-
invokeHandler(handler, type, args);
|
|
94
|
-
}
|
|
95
|
-
const wildcardHandler = this._events["*"];
|
|
96
|
-
if (wildcardHandler) {
|
|
97
|
-
invokeHandler(wildcardHandler, type, args);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
once(type: string, listener: EventListener) {
|
|
103
|
-
const handler = (evtName: string, message: unknown) => {
|
|
104
|
-
this.removeListener(evtName, handler);
|
|
105
|
-
listener(evtName, message);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
this.on(type, handler);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
on(type: string, listener: EventListener) {
|
|
112
|
-
return this.addListener(type, listener);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function invokeHandler(
|
|
117
|
-
handler: EventListener | EventListener[],
|
|
118
|
-
type: string,
|
|
119
|
-
args: unknown[]
|
|
120
|
-
) {
|
|
121
|
-
if (isArrayOfListeners(handler)) {
|
|
122
|
-
handler.slice().forEach((listener) => invokeHandler(listener, type, args));
|
|
123
|
-
} else {
|
|
124
|
-
switch (args.length) {
|
|
125
|
-
case 0:
|
|
126
|
-
handler(type);
|
|
127
|
-
break;
|
|
128
|
-
case 1:
|
|
129
|
-
handler(type, args[0]);
|
|
130
|
-
break;
|
|
131
|
-
case 2:
|
|
132
|
-
handler(type, args[0], args[1]);
|
|
133
|
-
break;
|
|
134
|
-
// slower
|
|
135
|
-
default:
|
|
136
|
-
handler.call(null, type, ...args);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
package/src/getUniqueId.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const getUniqueId = () => `hw-${Math.round(Math.random() * 1e5)}`;
|
package/src/input-utils.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const actionKeys = {
|
|
2
|
-
Enter: 'Enter',
|
|
3
|
-
Delete: 'Delete'
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
const navigationKeys = {
|
|
7
|
-
Home: 'Home',
|
|
8
|
-
End: 'End',
|
|
9
|
-
ArrowRight: 'ArrowRight',
|
|
10
|
-
ArrowLeft: 'ArrowLeft',
|
|
11
|
-
ArrowDown: 'ArrowDown',
|
|
12
|
-
ArrowUp: 'ArrowUp',
|
|
13
|
-
Tab: 'Tab'
|
|
14
|
-
};
|
|
15
|
-
const functionKeys = {
|
|
16
|
-
F1: 'F1',
|
|
17
|
-
F2: 'F2',
|
|
18
|
-
F3: 'F3',
|
|
19
|
-
F4: 'F4',
|
|
20
|
-
F5: 'F5',
|
|
21
|
-
F6: 'F6',
|
|
22
|
-
F7: 'F7',
|
|
23
|
-
F8: 'F8',
|
|
24
|
-
F9: 'F9',
|
|
25
|
-
F10: 'F10',
|
|
26
|
-
F11: 'F11',
|
|
27
|
-
F12: 'F12'
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const specialKeys = {
|
|
31
|
-
...actionKeys,
|
|
32
|
-
...navigationKeys,
|
|
33
|
-
...functionKeys
|
|
34
|
-
};
|
|
35
|
-
type specialKey = keyof typeof specialKeys;
|
|
36
|
-
|
|
37
|
-
const isSpecialKey = (key: string): key is specialKey => key in specialKeys;
|
|
38
|
-
|
|
39
|
-
export const isCharacterKey = (evt: KeyboardEvent) => {
|
|
40
|
-
if (isSpecialKey(evt.key)) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
if (typeof evt.which === 'number' && evt.which > 0) {
|
|
44
|
-
return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which !== 8;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export const isQuoteKey = (evt: KeyboardEvent) => {
|
|
49
|
-
return evt.key === '"' || evt.key === "'";
|
|
50
|
-
};
|
package/src/invariant.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export function invariant(condition: boolean, message: string) {
|
|
2
|
-
if (!condition) {
|
|
3
|
-
const error = new Error(message);
|
|
4
|
-
error.name = 'Invariant Violation';
|
|
5
|
-
// TODO what is framesToPop?
|
|
6
|
-
// @ts-ignore
|
|
7
|
-
error.framesToPop = 1; // we don't care about invariant's own frame
|
|
8
|
-
throw error;
|
|
9
|
-
}
|
|
10
|
-
}
|
package/src/nanoid/index.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// This is the index.browser.js file from nanoid
|
|
2
|
-
// couldn't get original code to work as npm import without crypro warnings -
|
|
3
|
-
// seemed to be picking up node version, not browser version
|
|
4
|
-
|
|
5
|
-
export const uuid = (size: number = 21): string => {
|
|
6
|
-
let id: string = '';
|
|
7
|
-
let bytes = crypto.getRandomValues(new Uint8Array(size));
|
|
8
|
-
|
|
9
|
-
// A compact alternative for `for (var i = 0; i < step; i++)`.
|
|
10
|
-
while (size--) {
|
|
11
|
-
// It is incorrect to use bytes exceeding the alphabet size.
|
|
12
|
-
// The following mask reduces the random byte in the 0-255 value
|
|
13
|
-
// range to the 0-63 value range. Therefore, adding hacks, such
|
|
14
|
-
// as empty string fallback or magic numbers, is unneccessary because
|
|
15
|
-
// the bitmask trims bytes down to the alphabet size.
|
|
16
|
-
let byte = bytes[size] & 63;
|
|
17
|
-
if (byte < 36) {
|
|
18
|
-
// `0-9a-z`
|
|
19
|
-
id += byte.toString(36);
|
|
20
|
-
} else if (byte < 62) {
|
|
21
|
-
// `A-Z`
|
|
22
|
-
id += (byte - 26).toString(36).toUpperCase();
|
|
23
|
-
} else if (byte < 63) {
|
|
24
|
-
id += '_';
|
|
25
|
-
} else {
|
|
26
|
-
id += '-';
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return id;
|
|
30
|
-
};
|
package/src/range-utils.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
export interface VuuRange {
|
|
2
|
-
from: number;
|
|
3
|
-
to: number;
|
|
4
|
-
bufferSize?: number;
|
|
5
|
-
reset?: boolean;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
interface FromToRange {
|
|
9
|
-
from: number;
|
|
10
|
-
to: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function getFullRange(
|
|
14
|
-
{ from, to }: VuuRange,
|
|
15
|
-
bufferSize: number = 0,
|
|
16
|
-
rowCount: number = Number.MAX_SAFE_INTEGER
|
|
17
|
-
): FromToRange {
|
|
18
|
-
if (bufferSize === 0) {
|
|
19
|
-
return { from, to: Math.min(to, rowCount) };
|
|
20
|
-
} else if (from === 0) {
|
|
21
|
-
return { from, to: Math.min(to + bufferSize, rowCount) };
|
|
22
|
-
} else {
|
|
23
|
-
const rangeSize = to - from;
|
|
24
|
-
const buff = Math.round(bufferSize / 2);
|
|
25
|
-
const shortfallBefore = from - buff < 0;
|
|
26
|
-
const shortFallAfter = rowCount - (to + buff) < 0;
|
|
27
|
-
|
|
28
|
-
if (shortfallBefore && shortFallAfter) {
|
|
29
|
-
return { from: 0, to: rowCount };
|
|
30
|
-
} else if (shortfallBefore) {
|
|
31
|
-
return { from: 0, to: rangeSize + bufferSize };
|
|
32
|
-
} else if (shortFallAfter) {
|
|
33
|
-
return { from: Math.max(0, rowCount - (rangeSize + bufferSize)), to: rowCount };
|
|
34
|
-
} else {
|
|
35
|
-
return { from: from - buff, to: to + buff };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function resetRange({ from, to, bufferSize = 0 }: VuuRange): VuuRange {
|
|
41
|
-
return {
|
|
42
|
-
from: 0,
|
|
43
|
-
to: to - from,
|
|
44
|
-
bufferSize,
|
|
45
|
-
reset: true
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export class WindowRange {
|
|
50
|
-
public from: number;
|
|
51
|
-
public to: number;
|
|
52
|
-
|
|
53
|
-
constructor(from: number, to: number) {
|
|
54
|
-
this.from = from;
|
|
55
|
-
this.to = to;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
public isWithin(index: number) {
|
|
59
|
-
return index >= this.from && index < this.to;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
//find the overlap of this range and a new one
|
|
63
|
-
public overlap(from: number, to: number): [number, number] {
|
|
64
|
-
return from >= this.to || to < this.from
|
|
65
|
-
? [0, 0]
|
|
66
|
-
: [Math.max(from, this.from), Math.min(to, this.to)];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public copy(): WindowRange {
|
|
70
|
-
return new WindowRange(this.from, this.to);
|
|
71
|
-
}
|
|
72
|
-
}
|
package/src/round-decimal.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
const PUNCTUATION_STR = String.fromCharCode(8200);
|
|
2
|
-
const DIGIT_STR = String.fromCharCode(8199);
|
|
3
|
-
const DECIMALS_AUTO = -1;
|
|
4
|
-
|
|
5
|
-
type PadMap = {
|
|
6
|
-
DIGIT: string;
|
|
7
|
-
TWO_DIGITS: string;
|
|
8
|
-
THREE_DIGITS: string;
|
|
9
|
-
FULL_PADDING: [null, string, string, string, string];
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const Space: PadMap = {
|
|
13
|
-
DIGIT: DIGIT_STR,
|
|
14
|
-
TWO_DIGITS: DIGIT_STR + DIGIT_STR,
|
|
15
|
-
THREE_DIGITS: DIGIT_STR + DIGIT_STR + DIGIT_STR,
|
|
16
|
-
FULL_PADDING: [
|
|
17
|
-
null,
|
|
18
|
-
PUNCTUATION_STR + DIGIT_STR,
|
|
19
|
-
PUNCTUATION_STR + DIGIT_STR + DIGIT_STR,
|
|
20
|
-
PUNCTUATION_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR,
|
|
21
|
-
PUNCTUATION_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR + DIGIT_STR,
|
|
22
|
-
],
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const Zero: PadMap = {
|
|
26
|
-
DIGIT: "0",
|
|
27
|
-
TWO_DIGITS: "00",
|
|
28
|
-
THREE_DIGITS: "000",
|
|
29
|
-
FULL_PADDING: [null, "0", "00", "000", "0000"],
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
function padLeft(value: string, maxLength = 6) {
|
|
33
|
-
return (LEADING_FILL + value).slice(-maxLength);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const LEADING_FILL =
|
|
37
|
-
DIGIT_STR +
|
|
38
|
-
DIGIT_STR +
|
|
39
|
-
DIGIT_STR +
|
|
40
|
-
DIGIT_STR +
|
|
41
|
-
DIGIT_STR +
|
|
42
|
-
DIGIT_STR +
|
|
43
|
-
DIGIT_STR +
|
|
44
|
-
DIGIT_STR +
|
|
45
|
-
DIGIT_STR;
|
|
46
|
-
|
|
47
|
-
const Align = {
|
|
48
|
-
Right: "right",
|
|
49
|
-
Center: "center",
|
|
50
|
-
Left: "left",
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
function pad(n: string, dp: number, Pad: PadMap): string {
|
|
54
|
-
let len = n.length;
|
|
55
|
-
const diff = dp - len;
|
|
56
|
-
|
|
57
|
-
if (diff > 0) {
|
|
58
|
-
if (diff === 1) {
|
|
59
|
-
n = n + Pad.DIGIT;
|
|
60
|
-
} else if (diff === 2) {
|
|
61
|
-
n = n + Pad.TWO_DIGITS;
|
|
62
|
-
} else if (diff === 3) {
|
|
63
|
-
n = n + Pad.THREE_DIGITS;
|
|
64
|
-
}
|
|
65
|
-
} else {
|
|
66
|
-
if (diff < 0) {
|
|
67
|
-
n = n.slice(0, dp);
|
|
68
|
-
len = dp;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (Pad === Space && n.charAt(len - 1) === "0") {
|
|
72
|
-
n = n.replace(/0+$/, "");
|
|
73
|
-
return pad(n, dp, Pad);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return n;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function roundDecimal(
|
|
80
|
-
value?: number,
|
|
81
|
-
align = Align.Right,
|
|
82
|
-
decimals = 4,
|
|
83
|
-
zeroPad?: boolean,
|
|
84
|
-
alignOnDecimals?: boolean
|
|
85
|
-
) {
|
|
86
|
-
if (value === undefined || typeof value !== "number" || isNaN(value)) {
|
|
87
|
-
return "";
|
|
88
|
-
}
|
|
89
|
-
let integral, fraction, Pad;
|
|
90
|
-
|
|
91
|
-
const [part1, part2 = ""] = value.toString().split(".");
|
|
92
|
-
const actualDecimals = part2.length;
|
|
93
|
-
|
|
94
|
-
integral = parseFloat(part1).toLocaleString();
|
|
95
|
-
|
|
96
|
-
if (align === Align.Left && alignOnDecimals) {
|
|
97
|
-
integral = padLeft(integral);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (decimals === DECIMALS_AUTO || actualDecimals === decimals) {
|
|
101
|
-
fraction = part2;
|
|
102
|
-
} else if (actualDecimals > decimals) {
|
|
103
|
-
fraction = parseFloat("0." + part2)
|
|
104
|
-
.toFixed(decimals)
|
|
105
|
-
.slice(2);
|
|
106
|
-
} else {
|
|
107
|
-
/* eslint-disable no-cond-assign */
|
|
108
|
-
if (
|
|
109
|
-
(Pad = zeroPad
|
|
110
|
-
? Zero
|
|
111
|
-
: alignOnDecimals && align !== Align.Left
|
|
112
|
-
? Space
|
|
113
|
-
: null)
|
|
114
|
-
) {
|
|
115
|
-
if (actualDecimals === 0) {
|
|
116
|
-
fraction = Pad.FULL_PADDING[decimals];
|
|
117
|
-
} else {
|
|
118
|
-
fraction = pad(part2, decimals, Pad);
|
|
119
|
-
}
|
|
120
|
-
} else {
|
|
121
|
-
fraction = part2;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return integral + (fraction ? "." + fraction : "");
|
|
126
|
-
}
|
package/src/row-utils.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
export type RowIndex = {
|
|
2
|
-
[field: string]: number;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
// TODO
|
|
6
|
-
export type Row = {
|
|
7
|
-
[strKey: string]: any;
|
|
8
|
-
} & any[];
|
|
9
|
-
|
|
10
|
-
export function addRowsToIndex(rows: Row[], index: RowIndex, indexField: string) {
|
|
11
|
-
for (let idx = 0, len = rows.length; idx < len; idx++) {
|
|
12
|
-
index[rows[idx][indexField]] = idx;
|
|
13
|
-
}
|
|
14
|
-
return index;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function indexRows(rows: Row[], indexField: string) {
|
|
18
|
-
return addRowsToIndex(rows, {}, indexField);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function isEmptyRow(row: Row) {
|
|
22
|
-
return row[0] === undefined;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// TODO rename
|
|
26
|
-
export function update(rows: Row[], updates: any) { // TODO
|
|
27
|
-
const results = rows.slice();
|
|
28
|
-
const [[offsetIdx]] = rows;
|
|
29
|
-
for (let i = 0; i < updates.length; i++) {
|
|
30
|
-
const idx = updates[i][0] - offsetIdx;
|
|
31
|
-
// slow, refactor for performance
|
|
32
|
-
if (rows[idx]) {
|
|
33
|
-
const row = rows[idx].slice();
|
|
34
|
-
for (let j = 1; j < updates[i].length; j += 3) {
|
|
35
|
-
row[updates[i][j]] = updates[i][j + 2];
|
|
36
|
-
}
|
|
37
|
-
results[idx] = row;
|
|
38
|
-
} else {
|
|
39
|
-
console.log(`row not found in rows`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return results;
|
|
44
|
-
}
|