tinybase 4.1.0-beta.3 → 4.1.0-beta.4
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/lib/checkpoints.js +1 -1
- package/lib/checkpoints.js.gz +0 -0
- package/lib/cjs/checkpoints.cjs +1 -1
- package/lib/cjs/checkpoints.cjs.gz +0 -0
- package/lib/cjs/common.cjs +1 -1
- package/lib/cjs/common.cjs.gz +0 -0
- package/lib/cjs/indexes.cjs +1 -1
- package/lib/cjs/indexes.cjs.gz +0 -0
- package/lib/cjs/metrics.cjs +1 -1
- package/lib/cjs/metrics.cjs.gz +0 -0
- package/lib/cjs/queries.cjs +1 -1
- package/lib/cjs/queries.cjs.gz +0 -0
- package/lib/cjs/relationships.cjs +1 -1
- package/lib/cjs/relationships.cjs.gz +0 -0
- package/lib/cjs/store.cjs +1 -1
- package/lib/cjs/store.cjs.gz +0 -0
- package/lib/cjs/tinybase.cjs +1 -1
- package/lib/cjs/tinybase.cjs.gz +0 -0
- package/lib/cjs/ui-react-dom-debug.cjs +1 -0
- package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
- package/lib/cjs/ui-react-dom.cjs +1 -1
- package/lib/cjs/ui-react-dom.cjs.gz +0 -0
- package/lib/cjs/ui-react.cjs +1 -1
- package/lib/cjs/ui-react.cjs.gz +0 -0
- package/lib/cjs-es6/checkpoints.cjs +1 -1
- package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
- package/lib/cjs-es6/common.cjs +1 -1
- package/lib/cjs-es6/common.cjs.gz +0 -0
- package/lib/cjs-es6/indexes.cjs +1 -1
- package/lib/cjs-es6/indexes.cjs.gz +0 -0
- package/lib/cjs-es6/metrics.cjs +1 -1
- package/lib/cjs-es6/metrics.cjs.gz +0 -0
- package/lib/cjs-es6/queries.cjs +1 -1
- package/lib/cjs-es6/queries.cjs.gz +0 -0
- package/lib/cjs-es6/relationships.cjs +1 -1
- package/lib/cjs-es6/relationships.cjs.gz +0 -0
- package/lib/cjs-es6/store.cjs +1 -1
- package/lib/cjs-es6/store.cjs.gz +0 -0
- package/lib/cjs-es6/tinybase.cjs +1 -1
- package/lib/cjs-es6/tinybase.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -0
- package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react-dom.cjs +1 -1
- package/lib/cjs-es6/ui-react-dom.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react.cjs +1 -1
- package/lib/cjs-es6/ui-react.cjs.gz +0 -0
- package/lib/common.js +1 -1
- package/lib/common.js.gz +0 -0
- package/lib/debug/checkpoints.js +1 -1
- package/lib/debug/common.js +2 -1
- package/lib/debug/indexes.js +3 -2
- package/lib/debug/metrics.js +1 -1
- package/lib/debug/queries.js +3 -1
- package/lib/debug/relationships.js +1 -1
- package/lib/debug/store.js +32 -6
- package/lib/debug/tinybase.js +33 -6
- package/lib/debug/ui-react-dom.js +2143 -79
- package/lib/debug/ui-react.js +85 -25
- package/lib/es6/checkpoints.js +1 -1
- package/lib/es6/checkpoints.js.gz +0 -0
- package/lib/es6/common.js +1 -1
- package/lib/es6/common.js.gz +0 -0
- package/lib/es6/indexes.js +1 -1
- package/lib/es6/indexes.js.gz +0 -0
- package/lib/es6/metrics.js +1 -1
- package/lib/es6/metrics.js.gz +0 -0
- package/lib/es6/queries.js +1 -1
- package/lib/es6/queries.js.gz +0 -0
- package/lib/es6/relationships.js +1 -1
- package/lib/es6/relationships.js.gz +0 -0
- package/lib/es6/store.js +1 -1
- package/lib/es6/store.js.gz +0 -0
- package/lib/es6/tinybase.js +1 -1
- package/lib/es6/tinybase.js.gz +0 -0
- package/lib/es6/ui-react-dom-debug.js +1 -0
- package/lib/es6/ui-react-dom-debug.js.gz +0 -0
- package/lib/es6/ui-react-dom.js +1 -1
- package/lib/es6/ui-react-dom.js.gz +0 -0
- package/lib/es6/ui-react.js +1 -1
- package/lib/es6/ui-react.js.gz +0 -0
- package/lib/indexes.js +1 -1
- package/lib/indexes.js.gz +0 -0
- package/lib/metrics.js +1 -1
- package/lib/metrics.js.gz +0 -0
- package/lib/queries.js +1 -1
- package/lib/queries.js.gz +0 -0
- package/lib/relationships.js +1 -1
- package/lib/relationships.js.gz +0 -0
- package/lib/store.js +1 -1
- package/lib/store.js.gz +0 -0
- package/lib/tinybase.js +1 -1
- package/lib/tinybase.js.gz +0 -0
- package/lib/types/queries.d.ts +204 -19
- package/lib/types/store.d.ts +155 -0
- package/lib/types/ui-react-dom.d.ts +278 -18
- package/lib/types/ui-react.d.ts +532 -1
- package/lib/types/with-schemas/queries.d.ts +229 -21
- package/lib/types/with-schemas/store.d.ts +188 -0
- package/lib/types/with-schemas/ui-react-dom.d.ts +278 -18
- package/lib/types/with-schemas/ui-react.d.ts +576 -2
- package/lib/ui-react-dom.js +1 -1
- package/lib/ui-react-dom.js.gz +0 -0
- package/lib/ui-react.js +1 -1
- package/lib/ui-react.js.gz +0 -0
- package/lib/umd/checkpoints.js +1 -1
- package/lib/umd/checkpoints.js.gz +0 -0
- package/lib/umd/common.js +1 -1
- package/lib/umd/common.js.gz +0 -0
- package/lib/umd/indexes.js +1 -1
- package/lib/umd/indexes.js.gz +0 -0
- package/lib/umd/metrics.js +1 -1
- package/lib/umd/metrics.js.gz +0 -0
- package/lib/umd/queries.js +1 -1
- package/lib/umd/queries.js.gz +0 -0
- package/lib/umd/relationships.js +1 -1
- package/lib/umd/relationships.js.gz +0 -0
- package/lib/umd/store.js +1 -1
- package/lib/umd/store.js.gz +0 -0
- package/lib/umd/tinybase.js +1 -1
- package/lib/umd/tinybase.js.gz +0 -0
- package/lib/umd/ui-react-dom-debug.js +1 -0
- package/lib/umd/ui-react-dom-debug.js.gz +0 -0
- package/lib/umd/ui-react-dom.js +1 -1
- package/lib/umd/ui-react-dom.js.gz +0 -0
- package/lib/umd/ui-react.js +1 -1
- package/lib/umd/ui-react.js.gz +0 -0
- package/lib/umd-es6/checkpoints.js +1 -1
- package/lib/umd-es6/checkpoints.js.gz +0 -0
- package/lib/umd-es6/common.js +1 -1
- package/lib/umd-es6/common.js.gz +0 -0
- package/lib/umd-es6/indexes.js +1 -1
- package/lib/umd-es6/indexes.js.gz +0 -0
- package/lib/umd-es6/metrics.js +1 -1
- package/lib/umd-es6/metrics.js.gz +0 -0
- package/lib/umd-es6/queries.js +1 -1
- package/lib/umd-es6/queries.js.gz +0 -0
- package/lib/umd-es6/relationships.js +1 -1
- package/lib/umd-es6/relationships.js.gz +0 -0
- package/lib/umd-es6/store.js +1 -1
- package/lib/umd-es6/store.js.gz +0 -0
- package/lib/umd-es6/tinybase.js +1 -1
- package/lib/umd-es6/tinybase.js.gz +0 -0
- package/lib/umd-es6/ui-react-dom-debug.js +1 -0
- package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
- package/lib/umd-es6/ui-react-dom.js +1 -1
- package/lib/umd-es6/ui-react-dom.js.gz +0 -0
- package/lib/umd-es6/ui-react.js +1 -1
- package/lib/umd-es6/ui-react.js.gz +0 -0
- package/package.json +10 -9
- package/readme.md +3 -3
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
|
+
useValue,
|
|
3
|
+
useSetValueCallback,
|
|
2
4
|
CellView,
|
|
3
|
-
useRowIds,
|
|
4
5
|
useTableCellIds,
|
|
6
|
+
useRowIds,
|
|
7
|
+
useRowCount,
|
|
5
8
|
useSortedRowIds,
|
|
6
9
|
useValueIds,
|
|
7
10
|
ValueView,
|
|
8
11
|
ResultCellView,
|
|
9
|
-
useResultRowIds,
|
|
10
12
|
useResultTableCellIds,
|
|
13
|
+
useResultRowIds,
|
|
14
|
+
useResultRowCount,
|
|
11
15
|
useResultSortedRowIds,
|
|
12
16
|
useCell,
|
|
13
17
|
useSetCellCallback,
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
useStore,
|
|
19
|
+
useTableIds,
|
|
20
|
+
useStoreIds,
|
|
21
|
+
useCreateStore,
|
|
22
|
+
useCreatePersister,
|
|
16
23
|
} from './ui-react';
|
|
17
24
|
import React from 'react';
|
|
18
25
|
|
|
@@ -21,53 +28,278 @@ const EMPTY_STRING = '';
|
|
|
21
28
|
const STRING = getTypeOf(EMPTY_STRING);
|
|
22
29
|
const BOOLEAN = getTypeOf(true);
|
|
23
30
|
const NUMBER = getTypeOf(0);
|
|
31
|
+
const FUNCTION = getTypeOf(getTypeOf);
|
|
32
|
+
const TYPE = 'type';
|
|
33
|
+
const DEFAULT = 'default';
|
|
34
|
+
const LISTENER = 'Listener';
|
|
35
|
+
const ADD = 'add';
|
|
36
|
+
const IDS = 'Ids';
|
|
37
|
+
const TABLE = 'Table';
|
|
38
|
+
const TABLES = TABLE + 's';
|
|
39
|
+
const TABLE_IDS = TABLE + IDS;
|
|
40
|
+
const ROW = 'Row';
|
|
41
|
+
const ROW_COUNT = ROW + 'Count';
|
|
42
|
+
const ROW_IDS = ROW + IDS;
|
|
24
43
|
const CELL = 'Cell';
|
|
44
|
+
const CELL_IDS = CELL + IDS;
|
|
25
45
|
const VALUE = 'Value';
|
|
46
|
+
const VALUES = VALUE + 's';
|
|
47
|
+
const VALUE_IDS = VALUE + IDS;
|
|
26
48
|
const CURRENT_TARGET = 'currentTarget';
|
|
27
49
|
const _VALUE = 'value';
|
|
50
|
+
const id = (key) => EMPTY_STRING + key;
|
|
28
51
|
|
|
29
52
|
const isFiniteNumber = isFinite;
|
|
53
|
+
const isInstanceOf = (thing, cls) => thing instanceof cls;
|
|
30
54
|
const isUndefined = (thing) => thing == void 0;
|
|
55
|
+
const ifNotUndefined = (value, then, otherwise) =>
|
|
56
|
+
isUndefined(value) ? otherwise?.() : then(value);
|
|
31
57
|
const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
|
|
32
58
|
const isString = (thing) => getTypeOf(thing) == STRING;
|
|
59
|
+
const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
|
|
33
60
|
const isArray = (thing) => Array.isArray(thing);
|
|
61
|
+
const test = (regex, subject) => regex.test(subject);
|
|
34
62
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
63
|
+
const arrayHas = (array, value) => array.includes(value);
|
|
64
|
+
const arrayEvery = (array, cb) => array.every(cb);
|
|
65
|
+
const arrayIsEqual = (array1, array2) =>
|
|
66
|
+
arrayLength(array1) === arrayLength(array2) &&
|
|
67
|
+
arrayEvery(array1, (value1, index) => array2[index] === value1);
|
|
68
|
+
const arraySort = (array, sorter) => array.sort(sorter);
|
|
69
|
+
const arrayForEach = (array, cb) => array.forEach(cb);
|
|
70
|
+
const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
|
|
44
71
|
const arrayMap = (array, cb) => array.map(cb);
|
|
72
|
+
const arrayLength = (array) => array.length;
|
|
73
|
+
const arrayIsEmpty = (array) => arrayLength(array) == 0;
|
|
74
|
+
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
75
|
+
const arraySlice = (array, start, end) => array.slice(start, end);
|
|
76
|
+
const arrayPush = (array, ...values) => array.push(...values);
|
|
77
|
+
const arrayShift = (array) => array.shift();
|
|
45
78
|
|
|
46
79
|
const object = Object;
|
|
80
|
+
const objIds = object.keys;
|
|
81
|
+
const objFrozen = object.isFrozen;
|
|
82
|
+
const objFreeze = object.freeze;
|
|
83
|
+
const isObject = (obj) =>
|
|
84
|
+
isInstanceOf(obj, object) && obj.constructor == object;
|
|
47
85
|
const objNew = (entries = []) => object.fromEntries(entries);
|
|
86
|
+
const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
|
|
87
|
+
const objHas = (obj, id) => !isUndefined(objGet(obj, id));
|
|
88
|
+
const objDel = (obj, id) => {
|
|
89
|
+
delete obj[id];
|
|
90
|
+
return obj;
|
|
91
|
+
};
|
|
48
92
|
const objMap = (obj, cb) =>
|
|
49
93
|
arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
|
|
94
|
+
const objSize = (obj) => arrayLength(objIds(obj));
|
|
95
|
+
const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
|
|
50
96
|
|
|
51
|
-
const
|
|
52
|
-
|
|
97
|
+
const jsonString = (obj) =>
|
|
98
|
+
JSON.stringify(obj, (_key, value) =>
|
|
99
|
+
isInstanceOf(value, Map) ? object.fromEntries([...value]) : value,
|
|
100
|
+
);
|
|
101
|
+
const jsonParse = JSON.parse;
|
|
102
|
+
|
|
103
|
+
const UNIQUE_ID = 'tinybaseStoreInspector';
|
|
104
|
+
const TITLE = 'TinyBase Store Inspector';
|
|
105
|
+
const POSITIONS = ['left', 'top', 'bottom', 'right', 'full'];
|
|
106
|
+
const STATE_TABLE = 'state';
|
|
107
|
+
const SORT_CELL = 'sort';
|
|
108
|
+
const OPEN_CELL = 'open';
|
|
109
|
+
const POSITION_VALUE = 'position';
|
|
110
|
+
const OPEN_VALUE = OPEN_CELL;
|
|
111
|
+
const getUniqueId = (...args) => jsonString(args);
|
|
112
|
+
|
|
113
|
+
var img =
|
|
114
|
+
"data:image/svg+xml,%3csvg viewBox='0 0 680 680' xmlns='http://www.w3.org/2000/svg' style='width:680px%3bheight:680px'%3e %3cpath stroke='white' stroke-width='80' fill='none' d='M340 617a84 241 90 11.01 0zM131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124zm-12-127a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e %3cpath fill='%23d81b60' d='M131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124z' /%3e %3cpath d='M249 619a94 240 90 00308-128 114 289 70 01-308 128zM119 208a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e%3c/svg%3e";
|
|
115
|
+
|
|
116
|
+
const PRE_CSS = 'content:url("';
|
|
117
|
+
const POST_CSS = '")';
|
|
118
|
+
const PRE =
|
|
119
|
+
PRE_CSS +
|
|
120
|
+
`data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' stroke-width='4' stroke='white'>`;
|
|
121
|
+
const POST = `</svg>` + POST_CSS;
|
|
122
|
+
const LOGO_SVG = PRE_CSS + img + POST_CSS;
|
|
123
|
+
const POSITIONS_SVG = arrayMap(
|
|
124
|
+
[
|
|
125
|
+
[20, 20, 20, 60],
|
|
126
|
+
[20, 20, 60, 20],
|
|
127
|
+
[20, 60, 60, 20],
|
|
128
|
+
[60, 20, 20, 60],
|
|
129
|
+
[30, 30, 40, 40],
|
|
130
|
+
],
|
|
131
|
+
([x, y, w, h]) =>
|
|
132
|
+
PRE +
|
|
133
|
+
`<rect x='20' y='20' width='60' height='60' fill='grey'/><rect x='${x}' y='${y}' width='${w}' height='${h}' fill='white'/>` +
|
|
134
|
+
POST,
|
|
135
|
+
);
|
|
136
|
+
const CLOSE_SVG = PRE + `<path d='M20 20l60 60M20 80l60-60' />` + POST;
|
|
137
|
+
|
|
138
|
+
const APP_STYLESHEET = arrayJoin(
|
|
139
|
+
objMap(
|
|
140
|
+
{
|
|
141
|
+
'': 'all:initial;font-family:sans-serif;font-size:0.75rem;position:fixed;z-index:999999',
|
|
142
|
+
'*': 'all:revert',
|
|
143
|
+
'*::before': 'all:revert',
|
|
144
|
+
'*::after': 'all:revert',
|
|
145
|
+
img: 'width:1rem;height:1rem;background:#111;border:0',
|
|
146
|
+
// Nub
|
|
147
|
+
'>img': 'padding:0.25rem;bottom:0;right:0;position:fixed;' + LOGO_SVG,
|
|
148
|
+
...objNew(
|
|
149
|
+
arrayMap(['bottom:0;left:0', 'top:0;right:0'], (css, p) => [
|
|
150
|
+
`>img[data-position='${p}']`,
|
|
151
|
+
css,
|
|
152
|
+
]),
|
|
153
|
+
),
|
|
154
|
+
// Panel
|
|
155
|
+
main: 'display:flex;flex-direction:column;background:#111d;color:#fff;position:fixed;',
|
|
156
|
+
...objNew(
|
|
157
|
+
arrayMap(
|
|
158
|
+
[
|
|
159
|
+
'bottom:0;left:0;width:35vw;height:100vh',
|
|
160
|
+
'top:0;right:0;width:100vw;height:30vh',
|
|
161
|
+
'bottom:0;left:0;width:100vw;height:30vh',
|
|
162
|
+
'top:0;right:0;width:35vw;height:100vh',
|
|
163
|
+
'top:0;right:0;width:100vw;height:100vh',
|
|
164
|
+
],
|
|
165
|
+
(css, p) => [`main[data-position='${p}']`, css],
|
|
166
|
+
),
|
|
167
|
+
),
|
|
168
|
+
// Header
|
|
169
|
+
header: 'display:flex;padding:0.25rem;background:#000;align-items:center',
|
|
170
|
+
'header>img:nth-of-type(1)': LOGO_SVG,
|
|
171
|
+
'header>img:nth-of-type(6)': CLOSE_SVG,
|
|
172
|
+
...objNew(
|
|
173
|
+
arrayMap(POSITIONS_SVG, (SVG, p) => [
|
|
174
|
+
`header>img[data-id='${p}']`,
|
|
175
|
+
SVG,
|
|
176
|
+
]),
|
|
177
|
+
),
|
|
178
|
+
'header>span':
|
|
179
|
+
'flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:0.25rem',
|
|
180
|
+
// Body
|
|
181
|
+
article: 'padding:0.25rem 0.25rem 0.25rem 0.5rem;overflow:auto',
|
|
182
|
+
details: 'margin-left:0.75rem;width:fit-content;',
|
|
183
|
+
summary:
|
|
184
|
+
'margin-left:-0.75rem;line-height:1.25rem;user-select:none;width:fit-content',
|
|
185
|
+
table: 'border-collapse:collapse;table-layout:fixed;margin-bottom:0.5rem',
|
|
186
|
+
thead: 'background:#222',
|
|
187
|
+
'th:nth-of-type(1)': 'min-width:2rem;',
|
|
188
|
+
'th.sorted': 'background:#000',
|
|
189
|
+
'table caption': 'text-align:left;white-space:nowrap;line-height:1.25rem',
|
|
190
|
+
button: 'width:1.5rem;border:none;background:none;color:#fff;padding:0',
|
|
191
|
+
'button[disabled]': 'color:#777',
|
|
192
|
+
'button.next': 'margin-right:0.5rem',
|
|
193
|
+
[`th,#${UNIQUE_ID} td`]:
|
|
194
|
+
'overflow:hidden;text-overflow:ellipsis;padding:0.25rem 0.5rem;max-width:12rem;white-space:nowrap;border-width:1px 0;border-style:solid;border-color:#777;text-align:left',
|
|
195
|
+
},
|
|
196
|
+
(style, selector) => (style ? `#${UNIQUE_ID} ${selector}{${style}}` : ''),
|
|
197
|
+
),
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const {createElement} = React;
|
|
53
201
|
const getProps = (getProps2, ...ids) =>
|
|
54
202
|
isUndefined(getProps2) ? {} : getProps2(...ids);
|
|
55
203
|
|
|
56
|
-
const
|
|
204
|
+
const Nub = ({s}) => {
|
|
205
|
+
const position = useValue(POSITION_VALUE, s) ?? 1;
|
|
206
|
+
const handleOpen = useSetValueCallback(OPEN_VALUE, () => true, [], s);
|
|
207
|
+
return useValue(OPEN_VALUE, s)
|
|
208
|
+
? null
|
|
209
|
+
: /* @__PURE__ */ createElement('img', {
|
|
210
|
+
onClick: handleOpen,
|
|
211
|
+
title: TITLE,
|
|
212
|
+
'data-position': position,
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const getCellOrValueType = (cell) => {
|
|
217
|
+
const type = getTypeOf(cell);
|
|
218
|
+
return isTypeStringOrBoolean(type) || (type == NUMBER && isFiniteNumber(cell))
|
|
219
|
+
? type
|
|
220
|
+
: void 0;
|
|
221
|
+
};
|
|
222
|
+
const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
|
|
223
|
+
isUndefined(cell)
|
|
224
|
+
? store.delCell(tableId, rowId, cellId, true)
|
|
225
|
+
: store.setCell(tableId, rowId, cellId, cell);
|
|
226
|
+
const setOrDelValue = (store, valueId, value) =>
|
|
227
|
+
isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
|
|
228
|
+
const getTypeCase = (type, stringCase, numberCase, booleanCase) =>
|
|
229
|
+
type == STRING ? stringCase : type == NUMBER ? numberCase : booleanCase;
|
|
230
|
+
|
|
231
|
+
const {useCallback, useMemo, useState} = React;
|
|
57
232
|
const EDITABLE = 'editable';
|
|
233
|
+
const LEFT_ARROW = '\u2190';
|
|
234
|
+
const UP_ARROW = '\u2191';
|
|
235
|
+
const RIGHT_ARROW = '\u2192';
|
|
236
|
+
const DOWN_ARROW = '\u2193';
|
|
58
237
|
const useCallbackOrUndefined = (callback, deps, test) => {
|
|
59
238
|
const returnCallback = useCallback(callback, deps);
|
|
60
239
|
return test ? returnCallback : void 0;
|
|
61
240
|
};
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
241
|
+
const useSortingAndPagination = (
|
|
242
|
+
cellId,
|
|
243
|
+
descending = false,
|
|
244
|
+
sortOnClick,
|
|
245
|
+
offset = 0,
|
|
246
|
+
limit,
|
|
247
|
+
total,
|
|
248
|
+
paginator,
|
|
249
|
+
onChange,
|
|
250
|
+
) => {
|
|
251
|
+
const [[currentCellId, currentDescending, currentOffset], setState] =
|
|
252
|
+
useState([cellId, descending, offset]);
|
|
253
|
+
const setStateAndChange = useCallback(
|
|
254
|
+
(sortAndOffset) => {
|
|
255
|
+
setState(sortAndOffset);
|
|
256
|
+
onChange?.(sortAndOffset);
|
|
257
|
+
},
|
|
258
|
+
[onChange],
|
|
259
|
+
);
|
|
260
|
+
const handleSort = useCallbackOrUndefined(
|
|
261
|
+
(cellId2) =>
|
|
262
|
+
setStateAndChange([
|
|
263
|
+
cellId2,
|
|
264
|
+
cellId2 == currentCellId ? !currentDescending : false,
|
|
265
|
+
currentOffset,
|
|
266
|
+
]),
|
|
267
|
+
[setStateAndChange, currentCellId, currentDescending, currentOffset],
|
|
268
|
+
sortOnClick,
|
|
269
|
+
);
|
|
270
|
+
const handleChangeOffset = useCallback(
|
|
271
|
+
(offset2) => setStateAndChange([currentCellId, currentDescending, offset2]),
|
|
272
|
+
[setStateAndChange, currentCellId, currentDescending],
|
|
273
|
+
);
|
|
274
|
+
const PaginatorComponent =
|
|
275
|
+
paginator === true ? SortedTablePaginator : paginator;
|
|
276
|
+
return [
|
|
277
|
+
[currentCellId, currentDescending, currentOffset],
|
|
278
|
+
handleSort,
|
|
279
|
+
useMemo(
|
|
280
|
+
() =>
|
|
281
|
+
paginator === false
|
|
282
|
+
? null
|
|
283
|
+
: /* @__PURE__ */ createElement(PaginatorComponent, {
|
|
284
|
+
offset: currentOffset,
|
|
285
|
+
limit,
|
|
286
|
+
total,
|
|
287
|
+
onChange: handleChangeOffset,
|
|
288
|
+
}),
|
|
289
|
+
[
|
|
290
|
+
paginator,
|
|
291
|
+
PaginatorComponent,
|
|
292
|
+
currentOffset,
|
|
293
|
+
limit,
|
|
294
|
+
total,
|
|
295
|
+
handleChangeOffset,
|
|
296
|
+
],
|
|
297
|
+
),
|
|
298
|
+
];
|
|
299
|
+
};
|
|
300
|
+
const HtmlHeader = ({
|
|
69
301
|
cellId,
|
|
70
|
-
|
|
302
|
+
sort: [sortCellId, sortDescending],
|
|
71
303
|
label = cellId ?? EMPTY_STRING,
|
|
72
304
|
onClick,
|
|
73
305
|
}) =>
|
|
@@ -77,10 +309,16 @@ const HtmlHeaderTh = ({
|
|
|
77
309
|
onClick: useCallbackOrUndefined(
|
|
78
310
|
() => onClick?.(cellId),
|
|
79
311
|
[onClick, cellId],
|
|
80
|
-
|
|
312
|
+
onClick,
|
|
81
313
|
),
|
|
82
|
-
className:
|
|
314
|
+
className:
|
|
315
|
+
isUndefined(sortDescending) || sortCellId != cellId
|
|
316
|
+
? void 0
|
|
317
|
+
: `sorted ${sortDescending ? 'de' : 'a'}scending`,
|
|
83
318
|
},
|
|
319
|
+
isUndefined(sortDescending) || sortCellId != cellId
|
|
320
|
+
? null
|
|
321
|
+
: (sortDescending ? DOWN_ARROW : UP_ARROW) + ' ',
|
|
84
322
|
label,
|
|
85
323
|
);
|
|
86
324
|
const HtmlTable = ({
|
|
@@ -88,13 +326,19 @@ const HtmlTable = ({
|
|
|
88
326
|
headerRow,
|
|
89
327
|
idColumn,
|
|
90
328
|
customCells,
|
|
91
|
-
|
|
92
|
-
defaultCellComponent,
|
|
329
|
+
params,
|
|
93
330
|
rowIds,
|
|
94
|
-
defaultCellIds,
|
|
95
|
-
sorting,
|
|
96
|
-
onHeaderThClick,
|
|
97
331
|
}) => {
|
|
332
|
+
const [
|
|
333
|
+
cellComponentProps,
|
|
334
|
+
useCellIdsArgs,
|
|
335
|
+
defaultCellComponent,
|
|
336
|
+
useDefaultCellIds,
|
|
337
|
+
sortAndOffset,
|
|
338
|
+
handleSort,
|
|
339
|
+
paginatorComponent,
|
|
340
|
+
] = params;
|
|
341
|
+
const defaultCellIds = useDefaultCellIds(...useCellIdsArgs);
|
|
98
342
|
const customCellConfigurations = useMemo(() => {
|
|
99
343
|
const cellIds = customCells ?? defaultCellIds;
|
|
100
344
|
return objNew(
|
|
@@ -117,6 +361,9 @@ const HtmlTable = ({
|
|
|
117
361
|
return /* @__PURE__ */ createElement(
|
|
118
362
|
'table',
|
|
119
363
|
{className},
|
|
364
|
+
paginatorComponent
|
|
365
|
+
? /* @__PURE__ */ createElement('caption', null, paginatorComponent)
|
|
366
|
+
: null,
|
|
120
367
|
headerRow === false
|
|
121
368
|
? null
|
|
122
369
|
: /* @__PURE__ */ createElement(
|
|
@@ -127,18 +374,18 @@ const HtmlTable = ({
|
|
|
127
374
|
null,
|
|
128
375
|
idColumn === false
|
|
129
376
|
? null
|
|
130
|
-
: /* @__PURE__ */ createElement(
|
|
131
|
-
|
|
377
|
+
: /* @__PURE__ */ createElement(HtmlHeader, {
|
|
378
|
+
sort: sortAndOffset ?? [],
|
|
132
379
|
label: 'Id',
|
|
133
|
-
onClick:
|
|
380
|
+
onClick: handleSort,
|
|
134
381
|
}),
|
|
135
382
|
objMap(customCellConfigurations, ({label}, cellId) =>
|
|
136
|
-
/* @__PURE__ */ createElement(
|
|
383
|
+
/* @__PURE__ */ createElement(HtmlHeader, {
|
|
137
384
|
key: cellId,
|
|
138
385
|
cellId,
|
|
139
386
|
label,
|
|
140
|
-
|
|
141
|
-
onClick:
|
|
387
|
+
sort: sortAndOffset ?? [],
|
|
388
|
+
onClick: handleSort,
|
|
142
389
|
}),
|
|
143
390
|
),
|
|
144
391
|
),
|
|
@@ -164,7 +411,7 @@ const HtmlTable = ({
|
|
|
164
411
|
{key: cellId},
|
|
165
412
|
/* @__PURE__ */ createElement(CellView2, {
|
|
166
413
|
...getProps(getComponentProps, rowId, cellId),
|
|
167
|
-
...
|
|
414
|
+
...cellComponentProps,
|
|
168
415
|
rowId,
|
|
169
416
|
cellId,
|
|
170
417
|
}),
|
|
@@ -202,7 +449,6 @@ const EditableThing = ({thing, onThingChange, className}) => {
|
|
|
202
449
|
/* @__PURE__ */ createElement(
|
|
203
450
|
'button',
|
|
204
451
|
{
|
|
205
|
-
type: 'button',
|
|
206
452
|
className: thingType,
|
|
207
453
|
onClick: useCallback(() => {
|
|
208
454
|
const nextType = getTypeCase(thingType, NUMBER, BOOLEAN, STRING);
|
|
@@ -265,13 +511,16 @@ const EditableThing = ({thing, onThingChange, className}) => {
|
|
|
265
511
|
const TableInHtmlTable = ({tableId, store, editable, ...props}) =>
|
|
266
512
|
/* @__PURE__ */ createElement(HtmlTable, {
|
|
267
513
|
...props,
|
|
268
|
-
|
|
269
|
-
() =>
|
|
270
|
-
|
|
514
|
+
params: useMemo(
|
|
515
|
+
() => [
|
|
516
|
+
{tableId, store},
|
|
517
|
+
[tableId, store],
|
|
518
|
+
editable ? EditableCellView : CellView,
|
|
519
|
+
useTableCellIds,
|
|
520
|
+
],
|
|
521
|
+
[store, tableId, editable],
|
|
271
522
|
),
|
|
272
|
-
defaultCellComponent: editable ? EditableCellView : CellView,
|
|
273
523
|
rowIds: useRowIds(tableId, store),
|
|
274
|
-
defaultCellIds: useTableCellIds(tableId, store),
|
|
275
524
|
});
|
|
276
525
|
const SortedTableInHtmlTable = ({
|
|
277
526
|
tableId,
|
|
@@ -282,26 +531,36 @@ const SortedTableInHtmlTable = ({
|
|
|
282
531
|
store,
|
|
283
532
|
editable,
|
|
284
533
|
sortOnClick,
|
|
534
|
+
paginator = false,
|
|
535
|
+
onChange,
|
|
285
536
|
...props
|
|
286
537
|
}) => {
|
|
287
|
-
const [
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
538
|
+
const [sortAndOffset, handleSort, paginatorComponent] =
|
|
539
|
+
useSortingAndPagination(
|
|
540
|
+
cellId,
|
|
541
|
+
descending,
|
|
542
|
+
sortOnClick,
|
|
543
|
+
offset,
|
|
544
|
+
limit,
|
|
545
|
+
useRowCount(tableId, store),
|
|
546
|
+
paginator,
|
|
547
|
+
onChange,
|
|
548
|
+
);
|
|
294
549
|
return /* @__PURE__ */ createElement(HtmlTable, {
|
|
295
550
|
...props,
|
|
296
|
-
|
|
297
|
-
() =>
|
|
298
|
-
|
|
551
|
+
params: useMemo(
|
|
552
|
+
() => [
|
|
553
|
+
{tableId, store},
|
|
554
|
+
[tableId, store],
|
|
555
|
+
editable ? EditableCellView : CellView,
|
|
556
|
+
useTableCellIds,
|
|
557
|
+
sortAndOffset,
|
|
558
|
+
handleSort,
|
|
559
|
+
paginatorComponent,
|
|
560
|
+
],
|
|
561
|
+
[store, tableId, editable, sortAndOffset, handleSort, paginatorComponent],
|
|
299
562
|
),
|
|
300
|
-
|
|
301
|
-
rowIds: useSortedRowIds(tableId, ...sorting, offset, limit, store),
|
|
302
|
-
defaultCellIds: useTableCellIds(tableId, store),
|
|
303
|
-
sorting,
|
|
304
|
-
onHeaderThClick: handleHeaderThClick,
|
|
563
|
+
rowIds: useSortedRowIds(tableId, ...sortAndOffset, limit, store),
|
|
305
564
|
});
|
|
306
565
|
};
|
|
307
566
|
const ValuesInHtmlTable = ({
|
|
@@ -356,13 +615,16 @@ const ValuesInHtmlTable = ({
|
|
|
356
615
|
const ResultTableInHtmlTable = ({queryId, queries, ...props}) =>
|
|
357
616
|
/* @__PURE__ */ createElement(HtmlTable, {
|
|
358
617
|
...props,
|
|
359
|
-
|
|
360
|
-
() =>
|
|
361
|
-
|
|
618
|
+
params: useMemo(
|
|
619
|
+
() => [
|
|
620
|
+
{queryId, queries},
|
|
621
|
+
[queryId, queries],
|
|
622
|
+
ResultCellView,
|
|
623
|
+
useResultTableCellIds,
|
|
624
|
+
],
|
|
625
|
+
[queryId, queries],
|
|
362
626
|
),
|
|
363
|
-
defaultCellComponent: ResultCellView,
|
|
364
627
|
rowIds: useResultRowIds(queryId, queries),
|
|
365
|
-
defaultCellIds: useResultTableCellIds(queryId, queries),
|
|
366
628
|
});
|
|
367
629
|
const ResultSortedTableInHtmlTable = ({
|
|
368
630
|
queryId,
|
|
@@ -372,26 +634,36 @@ const ResultSortedTableInHtmlTable = ({
|
|
|
372
634
|
limit,
|
|
373
635
|
queries,
|
|
374
636
|
sortOnClick,
|
|
637
|
+
paginator = false,
|
|
638
|
+
onChange,
|
|
375
639
|
...props
|
|
376
640
|
}) => {
|
|
377
|
-
const [
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
641
|
+
const [sortAndOffset, handleSort, paginatorComponent] =
|
|
642
|
+
useSortingAndPagination(
|
|
643
|
+
cellId,
|
|
644
|
+
descending,
|
|
645
|
+
sortOnClick,
|
|
646
|
+
offset,
|
|
647
|
+
limit,
|
|
648
|
+
useResultRowCount(queryId, queries),
|
|
649
|
+
paginator,
|
|
650
|
+
onChange,
|
|
651
|
+
);
|
|
384
652
|
return /* @__PURE__ */ createElement(HtmlTable, {
|
|
385
653
|
...props,
|
|
386
|
-
|
|
387
|
-
() =>
|
|
388
|
-
|
|
654
|
+
params: useMemo(
|
|
655
|
+
() => [
|
|
656
|
+
{queryId, queries},
|
|
657
|
+
[queryId, queries],
|
|
658
|
+
ResultCellView,
|
|
659
|
+
useResultTableCellIds,
|
|
660
|
+
sortAndOffset,
|
|
661
|
+
handleSort,
|
|
662
|
+
paginatorComponent,
|
|
663
|
+
],
|
|
664
|
+
[queryId, queries, sortAndOffset, handleSort, paginatorComponent],
|
|
389
665
|
),
|
|
390
|
-
|
|
391
|
-
rowIds: useResultSortedRowIds(queryId, ...sorting, offset, limit, queries),
|
|
392
|
-
defaultCellIds: useResultTableCellIds(queryId, queries),
|
|
393
|
-
sorting,
|
|
394
|
-
onHeaderThClick: handleHeaderThClick,
|
|
666
|
+
rowIds: useResultSortedRowIds(queryId, ...sortAndOffset, limit, queries),
|
|
395
667
|
});
|
|
396
668
|
};
|
|
397
669
|
const EditableCellView = ({tableId, rowId, cellId, store, className}) =>
|
|
@@ -413,6 +685,1796 @@ const EditableValueView = ({valueId, store, className}) =>
|
|
|
413
685
|
onThingChange: useSetValueCallback(valueId, (value) => value, [], store),
|
|
414
686
|
className: className ?? EDITABLE + VALUE,
|
|
415
687
|
});
|
|
688
|
+
const SortedTablePaginator = ({
|
|
689
|
+
onChange,
|
|
690
|
+
total,
|
|
691
|
+
offset = 0,
|
|
692
|
+
limit = total,
|
|
693
|
+
singular = 'row',
|
|
694
|
+
plural = singular + 's',
|
|
695
|
+
}) => {
|
|
696
|
+
if (offset > total || offset < 0) {
|
|
697
|
+
offset = 0;
|
|
698
|
+
onChange(0);
|
|
699
|
+
}
|
|
700
|
+
const handlePrevClick = useCallbackOrUndefined(
|
|
701
|
+
() => onChange(offset - limit),
|
|
702
|
+
[onChange, offset, limit],
|
|
703
|
+
offset > 0,
|
|
704
|
+
);
|
|
705
|
+
const handleNextClick = useCallbackOrUndefined(
|
|
706
|
+
() => onChange(offset + limit),
|
|
707
|
+
[onChange, offset, limit],
|
|
708
|
+
offset + limit < total,
|
|
709
|
+
);
|
|
710
|
+
return /* @__PURE__ */ createElement(
|
|
711
|
+
React.Fragment,
|
|
712
|
+
null,
|
|
713
|
+
total > limit &&
|
|
714
|
+
/* @__PURE__ */ createElement(
|
|
715
|
+
React.Fragment,
|
|
716
|
+
null,
|
|
717
|
+
/* @__PURE__ */ createElement(
|
|
718
|
+
'button',
|
|
719
|
+
{
|
|
720
|
+
className: 'previous',
|
|
721
|
+
disabled: offset == 0,
|
|
722
|
+
onClick: handlePrevClick,
|
|
723
|
+
},
|
|
724
|
+
LEFT_ARROW,
|
|
725
|
+
),
|
|
726
|
+
/* @__PURE__ */ createElement(
|
|
727
|
+
'button',
|
|
728
|
+
{
|
|
729
|
+
className: 'next',
|
|
730
|
+
disabled: offset + limit >= total,
|
|
731
|
+
onClick: handleNextClick,
|
|
732
|
+
},
|
|
733
|
+
RIGHT_ARROW,
|
|
734
|
+
),
|
|
735
|
+
offset + 1,
|
|
736
|
+
' to ',
|
|
737
|
+
Math.min(total, offset + limit),
|
|
738
|
+
' of ',
|
|
739
|
+
),
|
|
740
|
+
total,
|
|
741
|
+
' ',
|
|
742
|
+
total != 1 ? plural : singular,
|
|
743
|
+
);
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
const Details = ({uniqueId, summary, children, s}) => {
|
|
747
|
+
const open = !!useCell(STATE_TABLE, uniqueId, OPEN_CELL, s);
|
|
748
|
+
const handleToggle = useSetCellCallback(
|
|
749
|
+
STATE_TABLE,
|
|
750
|
+
uniqueId,
|
|
751
|
+
OPEN_CELL,
|
|
752
|
+
(event) => event[CURRENT_TARGET].open,
|
|
753
|
+
[],
|
|
754
|
+
s,
|
|
755
|
+
);
|
|
756
|
+
return /* @__PURE__ */ React.createElement(
|
|
757
|
+
'details',
|
|
758
|
+
{open, onToggle: handleToggle},
|
|
759
|
+
/* @__PURE__ */ React.createElement('summary', null, summary),
|
|
760
|
+
children,
|
|
761
|
+
);
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
const StoreTableView = ({tableId, store, storeId, s}) => {
|
|
765
|
+
const uniqueId = getUniqueId('t', storeId, tableId);
|
|
766
|
+
const [cellId, descending, offset] = jsonParse(
|
|
767
|
+
useCell(STATE_TABLE, uniqueId, SORT_CELL, s) ?? '[]',
|
|
768
|
+
);
|
|
769
|
+
const handleChange = useSetCellCallback(
|
|
770
|
+
STATE_TABLE,
|
|
771
|
+
uniqueId,
|
|
772
|
+
SORT_CELL,
|
|
773
|
+
jsonString,
|
|
774
|
+
[],
|
|
775
|
+
s,
|
|
776
|
+
);
|
|
777
|
+
return /* @__PURE__ */ createElement(
|
|
778
|
+
Details,
|
|
779
|
+
{uniqueId, summary: TABLE + ': ' + tableId, s},
|
|
780
|
+
/* @__PURE__ */ createElement(SortedTableInHtmlTable, {
|
|
781
|
+
tableId,
|
|
782
|
+
store,
|
|
783
|
+
cellId,
|
|
784
|
+
descending,
|
|
785
|
+
offset,
|
|
786
|
+
limit: 10,
|
|
787
|
+
paginator: true,
|
|
788
|
+
sortOnClick: true,
|
|
789
|
+
onChange: handleChange,
|
|
790
|
+
}),
|
|
791
|
+
);
|
|
792
|
+
};
|
|
793
|
+
const StoreValuesView = ({store, storeId, s}) =>
|
|
794
|
+
arrayIsEmpty(useValueIds(store))
|
|
795
|
+
? null
|
|
796
|
+
: /* @__PURE__ */ createElement(
|
|
797
|
+
Details,
|
|
798
|
+
{uniqueId: getUniqueId('v', storeId), summary: VALUES, s},
|
|
799
|
+
/* @__PURE__ */ createElement(ValuesInHtmlTable, {store}),
|
|
800
|
+
);
|
|
801
|
+
const StoreView = ({storeId, s}) => {
|
|
802
|
+
const store = useStore(storeId);
|
|
803
|
+
const tableIds = useTableIds(store);
|
|
804
|
+
return isUndefined(store)
|
|
805
|
+
? null
|
|
806
|
+
: /* @__PURE__ */ createElement(
|
|
807
|
+
Details,
|
|
808
|
+
{
|
|
809
|
+
uniqueId: getUniqueId('s', storeId),
|
|
810
|
+
summary: 'Store: ' + (storeId ?? DEFAULT),
|
|
811
|
+
s,
|
|
812
|
+
},
|
|
813
|
+
/* @__PURE__ */ createElement(StoreValuesView, {storeId, store, s}),
|
|
814
|
+
arrayMap(tableIds, (tableId) =>
|
|
815
|
+
/* @__PURE__ */ createElement(StoreTableView, {
|
|
816
|
+
storeId,
|
|
817
|
+
tableId,
|
|
818
|
+
store,
|
|
819
|
+
s,
|
|
820
|
+
}),
|
|
821
|
+
),
|
|
822
|
+
);
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
const Body = (props) =>
|
|
826
|
+
/* @__PURE__ */ createElement(
|
|
827
|
+
'article',
|
|
828
|
+
null,
|
|
829
|
+
/* @__PURE__ */ createElement(StoreView, {...props}),
|
|
830
|
+
arrayMap(useStoreIds(), (storeId) =>
|
|
831
|
+
/* @__PURE__ */ createElement(StoreView, {
|
|
832
|
+
storeId,
|
|
833
|
+
key: storeId,
|
|
834
|
+
...props,
|
|
835
|
+
}),
|
|
836
|
+
),
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
const Header = ({s}) => {
|
|
840
|
+
const position = useValue(POSITION_VALUE, s) ?? 1;
|
|
841
|
+
const handleClose = useSetValueCallback(OPEN_VALUE, () => false, [], s);
|
|
842
|
+
const handleDock = useSetValueCallback(
|
|
843
|
+
POSITION_VALUE,
|
|
844
|
+
(event) => Number(event[CURRENT_TARGET].dataset.id),
|
|
845
|
+
[],
|
|
846
|
+
s,
|
|
847
|
+
);
|
|
848
|
+
return /* @__PURE__ */ createElement(
|
|
849
|
+
'header',
|
|
850
|
+
null,
|
|
851
|
+
/* @__PURE__ */ createElement('img', {title: TITLE}),
|
|
852
|
+
/* @__PURE__ */ createElement('span', null, TITLE),
|
|
853
|
+
arrayMap(POSITIONS, (name, p) =>
|
|
854
|
+
p == position
|
|
855
|
+
? null
|
|
856
|
+
: /* @__PURE__ */ createElement('img', {
|
|
857
|
+
onClick: handleDock,
|
|
858
|
+
'data-id': p,
|
|
859
|
+
title: 'Dock to ' + name,
|
|
860
|
+
key: p,
|
|
861
|
+
}),
|
|
862
|
+
),
|
|
863
|
+
/* @__PURE__ */ createElement('img', {
|
|
864
|
+
onClick: handleClose,
|
|
865
|
+
title: 'Close',
|
|
866
|
+
}),
|
|
867
|
+
);
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
const Panel = ({s}) => {
|
|
871
|
+
const position = useValue(POSITION_VALUE, s) ?? 1;
|
|
872
|
+
return useValue(OPEN_VALUE, s)
|
|
873
|
+
? /* @__PURE__ */ createElement(
|
|
874
|
+
'main',
|
|
875
|
+
{'data-position': position},
|
|
876
|
+
/* @__PURE__ */ createElement(Header, {s}),
|
|
877
|
+
/* @__PURE__ */ createElement(Body, {s}),
|
|
878
|
+
)
|
|
879
|
+
: null;
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
const createCustomPersister = (
|
|
883
|
+
store,
|
|
884
|
+
getPersisted,
|
|
885
|
+
setPersisted,
|
|
886
|
+
addPersisterListener,
|
|
887
|
+
delPersisterListener,
|
|
888
|
+
) => {
|
|
889
|
+
let listenerId;
|
|
890
|
+
let loadSave = 0;
|
|
891
|
+
let loads = 0;
|
|
892
|
+
let saves = 0;
|
|
893
|
+
let running = 0;
|
|
894
|
+
let listening = 0;
|
|
895
|
+
let action;
|
|
896
|
+
let listeningHandle;
|
|
897
|
+
const scheduledActions = [];
|
|
898
|
+
const run = async () => {
|
|
899
|
+
/* istanbul ignore else */
|
|
900
|
+
if (!running) {
|
|
901
|
+
running = 1;
|
|
902
|
+
while (!isUndefined((action = arrayShift(scheduledActions)))) {
|
|
903
|
+
try {
|
|
904
|
+
await action();
|
|
905
|
+
} catch {}
|
|
906
|
+
}
|
|
907
|
+
running = 0;
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
const loadLock = async (actions) => {
|
|
911
|
+
/* istanbul ignore else */
|
|
912
|
+
if (loadSave != 2) {
|
|
913
|
+
loadSave = 1;
|
|
914
|
+
{
|
|
915
|
+
loads++;
|
|
916
|
+
}
|
|
917
|
+
await persister.schedule(async () => {
|
|
918
|
+
await actions();
|
|
919
|
+
loadSave = 0;
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
return persister;
|
|
923
|
+
};
|
|
924
|
+
const persister = {
|
|
925
|
+
load: async (initialTables, initialValues) =>
|
|
926
|
+
await loadLock(async () => {
|
|
927
|
+
try {
|
|
928
|
+
store.setContent(await getPersisted());
|
|
929
|
+
} catch {
|
|
930
|
+
store.setContent([initialTables, initialValues]);
|
|
931
|
+
}
|
|
932
|
+
}),
|
|
933
|
+
startAutoLoad: async (initialTables = {}, initialValues = {}) => {
|
|
934
|
+
persister.stopAutoLoad();
|
|
935
|
+
await persister.load(initialTables, initialValues);
|
|
936
|
+
listening = 1;
|
|
937
|
+
listeningHandle = addPersisterListener(
|
|
938
|
+
async (getContent, getTransactionChanges) =>
|
|
939
|
+
await loadLock(async () => {
|
|
940
|
+
if (getTransactionChanges) {
|
|
941
|
+
store.setTransactionChanges(getTransactionChanges());
|
|
942
|
+
} else {
|
|
943
|
+
try {
|
|
944
|
+
store.setContent(getContent?.() ?? (await getPersisted()));
|
|
945
|
+
} catch {}
|
|
946
|
+
}
|
|
947
|
+
}),
|
|
948
|
+
);
|
|
949
|
+
return persister;
|
|
950
|
+
},
|
|
951
|
+
stopAutoLoad: () => {
|
|
952
|
+
if (listening) {
|
|
953
|
+
delPersisterListener(listeningHandle);
|
|
954
|
+
listeningHandle = void 0;
|
|
955
|
+
listening = 0;
|
|
956
|
+
}
|
|
957
|
+
return persister;
|
|
958
|
+
},
|
|
959
|
+
save: async (getTransactionChanges) => {
|
|
960
|
+
/* istanbul ignore else */
|
|
961
|
+
if (loadSave != 1) {
|
|
962
|
+
loadSave = 2;
|
|
963
|
+
{
|
|
964
|
+
saves++;
|
|
965
|
+
}
|
|
966
|
+
await persister.schedule(async () => {
|
|
967
|
+
try {
|
|
968
|
+
await setPersisted(store.getContent, getTransactionChanges);
|
|
969
|
+
} catch {}
|
|
970
|
+
loadSave = 0;
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
return persister;
|
|
974
|
+
},
|
|
975
|
+
startAutoSave: async () => {
|
|
976
|
+
await persister.stopAutoSave().save();
|
|
977
|
+
listenerId = store.addDidFinishTransactionListener(
|
|
978
|
+
(_store, getTransactionChanges) => {
|
|
979
|
+
const [tableChanges, valueChanges] = getTransactionChanges();
|
|
980
|
+
if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
|
|
981
|
+
persister.save(() => [tableChanges, valueChanges]);
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
);
|
|
985
|
+
return persister;
|
|
986
|
+
},
|
|
987
|
+
stopAutoSave: () => {
|
|
988
|
+
ifNotUndefined(listenerId, store.delListener);
|
|
989
|
+
return persister;
|
|
990
|
+
},
|
|
991
|
+
schedule: async (...actions) => {
|
|
992
|
+
arrayPush(scheduledActions, ...actions);
|
|
993
|
+
await run();
|
|
994
|
+
return persister;
|
|
995
|
+
},
|
|
996
|
+
getStore: () => store,
|
|
997
|
+
destroy: () => persister.stopAutoLoad().stopAutoSave(),
|
|
998
|
+
getStats: () => ({loads, saves}),
|
|
999
|
+
};
|
|
1000
|
+
return objFreeze(persister);
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
const STORAGE = 'storage';
|
|
1004
|
+
const WINDOW = globalThis.window;
|
|
1005
|
+
const getStoragePersister = (store, storageName, storage) => {
|
|
1006
|
+
const getPersisted = async () => jsonParse(storage.getItem(storageName));
|
|
1007
|
+
const setPersisted = async (getContent) =>
|
|
1008
|
+
storage.setItem(storageName, jsonString(getContent()));
|
|
1009
|
+
const addPersisterListener = (listener) => {
|
|
1010
|
+
const storeListener = (event) => {
|
|
1011
|
+
if (event.storageArea === storage && event.key === storageName) {
|
|
1012
|
+
listener(() => jsonParse(event.newValue));
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
WINDOW.addEventListener(STORAGE, storeListener);
|
|
1016
|
+
return storeListener;
|
|
1017
|
+
};
|
|
1018
|
+
const delPersisterListener = (storeListener) =>
|
|
1019
|
+
WINDOW.removeEventListener(STORAGE, storeListener);
|
|
1020
|
+
return createCustomPersister(
|
|
1021
|
+
store,
|
|
1022
|
+
getPersisted,
|
|
1023
|
+
setPersisted,
|
|
1024
|
+
addPersisterListener,
|
|
1025
|
+
delPersisterListener,
|
|
1026
|
+
);
|
|
1027
|
+
};
|
|
1028
|
+
const createSessionPersister = (store, storageName) =>
|
|
1029
|
+
getStoragePersister(store, storageName, sessionStorage);
|
|
1030
|
+
|
|
1031
|
+
const collSizeN = (collSizer) => (coll) =>
|
|
1032
|
+
arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
|
|
1033
|
+
const collSize = (coll) => coll?.size ?? 0;
|
|
1034
|
+
const collSize2 = collSizeN(collSize);
|
|
1035
|
+
const collSize3 = collSizeN(collSize2);
|
|
1036
|
+
const collSize4 = collSizeN(collSize3);
|
|
1037
|
+
const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
|
|
1038
|
+
const collIsEmpty = (coll) => isUndefined(coll) || collSize(coll) == 0;
|
|
1039
|
+
const collValues = (coll) => [...(coll?.values() ?? [])];
|
|
1040
|
+
const collClear = (coll) => coll.clear();
|
|
1041
|
+
const collForEach = (coll, cb) => coll?.forEach(cb);
|
|
1042
|
+
const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
|
|
1043
|
+
|
|
1044
|
+
const mapNew = (entries) => new Map(entries);
|
|
1045
|
+
const mapKeys = (map) => [...(map?.keys() ?? [])];
|
|
1046
|
+
const mapGet = (map, key) => map?.get(key);
|
|
1047
|
+
const mapForEach = (map, cb) =>
|
|
1048
|
+
collForEach(map, (value, key) => cb(key, value));
|
|
1049
|
+
const mapMap = (coll, cb) =>
|
|
1050
|
+
arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
|
|
1051
|
+
const mapSet = (map, key, value) =>
|
|
1052
|
+
isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
|
|
1053
|
+
const mapEnsure = (map, key, getDefaultValue) => {
|
|
1054
|
+
if (!collHas(map, key)) {
|
|
1055
|
+
mapSet(map, key, getDefaultValue());
|
|
1056
|
+
}
|
|
1057
|
+
return mapGet(map, key);
|
|
1058
|
+
};
|
|
1059
|
+
const mapMatch = (map, obj, set, del = mapSet) => {
|
|
1060
|
+
objMap(obj, (value, id) => set(map, id, value));
|
|
1061
|
+
mapForEach(map, (id) => (objHas(obj, id) ? 0 : del(map, id)));
|
|
1062
|
+
return map;
|
|
1063
|
+
};
|
|
1064
|
+
const mapToObj = (map, mapValue, excludeValue) => {
|
|
1065
|
+
const obj = {};
|
|
1066
|
+
collForEach(map, (value, id) => {
|
|
1067
|
+
const mappedValue = mapValue ? mapValue(value, id) : value;
|
|
1068
|
+
excludeValue?.(mappedValue, value) ? 0 : (obj[id] = mappedValue);
|
|
1069
|
+
});
|
|
1070
|
+
return obj;
|
|
1071
|
+
};
|
|
1072
|
+
const mapToObj2 = (map, mapValue, excludeValue) =>
|
|
1073
|
+
mapToObj(
|
|
1074
|
+
map,
|
|
1075
|
+
(childMap) => mapToObj(childMap, mapValue, excludeValue),
|
|
1076
|
+
objIsEmpty,
|
|
1077
|
+
);
|
|
1078
|
+
const mapToObj3 = (map, mapValue, excludeValue) =>
|
|
1079
|
+
mapToObj(
|
|
1080
|
+
map,
|
|
1081
|
+
(childMap) => mapToObj2(childMap, mapValue, excludeValue),
|
|
1082
|
+
objIsEmpty,
|
|
1083
|
+
);
|
|
1084
|
+
const mapClone = (map, mapValue) => {
|
|
1085
|
+
const map2 = mapNew();
|
|
1086
|
+
collForEach(map, (value, key) => map2.set(key, mapValue?.(value) ?? value));
|
|
1087
|
+
return map2;
|
|
1088
|
+
};
|
|
1089
|
+
const mapClone2 = (map) => mapClone(map, mapClone);
|
|
1090
|
+
const mapClone3 = (map) => mapClone(map, mapClone2);
|
|
1091
|
+
const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
|
|
1092
|
+
ifNotUndefined(
|
|
1093
|
+
(ensureLeaf ? mapEnsure : mapGet)(
|
|
1094
|
+
node,
|
|
1095
|
+
path[p],
|
|
1096
|
+
p > arrayLength(path) - 2 ? ensureLeaf : mapNew,
|
|
1097
|
+
),
|
|
1098
|
+
(nodeOrLeaf) => {
|
|
1099
|
+
if (p > arrayLength(path) - 2) {
|
|
1100
|
+
if (pruneLeaf?.(nodeOrLeaf)) {
|
|
1101
|
+
mapSet(node, path[p]);
|
|
1102
|
+
}
|
|
1103
|
+
return nodeOrLeaf;
|
|
1104
|
+
}
|
|
1105
|
+
const leaf = visitTree(nodeOrLeaf, path, ensureLeaf, pruneLeaf, p + 1);
|
|
1106
|
+
if (collIsEmpty(nodeOrLeaf)) {
|
|
1107
|
+
mapSet(node, path[p]);
|
|
1108
|
+
}
|
|
1109
|
+
return leaf;
|
|
1110
|
+
},
|
|
1111
|
+
);
|
|
1112
|
+
|
|
1113
|
+
const setNew = (entryOrEntries) =>
|
|
1114
|
+
new Set(
|
|
1115
|
+
isArray(entryOrEntries) || isUndefined(entryOrEntries)
|
|
1116
|
+
? entryOrEntries
|
|
1117
|
+
: [entryOrEntries],
|
|
1118
|
+
);
|
|
1119
|
+
const setAdd = (set, value) => set?.add(value);
|
|
1120
|
+
|
|
1121
|
+
const INTEGER = /^\d+$/;
|
|
1122
|
+
const getPoolFunctions = () => {
|
|
1123
|
+
const pool = [];
|
|
1124
|
+
let nextId = 0;
|
|
1125
|
+
return [
|
|
1126
|
+
(reuse) => (reuse ? arrayShift(pool) : null) ?? EMPTY_STRING + nextId++,
|
|
1127
|
+
(id) => {
|
|
1128
|
+
if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
|
|
1129
|
+
arrayPush(pool, id);
|
|
1130
|
+
}
|
|
1131
|
+
},
|
|
1132
|
+
];
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
1136
|
+
const leaves = [];
|
|
1137
|
+
const deep = (node, p) =>
|
|
1138
|
+
p == arrayLength(path)
|
|
1139
|
+
? arrayPush(leaves, node)
|
|
1140
|
+
: path[p] === null
|
|
1141
|
+
? collForEach(node, (node2) => deep(node2, p + 1))
|
|
1142
|
+
: arrayForEach([path[p], null], (id) => deep(mapGet(node, id), p + 1));
|
|
1143
|
+
deep(deepIdSet, 0);
|
|
1144
|
+
return leaves;
|
|
1145
|
+
};
|
|
1146
|
+
const getListenerFunctions = (getThing) => {
|
|
1147
|
+
let thing;
|
|
1148
|
+
const [getId, releaseId] = getPoolFunctions();
|
|
1149
|
+
const allListeners = mapNew();
|
|
1150
|
+
const addListener = (
|
|
1151
|
+
listener,
|
|
1152
|
+
idSetNode,
|
|
1153
|
+
path,
|
|
1154
|
+
pathGetters = [],
|
|
1155
|
+
extraArgsGetter = () => [],
|
|
1156
|
+
) => {
|
|
1157
|
+
thing ??= getThing();
|
|
1158
|
+
const id = getId(1);
|
|
1159
|
+
mapSet(allListeners, id, [
|
|
1160
|
+
listener,
|
|
1161
|
+
idSetNode,
|
|
1162
|
+
path,
|
|
1163
|
+
pathGetters,
|
|
1164
|
+
extraArgsGetter,
|
|
1165
|
+
]);
|
|
1166
|
+
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
1167
|
+
return id;
|
|
1168
|
+
};
|
|
1169
|
+
const callListeners = (idSetNode, ids, ...extraArgs) =>
|
|
1170
|
+
arrayForEach(getWildcardedLeaves(idSetNode, ids), (set) =>
|
|
1171
|
+
collForEach(set, (id) =>
|
|
1172
|
+
mapGet(allListeners, id)[0](thing, ...(ids ?? []), ...extraArgs),
|
|
1173
|
+
),
|
|
1174
|
+
);
|
|
1175
|
+
const delListener = (id) =>
|
|
1176
|
+
ifNotUndefined(mapGet(allListeners, id), ([, idSetNode, idOrNulls]) => {
|
|
1177
|
+
visitTree(idSetNode, idOrNulls ?? [EMPTY_STRING], void 0, (idSet) => {
|
|
1178
|
+
collDel(idSet, id);
|
|
1179
|
+
return collIsEmpty(idSet) ? 1 : 0;
|
|
1180
|
+
});
|
|
1181
|
+
mapSet(allListeners, id);
|
|
1182
|
+
releaseId(id);
|
|
1183
|
+
return idOrNulls;
|
|
1184
|
+
});
|
|
1185
|
+
const callListener = (id) =>
|
|
1186
|
+
ifNotUndefined(
|
|
1187
|
+
mapGet(allListeners, id),
|
|
1188
|
+
([listener, , path = [], pathGetters, extraArgsGetter]) => {
|
|
1189
|
+
const callWithIds = (...ids) => {
|
|
1190
|
+
const index = arrayLength(ids);
|
|
1191
|
+
index == arrayLength(path)
|
|
1192
|
+
? listener(thing, ...ids, ...extraArgsGetter(ids))
|
|
1193
|
+
: isUndefined(path[index])
|
|
1194
|
+
? arrayForEach(pathGetters[index]?.(...ids) ?? [], (id2) =>
|
|
1195
|
+
callWithIds(...ids, id2),
|
|
1196
|
+
)
|
|
1197
|
+
: callWithIds(...ids, path[index]);
|
|
1198
|
+
};
|
|
1199
|
+
callWithIds();
|
|
1200
|
+
},
|
|
1201
|
+
);
|
|
1202
|
+
return [addListener, callListeners, delListener, callListener];
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
const pairNew = (value) => [value, value];
|
|
1206
|
+
const pairCollSize2 = (pair, func = collSize2) => func(pair[0]) + func(pair[1]);
|
|
1207
|
+
const pairNewMap = () => [mapNew(), mapNew()];
|
|
1208
|
+
const pairClone = (array) => [...array];
|
|
1209
|
+
const pairIsEqual = ([entry1, entry2]) => entry1 === entry2;
|
|
1210
|
+
|
|
1211
|
+
const defaultSorter = (sortKey1, sortKey2) =>
|
|
1212
|
+
(sortKey1 ?? 0) < (sortKey2 ?? 0) ? -1 : 1;
|
|
1213
|
+
|
|
1214
|
+
const validate = (obj, validateChild, onInvalidObj) => {
|
|
1215
|
+
if (isUndefined(obj) || !isObject(obj) || objIsEmpty(obj) || objFrozen(obj)) {
|
|
1216
|
+
onInvalidObj?.();
|
|
1217
|
+
return false;
|
|
1218
|
+
}
|
|
1219
|
+
objMap(obj, (child, id2) => {
|
|
1220
|
+
if (!validateChild(child, id2)) {
|
|
1221
|
+
objDel(obj, id2);
|
|
1222
|
+
}
|
|
1223
|
+
});
|
|
1224
|
+
return !objIsEmpty(obj);
|
|
1225
|
+
};
|
|
1226
|
+
const idsChanged = (changedIds, id2, addedOrRemoved) =>
|
|
1227
|
+
mapSet(
|
|
1228
|
+
changedIds,
|
|
1229
|
+
id2,
|
|
1230
|
+
mapGet(changedIds, id2) == -addedOrRemoved ? void 0 : addedOrRemoved,
|
|
1231
|
+
);
|
|
1232
|
+
const createStore = () => {
|
|
1233
|
+
let hasTablesSchema;
|
|
1234
|
+
let hasValuesSchema;
|
|
1235
|
+
let cellsTouched = false;
|
|
1236
|
+
let valuesTouched = false;
|
|
1237
|
+
let transactions = 0;
|
|
1238
|
+
const changedTableIds = mapNew();
|
|
1239
|
+
const changedTableCellIds = mapNew();
|
|
1240
|
+
const changedRowCount = mapNew();
|
|
1241
|
+
const changedRowIds = mapNew();
|
|
1242
|
+
const changedCellIds = mapNew();
|
|
1243
|
+
const changedCells = mapNew();
|
|
1244
|
+
const changedValueIds = mapNew();
|
|
1245
|
+
const changedValues = mapNew();
|
|
1246
|
+
const invalidCells = mapNew();
|
|
1247
|
+
const invalidValues = mapNew();
|
|
1248
|
+
const tablesSchemaMap = mapNew();
|
|
1249
|
+
const tablesSchemaRowCache = mapNew();
|
|
1250
|
+
const valuesSchemaMap = mapNew();
|
|
1251
|
+
const valuesDefaulted = mapNew();
|
|
1252
|
+
const valuesNonDefaulted = setNew();
|
|
1253
|
+
const tablePoolFunctions = mapNew();
|
|
1254
|
+
const tableCellIds = mapNew();
|
|
1255
|
+
const tablesMap = mapNew();
|
|
1256
|
+
const valuesMap = mapNew();
|
|
1257
|
+
const tablesListeners = pairNewMap();
|
|
1258
|
+
const tableIdsListeners = pairNewMap();
|
|
1259
|
+
const tableListeners = pairNewMap();
|
|
1260
|
+
const tableCellIdsListeners = pairNewMap();
|
|
1261
|
+
const rowCountListeners = pairNewMap();
|
|
1262
|
+
const rowIdsListeners = pairNewMap();
|
|
1263
|
+
const sortedRowIdsListeners = pairNewMap();
|
|
1264
|
+
const rowListeners = pairNewMap();
|
|
1265
|
+
const cellIdsListeners = pairNewMap();
|
|
1266
|
+
const cellListeners = pairNewMap();
|
|
1267
|
+
const invalidCellListeners = pairNewMap();
|
|
1268
|
+
const invalidValueListeners = pairNewMap();
|
|
1269
|
+
const valuesListeners = pairNewMap();
|
|
1270
|
+
const valueIdsListeners = pairNewMap();
|
|
1271
|
+
const valueListeners = pairNewMap();
|
|
1272
|
+
const startTransactionListeners = mapNew();
|
|
1273
|
+
const finishTransactionListeners = pairNewMap();
|
|
1274
|
+
const [addListener, callListeners, delListenerImpl, callListenerImpl] =
|
|
1275
|
+
getListenerFunctions(() => store);
|
|
1276
|
+
const validateTablesSchema = (tableSchema) =>
|
|
1277
|
+
validate(tableSchema, (tableSchema2) =>
|
|
1278
|
+
validate(tableSchema2, validateCellOrValueSchema),
|
|
1279
|
+
);
|
|
1280
|
+
const validateValuesSchema = (valuesSchema) =>
|
|
1281
|
+
validate(valuesSchema, validateCellOrValueSchema);
|
|
1282
|
+
const validateCellOrValueSchema = (schema) => {
|
|
1283
|
+
if (!validate(schema, (_child, id2) => arrayHas([TYPE, DEFAULT], id2))) {
|
|
1284
|
+
return false;
|
|
1285
|
+
}
|
|
1286
|
+
const type = schema[TYPE];
|
|
1287
|
+
if (!isTypeStringOrBoolean(type) && type != NUMBER) {
|
|
1288
|
+
return false;
|
|
1289
|
+
}
|
|
1290
|
+
if (getCellOrValueType(schema[DEFAULT]) != type) {
|
|
1291
|
+
objDel(schema, DEFAULT);
|
|
1292
|
+
}
|
|
1293
|
+
return true;
|
|
1294
|
+
};
|
|
1295
|
+
const validateTables = (tables) =>
|
|
1296
|
+
validate(tables, validateTable, cellInvalid);
|
|
1297
|
+
const validateTable = (table, tableId) =>
|
|
1298
|
+
(!hasTablesSchema ||
|
|
1299
|
+
collHas(tablesSchemaMap, tableId) ||
|
|
1300
|
+
cellInvalid(tableId)) &&
|
|
1301
|
+
validate(
|
|
1302
|
+
table,
|
|
1303
|
+
(row, rowId) => validateRow(tableId, rowId, row),
|
|
1304
|
+
() => cellInvalid(tableId),
|
|
1305
|
+
);
|
|
1306
|
+
const validateRow = (tableId, rowId, row, skipDefaults) =>
|
|
1307
|
+
validate(
|
|
1308
|
+
skipDefaults ? row : addDefaultsToRow(row, tableId, rowId),
|
|
1309
|
+
(cell, cellId) =>
|
|
1310
|
+
ifNotUndefined(
|
|
1311
|
+
getValidatedCell(tableId, rowId, cellId, cell),
|
|
1312
|
+
(validCell) => {
|
|
1313
|
+
row[cellId] = validCell;
|
|
1314
|
+
return true;
|
|
1315
|
+
},
|
|
1316
|
+
() => false,
|
|
1317
|
+
),
|
|
1318
|
+
() => cellInvalid(tableId, rowId),
|
|
1319
|
+
);
|
|
1320
|
+
const getValidatedCell = (tableId, rowId, cellId, cell) =>
|
|
1321
|
+
hasTablesSchema
|
|
1322
|
+
? ifNotUndefined(
|
|
1323
|
+
mapGet(mapGet(tablesSchemaMap, tableId), cellId),
|
|
1324
|
+
(cellSchema) =>
|
|
1325
|
+
getCellOrValueType(cell) != cellSchema[TYPE]
|
|
1326
|
+
? cellInvalid(tableId, rowId, cellId, cell, cellSchema[DEFAULT])
|
|
1327
|
+
: cell,
|
|
1328
|
+
() => cellInvalid(tableId, rowId, cellId, cell),
|
|
1329
|
+
)
|
|
1330
|
+
: isUndefined(getCellOrValueType(cell))
|
|
1331
|
+
? cellInvalid(tableId, rowId, cellId, cell)
|
|
1332
|
+
: cell;
|
|
1333
|
+
const validateValues = (values, skipDefaults) =>
|
|
1334
|
+
validate(
|
|
1335
|
+
skipDefaults ? values : addDefaultsToValues(values),
|
|
1336
|
+
(value, valueId) =>
|
|
1337
|
+
ifNotUndefined(
|
|
1338
|
+
getValidatedValue(valueId, value),
|
|
1339
|
+
(validValue) => {
|
|
1340
|
+
values[valueId] = validValue;
|
|
1341
|
+
return true;
|
|
1342
|
+
},
|
|
1343
|
+
() => false,
|
|
1344
|
+
),
|
|
1345
|
+
() => valueInvalid(),
|
|
1346
|
+
);
|
|
1347
|
+
const getValidatedValue = (valueId, value) =>
|
|
1348
|
+
hasValuesSchema
|
|
1349
|
+
? ifNotUndefined(
|
|
1350
|
+
mapGet(valuesSchemaMap, valueId),
|
|
1351
|
+
(valueSchema) =>
|
|
1352
|
+
getCellOrValueType(value) != valueSchema[TYPE]
|
|
1353
|
+
? valueInvalid(valueId, value, valueSchema[DEFAULT])
|
|
1354
|
+
: value,
|
|
1355
|
+
() => valueInvalid(valueId, value),
|
|
1356
|
+
)
|
|
1357
|
+
: isUndefined(getCellOrValueType(value))
|
|
1358
|
+
? valueInvalid(valueId, value)
|
|
1359
|
+
: value;
|
|
1360
|
+
const addDefaultsToRow = (row, tableId, rowId) => {
|
|
1361
|
+
ifNotUndefined(
|
|
1362
|
+
mapGet(tablesSchemaRowCache, tableId),
|
|
1363
|
+
([rowDefaulted, rowNonDefaulted]) => {
|
|
1364
|
+
collForEach(rowDefaulted, (cell, cellId) => {
|
|
1365
|
+
if (!objHas(row, cellId)) {
|
|
1366
|
+
row[cellId] = cell;
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
collForEach(rowNonDefaulted, (cellId) => {
|
|
1370
|
+
if (!objHas(row, cellId)) {
|
|
1371
|
+
cellInvalid(tableId, rowId, cellId);
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
},
|
|
1375
|
+
);
|
|
1376
|
+
return row;
|
|
1377
|
+
};
|
|
1378
|
+
const addDefaultsToValues = (values) => {
|
|
1379
|
+
if (hasValuesSchema) {
|
|
1380
|
+
collForEach(valuesDefaulted, (value, valueId) => {
|
|
1381
|
+
if (!objHas(values, valueId)) {
|
|
1382
|
+
values[valueId] = value;
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
collForEach(valuesNonDefaulted, (valueId) => {
|
|
1386
|
+
if (!objHas(values, valueId)) {
|
|
1387
|
+
valueInvalid(valueId);
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
return values;
|
|
1392
|
+
};
|
|
1393
|
+
const setValidTablesSchema = (tablesSchema) =>
|
|
1394
|
+
mapMatch(
|
|
1395
|
+
tablesSchemaMap,
|
|
1396
|
+
tablesSchema,
|
|
1397
|
+
(_tablesSchema, tableId, tableSchema) => {
|
|
1398
|
+
const rowDefaulted = mapNew();
|
|
1399
|
+
const rowNonDefaulted = setNew();
|
|
1400
|
+
mapMatch(
|
|
1401
|
+
mapEnsure(tablesSchemaMap, tableId, mapNew),
|
|
1402
|
+
tableSchema,
|
|
1403
|
+
(tableSchemaMap, cellId, cellSchema) => {
|
|
1404
|
+
mapSet(tableSchemaMap, cellId, cellSchema);
|
|
1405
|
+
ifNotUndefined(
|
|
1406
|
+
cellSchema[DEFAULT],
|
|
1407
|
+
(def) => mapSet(rowDefaulted, cellId, def),
|
|
1408
|
+
() => setAdd(rowNonDefaulted, cellId),
|
|
1409
|
+
);
|
|
1410
|
+
},
|
|
1411
|
+
);
|
|
1412
|
+
mapSet(tablesSchemaRowCache, tableId, [rowDefaulted, rowNonDefaulted]);
|
|
1413
|
+
},
|
|
1414
|
+
(_tablesSchema, tableId) => {
|
|
1415
|
+
mapSet(tablesSchemaMap, tableId);
|
|
1416
|
+
mapSet(tablesSchemaRowCache, tableId);
|
|
1417
|
+
},
|
|
1418
|
+
);
|
|
1419
|
+
const setValidValuesSchema = (valuesSchema) =>
|
|
1420
|
+
mapMatch(
|
|
1421
|
+
valuesSchemaMap,
|
|
1422
|
+
valuesSchema,
|
|
1423
|
+
(_valuesSchema, valueId, valueSchema) => {
|
|
1424
|
+
mapSet(valuesSchemaMap, valueId, valueSchema);
|
|
1425
|
+
ifNotUndefined(
|
|
1426
|
+
valueSchema[DEFAULT],
|
|
1427
|
+
(def) => mapSet(valuesDefaulted, valueId, def),
|
|
1428
|
+
() => setAdd(valuesNonDefaulted, valueId),
|
|
1429
|
+
);
|
|
1430
|
+
},
|
|
1431
|
+
(_valuesSchema, valueId) => {
|
|
1432
|
+
mapSet(valuesSchemaMap, valueId);
|
|
1433
|
+
mapSet(valuesDefaulted, valueId);
|
|
1434
|
+
collDel(valuesNonDefaulted, valueId);
|
|
1435
|
+
},
|
|
1436
|
+
);
|
|
1437
|
+
const setOrDelTables = (tables) =>
|
|
1438
|
+
objIsEmpty(tables) ? delTables() : setTables(tables);
|
|
1439
|
+
const setValidTables = (tables) =>
|
|
1440
|
+
mapMatch(
|
|
1441
|
+
tablesMap,
|
|
1442
|
+
tables,
|
|
1443
|
+
(_tables, tableId, table) => setValidTable(tableId, table),
|
|
1444
|
+
(_tables, tableId) => delValidTable(tableId),
|
|
1445
|
+
);
|
|
1446
|
+
const setValidTable = (tableId, table) =>
|
|
1447
|
+
mapMatch(
|
|
1448
|
+
mapEnsure(tablesMap, tableId, () => {
|
|
1449
|
+
tableIdsChanged(tableId, 1);
|
|
1450
|
+
mapSet(tablePoolFunctions, tableId, getPoolFunctions());
|
|
1451
|
+
mapSet(tableCellIds, tableId, mapNew());
|
|
1452
|
+
return mapNew();
|
|
1453
|
+
}),
|
|
1454
|
+
table,
|
|
1455
|
+
(tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
|
|
1456
|
+
(tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
|
|
1457
|
+
);
|
|
1458
|
+
const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
|
|
1459
|
+
mapMatch(
|
|
1460
|
+
mapEnsure(tableMap, rowId, () => {
|
|
1461
|
+
rowIdsChanged(tableId, rowId, 1);
|
|
1462
|
+
return mapNew();
|
|
1463
|
+
}),
|
|
1464
|
+
row,
|
|
1465
|
+
(rowMap, cellId, cell) =>
|
|
1466
|
+
setValidCell(tableId, rowId, rowMap, cellId, cell),
|
|
1467
|
+
(rowMap, cellId) =>
|
|
1468
|
+
delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
|
|
1469
|
+
);
|
|
1470
|
+
const setValidCell = (tableId, rowId, rowMap, cellId, cell) => {
|
|
1471
|
+
if (!collHas(rowMap, cellId)) {
|
|
1472
|
+
cellIdsChanged(tableId, rowId, cellId, 1);
|
|
1473
|
+
}
|
|
1474
|
+
const oldCell = mapGet(rowMap, cellId);
|
|
1475
|
+
if (cell !== oldCell) {
|
|
1476
|
+
cellChanged(tableId, rowId, cellId, oldCell, cell);
|
|
1477
|
+
mapSet(rowMap, cellId, cell);
|
|
1478
|
+
}
|
|
1479
|
+
};
|
|
1480
|
+
const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
|
|
1481
|
+
ifNotUndefined(
|
|
1482
|
+
mapGet(tableMap, rowId),
|
|
1483
|
+
(rowMap) => setValidCell(tableId, rowId, rowMap, cellId, validCell),
|
|
1484
|
+
() =>
|
|
1485
|
+
setValidRow(
|
|
1486
|
+
tableId,
|
|
1487
|
+
tableMap,
|
|
1488
|
+
rowId,
|
|
1489
|
+
addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
|
|
1490
|
+
),
|
|
1491
|
+
);
|
|
1492
|
+
const setOrDelValues = (values) =>
|
|
1493
|
+
objIsEmpty(values) ? delValues() : setValues(values);
|
|
1494
|
+
const setValidValues = (values) =>
|
|
1495
|
+
mapMatch(
|
|
1496
|
+
valuesMap,
|
|
1497
|
+
values,
|
|
1498
|
+
(_valuesMap, valueId, value) => setValidValue(valueId, value),
|
|
1499
|
+
(_valuesMap, valueId) => delValidValue(valueId),
|
|
1500
|
+
);
|
|
1501
|
+
const setValidValue = (valueId, value) => {
|
|
1502
|
+
if (!collHas(valuesMap, valueId)) {
|
|
1503
|
+
valueIdsChanged(valueId, 1);
|
|
1504
|
+
}
|
|
1505
|
+
const oldValue = mapGet(valuesMap, valueId);
|
|
1506
|
+
if (value !== oldValue) {
|
|
1507
|
+
valueChanged(valueId, oldValue, value);
|
|
1508
|
+
mapSet(valuesMap, valueId, value);
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
const getNewRowId = (tableId, reuse) => {
|
|
1512
|
+
const [getId] = mapGet(tablePoolFunctions, tableId);
|
|
1513
|
+
const rowId = getId(reuse);
|
|
1514
|
+
if (!collHas(mapGet(tablesMap, tableId), rowId)) {
|
|
1515
|
+
return rowId;
|
|
1516
|
+
}
|
|
1517
|
+
return getNewRowId(tableId, reuse);
|
|
1518
|
+
};
|
|
1519
|
+
const getOrCreateTable = (tableId) =>
|
|
1520
|
+
mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
|
|
1521
|
+
const delValidTable = (tableId) => setValidTable(tableId, {});
|
|
1522
|
+
const delValidRow = (tableId, tableMap, rowId) => {
|
|
1523
|
+
const [, releaseId] = mapGet(tablePoolFunctions, tableId);
|
|
1524
|
+
releaseId(rowId);
|
|
1525
|
+
setValidRow(tableId, tableMap, rowId, {}, true);
|
|
1526
|
+
};
|
|
1527
|
+
const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
|
|
1528
|
+
const defaultCell = mapGet(
|
|
1529
|
+
mapGet(tablesSchemaRowCache, tableId)?.[0],
|
|
1530
|
+
cellId,
|
|
1531
|
+
);
|
|
1532
|
+
if (!isUndefined(defaultCell) && !forceDel) {
|
|
1533
|
+
return setValidCell(tableId, rowId, row, cellId, defaultCell);
|
|
1534
|
+
}
|
|
1535
|
+
const delCell2 = (cellId2) => {
|
|
1536
|
+
cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
|
|
1537
|
+
cellIdsChanged(tableId, rowId, cellId2, -1);
|
|
1538
|
+
mapSet(row, cellId2);
|
|
1539
|
+
};
|
|
1540
|
+
isUndefined(defaultCell) ? delCell2(cellId) : mapForEach(row, delCell2);
|
|
1541
|
+
if (collIsEmpty(row)) {
|
|
1542
|
+
rowIdsChanged(tableId, rowId, -1);
|
|
1543
|
+
if (collIsEmpty(mapSet(table, rowId))) {
|
|
1544
|
+
tableIdsChanged(tableId, -1);
|
|
1545
|
+
mapSet(tablesMap, tableId);
|
|
1546
|
+
mapSet(tablePoolFunctions, tableId);
|
|
1547
|
+
mapSet(tableCellIds, tableId);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1551
|
+
const delValidValue = (valueId) => {
|
|
1552
|
+
const defaultValue = mapGet(valuesDefaulted, valueId);
|
|
1553
|
+
if (!isUndefined(defaultValue)) {
|
|
1554
|
+
return setValidValue(valueId, defaultValue);
|
|
1555
|
+
}
|
|
1556
|
+
valueChanged(valueId, mapGet(valuesMap, valueId));
|
|
1557
|
+
valueIdsChanged(valueId, -1);
|
|
1558
|
+
mapSet(valuesMap, valueId);
|
|
1559
|
+
};
|
|
1560
|
+
const tableIdsChanged = (tableId, addedOrRemoved) =>
|
|
1561
|
+
idsChanged(changedTableIds, tableId, addedOrRemoved);
|
|
1562
|
+
const rowIdsChanged = (tableId, rowId, addedOrRemoved) =>
|
|
1563
|
+
idsChanged(
|
|
1564
|
+
mapEnsure(changedRowIds, tableId, mapNew),
|
|
1565
|
+
rowId,
|
|
1566
|
+
addedOrRemoved,
|
|
1567
|
+
) &&
|
|
1568
|
+
mapSet(
|
|
1569
|
+
changedRowCount,
|
|
1570
|
+
tableId,
|
|
1571
|
+
mapEnsure(changedRowCount, tableId, () => 0) + addedOrRemoved,
|
|
1572
|
+
);
|
|
1573
|
+
const cellIdsChanged = (tableId, rowId, cellId, addedOrRemoved) => {
|
|
1574
|
+
const cellIds = mapGet(tableCellIds, tableId);
|
|
1575
|
+
const count = mapGet(cellIds, cellId) ?? 0;
|
|
1576
|
+
if (
|
|
1577
|
+
(count == 0 && addedOrRemoved == 1) ||
|
|
1578
|
+
(count == 1 && addedOrRemoved == -1)
|
|
1579
|
+
) {
|
|
1580
|
+
idsChanged(
|
|
1581
|
+
mapEnsure(changedTableCellIds, tableId, mapNew),
|
|
1582
|
+
cellId,
|
|
1583
|
+
addedOrRemoved,
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
mapSet(
|
|
1587
|
+
cellIds,
|
|
1588
|
+
cellId,
|
|
1589
|
+
count != -addedOrRemoved ? count + addedOrRemoved : null,
|
|
1590
|
+
);
|
|
1591
|
+
idsChanged(
|
|
1592
|
+
mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId, mapNew),
|
|
1593
|
+
cellId,
|
|
1594
|
+
addedOrRemoved,
|
|
1595
|
+
);
|
|
1596
|
+
};
|
|
1597
|
+
const cellChanged = (tableId, rowId, cellId, oldCell, newCell) =>
|
|
1598
|
+
(mapEnsure(
|
|
1599
|
+
mapEnsure(mapEnsure(changedCells, tableId, mapNew), rowId, mapNew),
|
|
1600
|
+
cellId,
|
|
1601
|
+
() => [oldCell, 0],
|
|
1602
|
+
)[1] = newCell);
|
|
1603
|
+
const valueIdsChanged = (valueId, addedOrRemoved) =>
|
|
1604
|
+
idsChanged(changedValueIds, valueId, addedOrRemoved);
|
|
1605
|
+
const valueChanged = (valueId, oldValue, newValue) =>
|
|
1606
|
+
(mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue);
|
|
1607
|
+
const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
|
|
1608
|
+
arrayPush(
|
|
1609
|
+
mapEnsure(
|
|
1610
|
+
mapEnsure(mapEnsure(invalidCells, tableId, mapNew), rowId, mapNew),
|
|
1611
|
+
cellId,
|
|
1612
|
+
() => [],
|
|
1613
|
+
),
|
|
1614
|
+
invalidCell,
|
|
1615
|
+
);
|
|
1616
|
+
return defaultedCell;
|
|
1617
|
+
};
|
|
1618
|
+
const valueInvalid = (valueId, invalidValue, defaultedValue) => {
|
|
1619
|
+
arrayPush(
|
|
1620
|
+
mapEnsure(invalidValues, valueId, () => []),
|
|
1621
|
+
invalidValue,
|
|
1622
|
+
);
|
|
1623
|
+
return defaultedValue;
|
|
1624
|
+
};
|
|
1625
|
+
const getCellChange = (tableId, rowId, cellId) =>
|
|
1626
|
+
ifNotUndefined(
|
|
1627
|
+
mapGet(mapGet(mapGet(changedCells, tableId), rowId), cellId),
|
|
1628
|
+
([oldCell, newCell]) => [true, oldCell, newCell],
|
|
1629
|
+
() => [false, ...pairNew(getCell(tableId, rowId, cellId))],
|
|
1630
|
+
);
|
|
1631
|
+
const getValueChange = (valueId) =>
|
|
1632
|
+
ifNotUndefined(
|
|
1633
|
+
mapGet(changedValues, valueId),
|
|
1634
|
+
([oldValue, newValue]) => [true, oldValue, newValue],
|
|
1635
|
+
() => [false, ...pairNew(getValue(valueId))],
|
|
1636
|
+
);
|
|
1637
|
+
const callInvalidCellListeners = (mutator) =>
|
|
1638
|
+
!collIsEmpty(invalidCells) && !collIsEmpty(invalidCellListeners[mutator])
|
|
1639
|
+
? collForEach(
|
|
1640
|
+
mutator ? mapClone3(invalidCells) : invalidCells,
|
|
1641
|
+
(rows, tableId) =>
|
|
1642
|
+
collForEach(rows, (cells, rowId) =>
|
|
1643
|
+
collForEach(cells, (invalidCell, cellId) =>
|
|
1644
|
+
callListeners(
|
|
1645
|
+
invalidCellListeners[mutator],
|
|
1646
|
+
[tableId, rowId, cellId],
|
|
1647
|
+
invalidCell,
|
|
1648
|
+
),
|
|
1649
|
+
),
|
|
1650
|
+
),
|
|
1651
|
+
)
|
|
1652
|
+
: 0;
|
|
1653
|
+
const callInvalidValueListeners = (mutator) =>
|
|
1654
|
+
!collIsEmpty(invalidValues) && !collIsEmpty(invalidValueListeners[mutator])
|
|
1655
|
+
? collForEach(
|
|
1656
|
+
mutator ? mapClone(invalidValues) : invalidValues,
|
|
1657
|
+
(invalidValue, valueId) =>
|
|
1658
|
+
callListeners(
|
|
1659
|
+
invalidValueListeners[mutator],
|
|
1660
|
+
[valueId],
|
|
1661
|
+
invalidValue,
|
|
1662
|
+
),
|
|
1663
|
+
)
|
|
1664
|
+
: 0;
|
|
1665
|
+
const callIdsListenersIfChanged = (listeners, changedIds, ids) => {
|
|
1666
|
+
if (!collIsEmpty(changedIds)) {
|
|
1667
|
+
callListeners(listeners, ids, () => mapToObj(changedIds));
|
|
1668
|
+
return 1;
|
|
1669
|
+
}
|
|
1670
|
+
};
|
|
1671
|
+
const callTabularListenersForChanges = (mutator) => {
|
|
1672
|
+
const emptySortedRowIdListeners = collIsEmpty(
|
|
1673
|
+
sortedRowIdsListeners[mutator],
|
|
1674
|
+
);
|
|
1675
|
+
const emptyIdListeners =
|
|
1676
|
+
collIsEmpty(cellIdsListeners[mutator]) &&
|
|
1677
|
+
collIsEmpty(tableCellIdsListeners[mutator]) &&
|
|
1678
|
+
collIsEmpty(rowCountListeners[mutator]) &&
|
|
1679
|
+
collIsEmpty(rowIdsListeners[mutator]) &&
|
|
1680
|
+
emptySortedRowIdListeners &&
|
|
1681
|
+
collIsEmpty(tableIdsListeners[mutator]);
|
|
1682
|
+
const emptyOtherListeners =
|
|
1683
|
+
collIsEmpty(cellListeners[mutator]) &&
|
|
1684
|
+
collIsEmpty(rowListeners[mutator]) &&
|
|
1685
|
+
collIsEmpty(tableListeners[mutator]) &&
|
|
1686
|
+
collIsEmpty(tablesListeners[mutator]);
|
|
1687
|
+
if (!emptyIdListeners || !emptyOtherListeners) {
|
|
1688
|
+
const changes = mutator
|
|
1689
|
+
? [
|
|
1690
|
+
mapClone(changedTableIds),
|
|
1691
|
+
mapClone2(changedTableCellIds),
|
|
1692
|
+
mapClone(changedRowCount),
|
|
1693
|
+
mapClone2(changedRowIds),
|
|
1694
|
+
mapClone3(changedCellIds),
|
|
1695
|
+
mapClone3(changedCells),
|
|
1696
|
+
]
|
|
1697
|
+
: [
|
|
1698
|
+
changedTableIds,
|
|
1699
|
+
changedTableCellIds,
|
|
1700
|
+
changedRowCount,
|
|
1701
|
+
changedRowIds,
|
|
1702
|
+
changedCellIds,
|
|
1703
|
+
changedCells,
|
|
1704
|
+
];
|
|
1705
|
+
if (!emptyIdListeners) {
|
|
1706
|
+
callIdsListenersIfChanged(tableIdsListeners[mutator], changes[0]);
|
|
1707
|
+
collForEach(changes[1], (changedIds, tableId) =>
|
|
1708
|
+
callIdsListenersIfChanged(
|
|
1709
|
+
tableCellIdsListeners[mutator],
|
|
1710
|
+
changedIds,
|
|
1711
|
+
[tableId],
|
|
1712
|
+
),
|
|
1713
|
+
);
|
|
1714
|
+
collForEach(changes[2], (changedCount, tableId) => {
|
|
1715
|
+
if (changedCount != 0) {
|
|
1716
|
+
callListeners(
|
|
1717
|
+
rowCountListeners[mutator],
|
|
1718
|
+
[tableId],
|
|
1719
|
+
getRowCount(tableId),
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
});
|
|
1723
|
+
const calledSortableTableIds = setNew();
|
|
1724
|
+
collForEach(changes[3], (changedIds, tableId) => {
|
|
1725
|
+
if (
|
|
1726
|
+
callIdsListenersIfChanged(rowIdsListeners[mutator], changedIds, [
|
|
1727
|
+
tableId,
|
|
1728
|
+
]) &&
|
|
1729
|
+
!emptySortedRowIdListeners
|
|
1730
|
+
) {
|
|
1731
|
+
callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
|
|
1732
|
+
setAdd(calledSortableTableIds, tableId);
|
|
1733
|
+
}
|
|
1734
|
+
});
|
|
1735
|
+
if (!emptySortedRowIdListeners) {
|
|
1736
|
+
collForEach(changes[5], (rows, tableId) => {
|
|
1737
|
+
if (!collHas(calledSortableTableIds, tableId)) {
|
|
1738
|
+
const sortableCellIds = setNew();
|
|
1739
|
+
collForEach(rows, (cells) =>
|
|
1740
|
+
collForEach(cells, ([oldCell, newCell], cellId) =>
|
|
1741
|
+
newCell !== oldCell
|
|
1742
|
+
? setAdd(sortableCellIds, cellId)
|
|
1743
|
+
: collDel(cells, cellId),
|
|
1744
|
+
),
|
|
1745
|
+
);
|
|
1746
|
+
collForEach(sortableCellIds, (cellId) =>
|
|
1747
|
+
callListeners(sortedRowIdsListeners[mutator], [
|
|
1748
|
+
tableId,
|
|
1749
|
+
cellId,
|
|
1750
|
+
]),
|
|
1751
|
+
);
|
|
1752
|
+
}
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
collForEach(changes[4], (rowCellIds, tableId) =>
|
|
1756
|
+
collForEach(rowCellIds, (changedIds, rowId) =>
|
|
1757
|
+
callIdsListenersIfChanged(cellIdsListeners[mutator], changedIds, [
|
|
1758
|
+
tableId,
|
|
1759
|
+
rowId,
|
|
1760
|
+
]),
|
|
1761
|
+
),
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
if (!emptyOtherListeners) {
|
|
1765
|
+
let tablesChanged;
|
|
1766
|
+
collForEach(changes[5], (rows, tableId) => {
|
|
1767
|
+
let tableChanged;
|
|
1768
|
+
collForEach(rows, (cells, rowId) => {
|
|
1769
|
+
let rowChanged;
|
|
1770
|
+
collForEach(cells, ([oldCell, newCell], cellId) => {
|
|
1771
|
+
if (newCell !== oldCell) {
|
|
1772
|
+
callListeners(
|
|
1773
|
+
cellListeners[mutator],
|
|
1774
|
+
[tableId, rowId, cellId],
|
|
1775
|
+
newCell,
|
|
1776
|
+
oldCell,
|
|
1777
|
+
getCellChange,
|
|
1778
|
+
);
|
|
1779
|
+
tablesChanged = tableChanged = rowChanged = 1;
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
if (rowChanged) {
|
|
1783
|
+
callListeners(
|
|
1784
|
+
rowListeners[mutator],
|
|
1785
|
+
[tableId, rowId],
|
|
1786
|
+
getCellChange,
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
if (tableChanged) {
|
|
1791
|
+
callListeners(tableListeners[mutator], [tableId], getCellChange);
|
|
1792
|
+
}
|
|
1793
|
+
});
|
|
1794
|
+
if (tablesChanged) {
|
|
1795
|
+
callListeners(tablesListeners[mutator], void 0, getCellChange);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
const callKeyedValuesListenersForChanges = (mutator) => {
|
|
1801
|
+
const emptyIdListeners = collIsEmpty(valueIdsListeners[mutator]);
|
|
1802
|
+
const emptyOtherListeners =
|
|
1803
|
+
collIsEmpty(valueListeners[mutator]) &&
|
|
1804
|
+
collIsEmpty(valuesListeners[mutator]);
|
|
1805
|
+
if (!emptyIdListeners || !emptyOtherListeners) {
|
|
1806
|
+
const changes = mutator
|
|
1807
|
+
? [mapClone(changedValueIds), mapClone(changedValues)]
|
|
1808
|
+
: [changedValueIds, changedValues];
|
|
1809
|
+
if (!emptyIdListeners) {
|
|
1810
|
+
callIdsListenersIfChanged(valueIdsListeners[mutator], changes[0]);
|
|
1811
|
+
}
|
|
1812
|
+
if (!emptyOtherListeners) {
|
|
1813
|
+
let valuesChanged;
|
|
1814
|
+
collForEach(changes[1], ([oldValue, newValue], valueId) => {
|
|
1815
|
+
if (newValue !== oldValue) {
|
|
1816
|
+
callListeners(
|
|
1817
|
+
valueListeners[mutator],
|
|
1818
|
+
[valueId],
|
|
1819
|
+
newValue,
|
|
1820
|
+
oldValue,
|
|
1821
|
+
getValueChange,
|
|
1822
|
+
);
|
|
1823
|
+
valuesChanged = 1;
|
|
1824
|
+
}
|
|
1825
|
+
});
|
|
1826
|
+
if (valuesChanged) {
|
|
1827
|
+
callListeners(valuesListeners[mutator], void 0, getValueChange);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
const fluentTransaction = (actions, ...args) => {
|
|
1833
|
+
transaction(() => actions(...arrayMap(args, id)));
|
|
1834
|
+
return store;
|
|
1835
|
+
};
|
|
1836
|
+
const getTransactionChanges = () => [
|
|
1837
|
+
mapToObj(
|
|
1838
|
+
changedCells,
|
|
1839
|
+
(table, tableId) =>
|
|
1840
|
+
mapGet(changedTableIds, tableId) === -1
|
|
1841
|
+
? null
|
|
1842
|
+
: mapToObj(
|
|
1843
|
+
table,
|
|
1844
|
+
(row, rowId) =>
|
|
1845
|
+
mapGet(mapGet(changedRowIds, tableId), rowId) === -1
|
|
1846
|
+
? null
|
|
1847
|
+
: mapToObj(
|
|
1848
|
+
row,
|
|
1849
|
+
([, newCell]) => newCell ?? null,
|
|
1850
|
+
(_, changedCell) => pairIsEqual(changedCell),
|
|
1851
|
+
),
|
|
1852
|
+
objIsEmpty,
|
|
1853
|
+
),
|
|
1854
|
+
objIsEmpty,
|
|
1855
|
+
),
|
|
1856
|
+
mapToObj(
|
|
1857
|
+
changedValues,
|
|
1858
|
+
([, newValue]) => newValue ?? null,
|
|
1859
|
+
(_, changedValue) => pairIsEqual(changedValue),
|
|
1860
|
+
),
|
|
1861
|
+
];
|
|
1862
|
+
const getTransactionLog = () => ({
|
|
1863
|
+
cellsTouched,
|
|
1864
|
+
valuesTouched,
|
|
1865
|
+
changedCells: mapToObj3(changedCells, pairClone, pairIsEqual),
|
|
1866
|
+
invalidCells: mapToObj3(invalidCells),
|
|
1867
|
+
changedValues: mapToObj(changedValues, pairClone, pairIsEqual),
|
|
1868
|
+
invalidValues: mapToObj(invalidValues),
|
|
1869
|
+
changedTableIds: mapToObj(changedTableIds),
|
|
1870
|
+
changedRowIds: mapToObj2(changedRowIds),
|
|
1871
|
+
changedCellIds: mapToObj3(changedCellIds),
|
|
1872
|
+
changedValueIds: mapToObj(changedValueIds),
|
|
1873
|
+
});
|
|
1874
|
+
const getContent = () => [getTables(), getValues()];
|
|
1875
|
+
const getTables = () => mapToObj3(tablesMap);
|
|
1876
|
+
const getTableIds = () => mapKeys(tablesMap);
|
|
1877
|
+
const getTable = (tableId) => mapToObj2(mapGet(tablesMap, id(tableId)));
|
|
1878
|
+
const getTableCellIds = (tableId) =>
|
|
1879
|
+
mapKeys(mapGet(tableCellIds, id(tableId)));
|
|
1880
|
+
const getRowCount = (tableId) => collSize(mapGet(tablesMap, id(tableId)));
|
|
1881
|
+
const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, id(tableId)));
|
|
1882
|
+
const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) =>
|
|
1883
|
+
arrayMap(
|
|
1884
|
+
arraySlice(
|
|
1885
|
+
arraySort(
|
|
1886
|
+
mapMap(mapGet(tablesMap, id(tableId)), (row, rowId) => [
|
|
1887
|
+
isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
|
|
1888
|
+
rowId,
|
|
1889
|
+
]),
|
|
1890
|
+
([cell1], [cell2]) =>
|
|
1891
|
+
defaultSorter(cell1, cell2) * (descending ? -1 : 1),
|
|
1892
|
+
),
|
|
1893
|
+
offset,
|
|
1894
|
+
isUndefined(limit) ? limit : offset + limit,
|
|
1895
|
+
),
|
|
1896
|
+
([, rowId]) => rowId,
|
|
1897
|
+
);
|
|
1898
|
+
const getRow = (tableId, rowId) =>
|
|
1899
|
+
mapToObj(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
|
|
1900
|
+
const getCellIds = (tableId, rowId) =>
|
|
1901
|
+
mapKeys(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
|
|
1902
|
+
const getCell = (tableId, rowId, cellId) =>
|
|
1903
|
+
mapGet(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
|
|
1904
|
+
const getValues = () => mapToObj(valuesMap);
|
|
1905
|
+
const getValueIds = () => mapKeys(valuesMap);
|
|
1906
|
+
const getValue = (valueId) => mapGet(valuesMap, id(valueId));
|
|
1907
|
+
const hasTables = () => !collIsEmpty(tablesMap);
|
|
1908
|
+
const hasTable = (tableId) => collHas(tablesMap, id(tableId));
|
|
1909
|
+
const hasTableCell = (tableId, cellId) =>
|
|
1910
|
+
collHas(mapGet(tableCellIds, id(tableId)), id(cellId));
|
|
1911
|
+
const hasRow = (tableId, rowId) =>
|
|
1912
|
+
collHas(mapGet(tablesMap, id(tableId)), id(rowId));
|
|
1913
|
+
const hasCell = (tableId, rowId, cellId) =>
|
|
1914
|
+
collHas(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
|
|
1915
|
+
const hasValues = () => !collIsEmpty(valuesMap);
|
|
1916
|
+
const hasValue = (valueId) => collHas(valuesMap, id(valueId));
|
|
1917
|
+
const getTablesJson = () => jsonString(tablesMap);
|
|
1918
|
+
const getValuesJson = () => jsonString(valuesMap);
|
|
1919
|
+
const getJson = () => jsonString([tablesMap, valuesMap]);
|
|
1920
|
+
const getTablesSchemaJson = () => jsonString(tablesSchemaMap);
|
|
1921
|
+
const getValuesSchemaJson = () => jsonString(valuesSchemaMap);
|
|
1922
|
+
const getSchemaJson = () => jsonString([tablesSchemaMap, valuesSchemaMap]);
|
|
1923
|
+
const setContent = ([tables, values]) =>
|
|
1924
|
+
fluentTransaction(() => {
|
|
1925
|
+
(objIsEmpty(tables) ? delTables : setTables)(tables);
|
|
1926
|
+
(objIsEmpty(values) ? delValues : setValues)(values);
|
|
1927
|
+
});
|
|
1928
|
+
const setTables = (tables) =>
|
|
1929
|
+
fluentTransaction(() =>
|
|
1930
|
+
validateTables(tables) ? setValidTables(tables) : 0,
|
|
1931
|
+
);
|
|
1932
|
+
const setTable = (tableId, table) =>
|
|
1933
|
+
fluentTransaction(
|
|
1934
|
+
(tableId2) =>
|
|
1935
|
+
validateTable(table, tableId2) ? setValidTable(tableId2, table) : 0,
|
|
1936
|
+
tableId,
|
|
1937
|
+
);
|
|
1938
|
+
const setRow = (tableId, rowId, row) =>
|
|
1939
|
+
fluentTransaction(
|
|
1940
|
+
(tableId2, rowId2) =>
|
|
1941
|
+
validateRow(tableId2, rowId2, row)
|
|
1942
|
+
? setValidRow(tableId2, getOrCreateTable(tableId2), rowId2, row)
|
|
1943
|
+
: 0,
|
|
1944
|
+
tableId,
|
|
1945
|
+
rowId,
|
|
1946
|
+
);
|
|
1947
|
+
const addRow = (tableId, row, reuseRowIds = true) =>
|
|
1948
|
+
transaction(() => {
|
|
1949
|
+
let rowId = void 0;
|
|
1950
|
+
if (validateRow(tableId, rowId, row)) {
|
|
1951
|
+
tableId = id(tableId);
|
|
1952
|
+
setValidRow(
|
|
1953
|
+
tableId,
|
|
1954
|
+
getOrCreateTable(tableId),
|
|
1955
|
+
(rowId = getNewRowId(tableId, reuseRowIds ? 1 : 0)),
|
|
1956
|
+
row,
|
|
1957
|
+
);
|
|
1958
|
+
}
|
|
1959
|
+
return rowId;
|
|
1960
|
+
});
|
|
1961
|
+
const setPartialRow = (tableId, rowId, partialRow) =>
|
|
1962
|
+
fluentTransaction(
|
|
1963
|
+
(tableId2, rowId2) => {
|
|
1964
|
+
if (validateRow(tableId2, rowId2, partialRow, 1)) {
|
|
1965
|
+
const table = getOrCreateTable(tableId2);
|
|
1966
|
+
objMap(partialRow, (cell, cellId) =>
|
|
1967
|
+
setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
},
|
|
1971
|
+
tableId,
|
|
1972
|
+
rowId,
|
|
1973
|
+
);
|
|
1974
|
+
const setCell = (tableId, rowId, cellId, cell) =>
|
|
1975
|
+
fluentTransaction(
|
|
1976
|
+
(tableId2, rowId2, cellId2) =>
|
|
1977
|
+
ifNotUndefined(
|
|
1978
|
+
getValidatedCell(
|
|
1979
|
+
tableId2,
|
|
1980
|
+
rowId2,
|
|
1981
|
+
cellId2,
|
|
1982
|
+
isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
|
|
1983
|
+
),
|
|
1984
|
+
(validCell) =>
|
|
1985
|
+
setCellIntoDefaultRow(
|
|
1986
|
+
tableId2,
|
|
1987
|
+
getOrCreateTable(tableId2),
|
|
1988
|
+
rowId2,
|
|
1989
|
+
cellId2,
|
|
1990
|
+
validCell,
|
|
1991
|
+
),
|
|
1992
|
+
),
|
|
1993
|
+
tableId,
|
|
1994
|
+
rowId,
|
|
1995
|
+
cellId,
|
|
1996
|
+
);
|
|
1997
|
+
const setValues = (values) =>
|
|
1998
|
+
fluentTransaction(() =>
|
|
1999
|
+
validateValues(values) ? setValidValues(values) : 0,
|
|
2000
|
+
);
|
|
2001
|
+
const setPartialValues = (partialValues) =>
|
|
2002
|
+
fluentTransaction(() =>
|
|
2003
|
+
validateValues(partialValues, 1)
|
|
2004
|
+
? objMap(partialValues, (value, valueId) =>
|
|
2005
|
+
setValidValue(valueId, value),
|
|
2006
|
+
)
|
|
2007
|
+
: 0,
|
|
2008
|
+
);
|
|
2009
|
+
const setValue = (valueId, value) =>
|
|
2010
|
+
fluentTransaction(
|
|
2011
|
+
(valueId2) =>
|
|
2012
|
+
ifNotUndefined(
|
|
2013
|
+
getValidatedValue(
|
|
2014
|
+
valueId2,
|
|
2015
|
+
isFunction(value) ? value(getValue(valueId2)) : value,
|
|
2016
|
+
),
|
|
2017
|
+
(validValue) => setValidValue(valueId2, validValue),
|
|
2018
|
+
),
|
|
2019
|
+
valueId,
|
|
2020
|
+
);
|
|
2021
|
+
const setTransactionChanges = (transactionChanges) =>
|
|
2022
|
+
fluentTransaction(() => {
|
|
2023
|
+
objMap(transactionChanges[0], (table, tableId) =>
|
|
2024
|
+
isUndefined(table)
|
|
2025
|
+
? delTable(tableId)
|
|
2026
|
+
: objMap(table, (row, rowId) =>
|
|
2027
|
+
isUndefined(row)
|
|
2028
|
+
? delRow(tableId, rowId)
|
|
2029
|
+
: objMap(row, (cell, cellId) =>
|
|
2030
|
+
setOrDelCell(store, tableId, rowId, cellId, cell),
|
|
2031
|
+
),
|
|
2032
|
+
),
|
|
2033
|
+
);
|
|
2034
|
+
objMap(transactionChanges[1], (value, valueId) =>
|
|
2035
|
+
setOrDelValue(store, valueId, value),
|
|
2036
|
+
);
|
|
2037
|
+
});
|
|
2038
|
+
const setTablesJson = (tablesJson) => {
|
|
2039
|
+
try {
|
|
2040
|
+
setOrDelTables(jsonParse(tablesJson));
|
|
2041
|
+
} catch {}
|
|
2042
|
+
return store;
|
|
2043
|
+
};
|
|
2044
|
+
const setValuesJson = (valuesJson) => {
|
|
2045
|
+
try {
|
|
2046
|
+
setOrDelValues(jsonParse(valuesJson));
|
|
2047
|
+
} catch {}
|
|
2048
|
+
return store;
|
|
2049
|
+
};
|
|
2050
|
+
const setJson = (tablesAndValuesJson) => {
|
|
2051
|
+
try {
|
|
2052
|
+
const [tables, values] = jsonParse(tablesAndValuesJson);
|
|
2053
|
+
setOrDelTables(tables);
|
|
2054
|
+
setOrDelValues(values);
|
|
2055
|
+
} catch {
|
|
2056
|
+
setTablesJson(tablesAndValuesJson);
|
|
2057
|
+
}
|
|
2058
|
+
return store;
|
|
2059
|
+
};
|
|
2060
|
+
const setTablesSchema = (tablesSchema) =>
|
|
2061
|
+
fluentTransaction(() => {
|
|
2062
|
+
if ((hasTablesSchema = validateTablesSchema(tablesSchema))) {
|
|
2063
|
+
setValidTablesSchema(tablesSchema);
|
|
2064
|
+
if (!collIsEmpty(tablesMap)) {
|
|
2065
|
+
const tables = getTables();
|
|
2066
|
+
delTables();
|
|
2067
|
+
setTables(tables);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
});
|
|
2071
|
+
const setValuesSchema = (valuesSchema) =>
|
|
2072
|
+
fluentTransaction(() => {
|
|
2073
|
+
if ((hasValuesSchema = validateValuesSchema(valuesSchema))) {
|
|
2074
|
+
const values = getValues();
|
|
2075
|
+
delValuesSchema();
|
|
2076
|
+
delValues();
|
|
2077
|
+
hasValuesSchema = true;
|
|
2078
|
+
setValidValuesSchema(valuesSchema);
|
|
2079
|
+
setValues(values);
|
|
2080
|
+
}
|
|
2081
|
+
});
|
|
2082
|
+
const setSchema = (tablesSchema, valuesSchema) =>
|
|
2083
|
+
fluentTransaction(() => {
|
|
2084
|
+
setTablesSchema(tablesSchema);
|
|
2085
|
+
setValuesSchema(valuesSchema);
|
|
2086
|
+
});
|
|
2087
|
+
const delTables = () => fluentTransaction(() => setValidTables({}));
|
|
2088
|
+
const delTable = (tableId) =>
|
|
2089
|
+
fluentTransaction(
|
|
2090
|
+
(tableId2) =>
|
|
2091
|
+
collHas(tablesMap, tableId2) ? delValidTable(tableId2) : 0,
|
|
2092
|
+
tableId,
|
|
2093
|
+
);
|
|
2094
|
+
const delRow = (tableId, rowId) =>
|
|
2095
|
+
fluentTransaction(
|
|
2096
|
+
(tableId2, rowId2) =>
|
|
2097
|
+
ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
|
|
2098
|
+
collHas(tableMap, rowId2)
|
|
2099
|
+
? delValidRow(tableId2, tableMap, rowId2)
|
|
2100
|
+
: 0,
|
|
2101
|
+
),
|
|
2102
|
+
tableId,
|
|
2103
|
+
rowId,
|
|
2104
|
+
);
|
|
2105
|
+
const delCell = (tableId, rowId, cellId, forceDel) =>
|
|
2106
|
+
fluentTransaction(
|
|
2107
|
+
(tableId2, rowId2, cellId2) =>
|
|
2108
|
+
ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
|
|
2109
|
+
ifNotUndefined(mapGet(tableMap, rowId2), (rowMap) =>
|
|
2110
|
+
collHas(rowMap, cellId2)
|
|
2111
|
+
? delValidCell(
|
|
2112
|
+
tableId2,
|
|
2113
|
+
tableMap,
|
|
2114
|
+
rowId2,
|
|
2115
|
+
rowMap,
|
|
2116
|
+
cellId2,
|
|
2117
|
+
forceDel,
|
|
2118
|
+
)
|
|
2119
|
+
: 0,
|
|
2120
|
+
),
|
|
2121
|
+
),
|
|
2122
|
+
tableId,
|
|
2123
|
+
rowId,
|
|
2124
|
+
cellId,
|
|
2125
|
+
);
|
|
2126
|
+
const delValues = () => fluentTransaction(() => setValidValues({}));
|
|
2127
|
+
const delValue = (valueId) =>
|
|
2128
|
+
fluentTransaction(
|
|
2129
|
+
(valueId2) =>
|
|
2130
|
+
collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
|
|
2131
|
+
valueId,
|
|
2132
|
+
);
|
|
2133
|
+
const delTablesSchema = () =>
|
|
2134
|
+
fluentTransaction(() => {
|
|
2135
|
+
setValidTablesSchema({});
|
|
2136
|
+
hasTablesSchema = false;
|
|
2137
|
+
});
|
|
2138
|
+
const delValuesSchema = () =>
|
|
2139
|
+
fluentTransaction(() => {
|
|
2140
|
+
setValidValuesSchema({});
|
|
2141
|
+
hasValuesSchema = false;
|
|
2142
|
+
});
|
|
2143
|
+
const delSchema = () =>
|
|
2144
|
+
fluentTransaction(() => {
|
|
2145
|
+
delTablesSchema();
|
|
2146
|
+
delValuesSchema();
|
|
2147
|
+
});
|
|
2148
|
+
const transaction = (actions, doRollback) => {
|
|
2149
|
+
if (transactions != -1) {
|
|
2150
|
+
startTransaction();
|
|
2151
|
+
const result = actions();
|
|
2152
|
+
finishTransaction(doRollback);
|
|
2153
|
+
return result;
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2156
|
+
const startTransaction = () => {
|
|
2157
|
+
if (transactions != -1) {
|
|
2158
|
+
transactions++;
|
|
2159
|
+
}
|
|
2160
|
+
if (transactions == 1) {
|
|
2161
|
+
callListeners(
|
|
2162
|
+
startTransactionListeners,
|
|
2163
|
+
void 0,
|
|
2164
|
+
getTransactionChanges,
|
|
2165
|
+
getTransactionLog,
|
|
2166
|
+
);
|
|
2167
|
+
}
|
|
2168
|
+
return store;
|
|
2169
|
+
};
|
|
2170
|
+
const finishTransaction = (doRollback) => {
|
|
2171
|
+
if (transactions > 0) {
|
|
2172
|
+
transactions--;
|
|
2173
|
+
if (transactions == 0) {
|
|
2174
|
+
cellsTouched = !collIsEmpty(changedCells);
|
|
2175
|
+
valuesTouched = !collIsEmpty(changedValues);
|
|
2176
|
+
transactions = 1;
|
|
2177
|
+
callInvalidCellListeners(1);
|
|
2178
|
+
if (cellsTouched) {
|
|
2179
|
+
callTabularListenersForChanges(1);
|
|
2180
|
+
}
|
|
2181
|
+
callInvalidValueListeners(1);
|
|
2182
|
+
if (valuesTouched) {
|
|
2183
|
+
callKeyedValuesListenersForChanges(1);
|
|
2184
|
+
}
|
|
2185
|
+
if (doRollback?.(getTransactionChanges, getTransactionLog)) {
|
|
2186
|
+
collForEach(changedCells, (table, tableId) =>
|
|
2187
|
+
collForEach(table, (row, rowId) =>
|
|
2188
|
+
collForEach(row, ([oldCell], cellId) =>
|
|
2189
|
+
setOrDelCell(store, tableId, rowId, cellId, oldCell),
|
|
2190
|
+
),
|
|
2191
|
+
),
|
|
2192
|
+
);
|
|
2193
|
+
collForEach(changedValues, ([oldValue], valueId) =>
|
|
2194
|
+
setOrDelValue(store, valueId, oldValue),
|
|
2195
|
+
);
|
|
2196
|
+
cellsTouched = valuesTouched = false;
|
|
2197
|
+
}
|
|
2198
|
+
callListeners(
|
|
2199
|
+
finishTransactionListeners[0],
|
|
2200
|
+
void 0,
|
|
2201
|
+
getTransactionChanges,
|
|
2202
|
+
getTransactionLog,
|
|
2203
|
+
);
|
|
2204
|
+
transactions = -1;
|
|
2205
|
+
callInvalidCellListeners(0);
|
|
2206
|
+
if (cellsTouched) {
|
|
2207
|
+
callTabularListenersForChanges(0);
|
|
2208
|
+
}
|
|
2209
|
+
callInvalidValueListeners(0);
|
|
2210
|
+
if (valuesTouched) {
|
|
2211
|
+
callKeyedValuesListenersForChanges(0);
|
|
2212
|
+
}
|
|
2213
|
+
callListeners(
|
|
2214
|
+
finishTransactionListeners[1],
|
|
2215
|
+
void 0,
|
|
2216
|
+
getTransactionChanges,
|
|
2217
|
+
getTransactionLog,
|
|
2218
|
+
);
|
|
2219
|
+
transactions = 0;
|
|
2220
|
+
cellsTouched = valuesTouched = false;
|
|
2221
|
+
arrayForEach(
|
|
2222
|
+
[
|
|
2223
|
+
changedTableIds,
|
|
2224
|
+
changedTableCellIds,
|
|
2225
|
+
changedRowCount,
|
|
2226
|
+
changedRowIds,
|
|
2227
|
+
changedCellIds,
|
|
2228
|
+
changedCells,
|
|
2229
|
+
invalidCells,
|
|
2230
|
+
changedValueIds,
|
|
2231
|
+
changedValues,
|
|
2232
|
+
invalidValues,
|
|
2233
|
+
],
|
|
2234
|
+
collClear,
|
|
2235
|
+
);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return store;
|
|
2239
|
+
};
|
|
2240
|
+
const forEachTable = (tableCallback) =>
|
|
2241
|
+
collForEach(tablesMap, (tableMap, tableId) =>
|
|
2242
|
+
tableCallback(tableId, (rowCallback) =>
|
|
2243
|
+
collForEach(tableMap, (rowMap, rowId) =>
|
|
2244
|
+
rowCallback(rowId, (cellCallback) =>
|
|
2245
|
+
mapForEach(rowMap, cellCallback),
|
|
2246
|
+
),
|
|
2247
|
+
),
|
|
2248
|
+
),
|
|
2249
|
+
);
|
|
2250
|
+
const forEachTableCell = (tableId, tableCellCallback) =>
|
|
2251
|
+
mapForEach(mapGet(tableCellIds, id(tableId)), tableCellCallback);
|
|
2252
|
+
const forEachRow = (tableId, rowCallback) =>
|
|
2253
|
+
collForEach(mapGet(tablesMap, id(tableId)), (rowMap, rowId) =>
|
|
2254
|
+
rowCallback(rowId, (cellCallback) => mapForEach(rowMap, cellCallback)),
|
|
2255
|
+
);
|
|
2256
|
+
const forEachCell = (tableId, rowId, cellCallback) =>
|
|
2257
|
+
mapForEach(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), cellCallback);
|
|
2258
|
+
const forEachValue = (valueCallback) => mapForEach(valuesMap, valueCallback);
|
|
2259
|
+
const addSortedRowIdsListener = (
|
|
2260
|
+
tableId,
|
|
2261
|
+
cellId,
|
|
2262
|
+
descending,
|
|
2263
|
+
offset,
|
|
2264
|
+
limit,
|
|
2265
|
+
listener,
|
|
2266
|
+
mutator,
|
|
2267
|
+
) => {
|
|
2268
|
+
let sortedRowIds = getSortedRowIds(
|
|
2269
|
+
tableId,
|
|
2270
|
+
cellId,
|
|
2271
|
+
descending,
|
|
2272
|
+
offset,
|
|
2273
|
+
limit,
|
|
2274
|
+
);
|
|
2275
|
+
return addListener(
|
|
2276
|
+
() => {
|
|
2277
|
+
const newSortedRowIds = getSortedRowIds(
|
|
2278
|
+
tableId,
|
|
2279
|
+
cellId,
|
|
2280
|
+
descending,
|
|
2281
|
+
offset,
|
|
2282
|
+
limit,
|
|
2283
|
+
);
|
|
2284
|
+
if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
|
|
2285
|
+
sortedRowIds = newSortedRowIds;
|
|
2286
|
+
listener(
|
|
2287
|
+
store,
|
|
2288
|
+
tableId,
|
|
2289
|
+
cellId,
|
|
2290
|
+
descending,
|
|
2291
|
+
offset,
|
|
2292
|
+
limit,
|
|
2293
|
+
sortedRowIds,
|
|
2294
|
+
);
|
|
2295
|
+
}
|
|
2296
|
+
},
|
|
2297
|
+
sortedRowIdsListeners[mutator ? 1 : 0],
|
|
2298
|
+
[tableId, cellId],
|
|
2299
|
+
[getTableIds],
|
|
2300
|
+
);
|
|
2301
|
+
};
|
|
2302
|
+
const addStartTransactionListener = (listener) =>
|
|
2303
|
+
addListener(listener, startTransactionListeners);
|
|
2304
|
+
const addWillFinishTransactionListener = (listener) =>
|
|
2305
|
+
addListener(listener, finishTransactionListeners[0]);
|
|
2306
|
+
const addDidFinishTransactionListener = (listener) =>
|
|
2307
|
+
addListener(listener, finishTransactionListeners[1]);
|
|
2308
|
+
const callListener = (listenerId) => {
|
|
2309
|
+
callListenerImpl(listenerId);
|
|
2310
|
+
return store;
|
|
2311
|
+
};
|
|
2312
|
+
const delListener = (listenerId) => {
|
|
2313
|
+
delListenerImpl(listenerId);
|
|
2314
|
+
return store;
|
|
2315
|
+
};
|
|
2316
|
+
const getListenerStats = () => ({
|
|
2317
|
+
tables: pairCollSize2(tablesListeners),
|
|
2318
|
+
tableIds: pairCollSize2(tableIdsListeners),
|
|
2319
|
+
tableCellIds: pairCollSize2(tableCellIdsListeners),
|
|
2320
|
+
table: pairCollSize2(tableListeners),
|
|
2321
|
+
rowCount: pairCollSize2(rowCountListeners),
|
|
2322
|
+
rowIds: pairCollSize2(rowIdsListeners),
|
|
2323
|
+
sortedRowIds: pairCollSize2(sortedRowIdsListeners),
|
|
2324
|
+
row: pairCollSize2(rowListeners, collSize3),
|
|
2325
|
+
cellIds: pairCollSize2(cellIdsListeners, collSize3),
|
|
2326
|
+
cell: pairCollSize2(cellListeners, collSize4),
|
|
2327
|
+
invalidCell: pairCollSize2(invalidCellListeners, collSize4),
|
|
2328
|
+
values: pairCollSize2(valuesListeners),
|
|
2329
|
+
valueIds: pairCollSize2(valueIdsListeners),
|
|
2330
|
+
value: pairCollSize2(valueListeners),
|
|
2331
|
+
invalidValue: pairCollSize2(invalidValueListeners),
|
|
2332
|
+
transaction:
|
|
2333
|
+
collSize2(startTransactionListeners) +
|
|
2334
|
+
pairCollSize2(finishTransactionListeners),
|
|
2335
|
+
});
|
|
2336
|
+
const store = {
|
|
2337
|
+
getContent,
|
|
2338
|
+
getTables,
|
|
2339
|
+
getTableIds,
|
|
2340
|
+
getTable,
|
|
2341
|
+
getTableCellIds,
|
|
2342
|
+
getRowCount,
|
|
2343
|
+
getRowIds,
|
|
2344
|
+
getSortedRowIds,
|
|
2345
|
+
getRow,
|
|
2346
|
+
getCellIds,
|
|
2347
|
+
getCell,
|
|
2348
|
+
getValues,
|
|
2349
|
+
getValueIds,
|
|
2350
|
+
getValue,
|
|
2351
|
+
hasTables,
|
|
2352
|
+
hasTable,
|
|
2353
|
+
hasTableCell,
|
|
2354
|
+
hasRow,
|
|
2355
|
+
hasCell,
|
|
2356
|
+
hasValues,
|
|
2357
|
+
hasValue,
|
|
2358
|
+
getTablesJson,
|
|
2359
|
+
getValuesJson,
|
|
2360
|
+
getJson,
|
|
2361
|
+
getTablesSchemaJson,
|
|
2362
|
+
getValuesSchemaJson,
|
|
2363
|
+
getSchemaJson,
|
|
2364
|
+
setContent,
|
|
2365
|
+
setTables,
|
|
2366
|
+
setTable,
|
|
2367
|
+
setRow,
|
|
2368
|
+
addRow,
|
|
2369
|
+
setPartialRow,
|
|
2370
|
+
setCell,
|
|
2371
|
+
setValues,
|
|
2372
|
+
setPartialValues,
|
|
2373
|
+
setValue,
|
|
2374
|
+
setTransactionChanges,
|
|
2375
|
+
setTablesJson,
|
|
2376
|
+
setValuesJson,
|
|
2377
|
+
setJson,
|
|
2378
|
+
setTablesSchema,
|
|
2379
|
+
setValuesSchema,
|
|
2380
|
+
setSchema,
|
|
2381
|
+
delTables,
|
|
2382
|
+
delTable,
|
|
2383
|
+
delRow,
|
|
2384
|
+
delCell,
|
|
2385
|
+
delValues,
|
|
2386
|
+
delValue,
|
|
2387
|
+
delTablesSchema,
|
|
2388
|
+
delValuesSchema,
|
|
2389
|
+
delSchema,
|
|
2390
|
+
transaction,
|
|
2391
|
+
startTransaction,
|
|
2392
|
+
finishTransaction,
|
|
2393
|
+
forEachTable,
|
|
2394
|
+
forEachTableCell,
|
|
2395
|
+
forEachRow,
|
|
2396
|
+
forEachCell,
|
|
2397
|
+
forEachValue,
|
|
2398
|
+
addSortedRowIdsListener,
|
|
2399
|
+
addStartTransactionListener,
|
|
2400
|
+
addWillFinishTransactionListener,
|
|
2401
|
+
addDidFinishTransactionListener,
|
|
2402
|
+
callListener,
|
|
2403
|
+
delListener,
|
|
2404
|
+
getListenerStats,
|
|
2405
|
+
createStore,
|
|
2406
|
+
};
|
|
2407
|
+
objMap(
|
|
2408
|
+
{
|
|
2409
|
+
[TABLES]: [0, tablesListeners],
|
|
2410
|
+
[TABLE_IDS]: [0, tableIdsListeners],
|
|
2411
|
+
[TABLE]: [1, tableListeners, [getTableIds]],
|
|
2412
|
+
[TABLE + CELL_IDS]: [1, tableCellIdsListeners, [getTableIds]],
|
|
2413
|
+
[ROW_COUNT]: [1, rowCountListeners, [getTableIds]],
|
|
2414
|
+
[ROW_IDS]: [1, rowIdsListeners, [getTableIds]],
|
|
2415
|
+
[ROW]: [2, rowListeners, [getTableIds, getRowIds]],
|
|
2416
|
+
[CELL_IDS]: [2, cellIdsListeners, [getTableIds, getRowIds]],
|
|
2417
|
+
[CELL]: [
|
|
2418
|
+
3,
|
|
2419
|
+
cellListeners,
|
|
2420
|
+
[getTableIds, getRowIds, getCellIds],
|
|
2421
|
+
(ids) => pairNew(getCell(...ids)),
|
|
2422
|
+
],
|
|
2423
|
+
InvalidCell: [3, invalidCellListeners],
|
|
2424
|
+
[VALUES]: [0, valuesListeners],
|
|
2425
|
+
[VALUE_IDS]: [0, valueIdsListeners],
|
|
2426
|
+
[VALUE]: [
|
|
2427
|
+
1,
|
|
2428
|
+
valueListeners,
|
|
2429
|
+
[getValueIds],
|
|
2430
|
+
(ids) => pairNew(getValue(ids[0])),
|
|
2431
|
+
],
|
|
2432
|
+
InvalidValue: [1, invalidValueListeners],
|
|
2433
|
+
},
|
|
2434
|
+
([argumentCount, idSetNode, pathGetters, extraArgsGetter], listenable) => {
|
|
2435
|
+
store[ADD + listenable + LISTENER] = (...args) =>
|
|
2436
|
+
addListener(
|
|
2437
|
+
args[argumentCount],
|
|
2438
|
+
idSetNode[args[argumentCount + 1] ? 1 : 0],
|
|
2439
|
+
argumentCount > 0 ? arraySlice(args, 0, argumentCount) : void 0,
|
|
2440
|
+
pathGetters,
|
|
2441
|
+
extraArgsGetter,
|
|
2442
|
+
);
|
|
2443
|
+
},
|
|
2444
|
+
);
|
|
2445
|
+
return objFreeze(store);
|
|
2446
|
+
};
|
|
2447
|
+
|
|
2448
|
+
const App = ({position = 'right', open = false}) => {
|
|
2449
|
+
const s = useCreateStore(createStore);
|
|
2450
|
+
const index = POSITIONS.indexOf(position);
|
|
2451
|
+
useCreatePersister(
|
|
2452
|
+
s,
|
|
2453
|
+
(s2) => createSessionPersister(s2, UNIQUE_ID),
|
|
2454
|
+
void 0,
|
|
2455
|
+
async (persister) => {
|
|
2456
|
+
await persister.load(void 0, {
|
|
2457
|
+
position: index == -1 ? 1 : index,
|
|
2458
|
+
open: !!open,
|
|
2459
|
+
});
|
|
2460
|
+
await persister.startAutoSave();
|
|
2461
|
+
},
|
|
2462
|
+
);
|
|
2463
|
+
return /* @__PURE__ */ createElement(
|
|
2464
|
+
React.Fragment,
|
|
2465
|
+
null,
|
|
2466
|
+
/* @__PURE__ */ createElement(
|
|
2467
|
+
'aside',
|
|
2468
|
+
{id: UNIQUE_ID},
|
|
2469
|
+
/* @__PURE__ */ createElement(Nub, {s}),
|
|
2470
|
+
/* @__PURE__ */ createElement(Panel, {s}),
|
|
2471
|
+
),
|
|
2472
|
+
/* @__PURE__ */ createElement('style', null, APP_STYLESHEET),
|
|
2473
|
+
);
|
|
2474
|
+
};
|
|
2475
|
+
|
|
2476
|
+
const StoreInspector = (props) =>
|
|
2477
|
+
/* @__PURE__ */ createElement(App, {...props});
|
|
416
2478
|
|
|
417
2479
|
export {
|
|
418
2480
|
EditableCellView,
|
|
@@ -420,6 +2482,8 @@ export {
|
|
|
420
2482
|
ResultSortedTableInHtmlTable,
|
|
421
2483
|
ResultTableInHtmlTable,
|
|
422
2484
|
SortedTableInHtmlTable,
|
|
2485
|
+
SortedTablePaginator,
|
|
2486
|
+
StoreInspector,
|
|
423
2487
|
TableInHtmlTable,
|
|
424
2488
|
ValuesInHtmlTable,
|
|
425
2489
|
};
|