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.
Files changed (150) hide show
  1. package/lib/checkpoints.js +1 -1
  2. package/lib/checkpoints.js.gz +0 -0
  3. package/lib/cjs/checkpoints.cjs +1 -1
  4. package/lib/cjs/checkpoints.cjs.gz +0 -0
  5. package/lib/cjs/common.cjs +1 -1
  6. package/lib/cjs/common.cjs.gz +0 -0
  7. package/lib/cjs/indexes.cjs +1 -1
  8. package/lib/cjs/indexes.cjs.gz +0 -0
  9. package/lib/cjs/metrics.cjs +1 -1
  10. package/lib/cjs/metrics.cjs.gz +0 -0
  11. package/lib/cjs/queries.cjs +1 -1
  12. package/lib/cjs/queries.cjs.gz +0 -0
  13. package/lib/cjs/relationships.cjs +1 -1
  14. package/lib/cjs/relationships.cjs.gz +0 -0
  15. package/lib/cjs/store.cjs +1 -1
  16. package/lib/cjs/store.cjs.gz +0 -0
  17. package/lib/cjs/tinybase.cjs +1 -1
  18. package/lib/cjs/tinybase.cjs.gz +0 -0
  19. package/lib/cjs/ui-react-dom-debug.cjs +1 -0
  20. package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
  21. package/lib/cjs/ui-react-dom.cjs +1 -1
  22. package/lib/cjs/ui-react-dom.cjs.gz +0 -0
  23. package/lib/cjs/ui-react.cjs +1 -1
  24. package/lib/cjs/ui-react.cjs.gz +0 -0
  25. package/lib/cjs-es6/checkpoints.cjs +1 -1
  26. package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
  27. package/lib/cjs-es6/common.cjs +1 -1
  28. package/lib/cjs-es6/common.cjs.gz +0 -0
  29. package/lib/cjs-es6/indexes.cjs +1 -1
  30. package/lib/cjs-es6/indexes.cjs.gz +0 -0
  31. package/lib/cjs-es6/metrics.cjs +1 -1
  32. package/lib/cjs-es6/metrics.cjs.gz +0 -0
  33. package/lib/cjs-es6/queries.cjs +1 -1
  34. package/lib/cjs-es6/queries.cjs.gz +0 -0
  35. package/lib/cjs-es6/relationships.cjs +1 -1
  36. package/lib/cjs-es6/relationships.cjs.gz +0 -0
  37. package/lib/cjs-es6/store.cjs +1 -1
  38. package/lib/cjs-es6/store.cjs.gz +0 -0
  39. package/lib/cjs-es6/tinybase.cjs +1 -1
  40. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  41. package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -0
  42. package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
  43. package/lib/cjs-es6/ui-react-dom.cjs +1 -1
  44. package/lib/cjs-es6/ui-react-dom.cjs.gz +0 -0
  45. package/lib/cjs-es6/ui-react.cjs +1 -1
  46. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  47. package/lib/common.js +1 -1
  48. package/lib/common.js.gz +0 -0
  49. package/lib/debug/checkpoints.js +1 -1
  50. package/lib/debug/common.js +2 -1
  51. package/lib/debug/indexes.js +3 -2
  52. package/lib/debug/metrics.js +1 -1
  53. package/lib/debug/queries.js +3 -1
  54. package/lib/debug/relationships.js +1 -1
  55. package/lib/debug/store.js +32 -6
  56. package/lib/debug/tinybase.js +33 -6
  57. package/lib/debug/ui-react-dom.js +2143 -79
  58. package/lib/debug/ui-react.js +85 -25
  59. package/lib/es6/checkpoints.js +1 -1
  60. package/lib/es6/checkpoints.js.gz +0 -0
  61. package/lib/es6/common.js +1 -1
  62. package/lib/es6/common.js.gz +0 -0
  63. package/lib/es6/indexes.js +1 -1
  64. package/lib/es6/indexes.js.gz +0 -0
  65. package/lib/es6/metrics.js +1 -1
  66. package/lib/es6/metrics.js.gz +0 -0
  67. package/lib/es6/queries.js +1 -1
  68. package/lib/es6/queries.js.gz +0 -0
  69. package/lib/es6/relationships.js +1 -1
  70. package/lib/es6/relationships.js.gz +0 -0
  71. package/lib/es6/store.js +1 -1
  72. package/lib/es6/store.js.gz +0 -0
  73. package/lib/es6/tinybase.js +1 -1
  74. package/lib/es6/tinybase.js.gz +0 -0
  75. package/lib/es6/ui-react-dom-debug.js +1 -0
  76. package/lib/es6/ui-react-dom-debug.js.gz +0 -0
  77. package/lib/es6/ui-react-dom.js +1 -1
  78. package/lib/es6/ui-react-dom.js.gz +0 -0
  79. package/lib/es6/ui-react.js +1 -1
  80. package/lib/es6/ui-react.js.gz +0 -0
  81. package/lib/indexes.js +1 -1
  82. package/lib/indexes.js.gz +0 -0
  83. package/lib/metrics.js +1 -1
  84. package/lib/metrics.js.gz +0 -0
  85. package/lib/queries.js +1 -1
  86. package/lib/queries.js.gz +0 -0
  87. package/lib/relationships.js +1 -1
  88. package/lib/relationships.js.gz +0 -0
  89. package/lib/store.js +1 -1
  90. package/lib/store.js.gz +0 -0
  91. package/lib/tinybase.js +1 -1
  92. package/lib/tinybase.js.gz +0 -0
  93. package/lib/types/queries.d.ts +204 -19
  94. package/lib/types/store.d.ts +155 -0
  95. package/lib/types/ui-react-dom.d.ts +278 -18
  96. package/lib/types/ui-react.d.ts +532 -1
  97. package/lib/types/with-schemas/queries.d.ts +229 -21
  98. package/lib/types/with-schemas/store.d.ts +188 -0
  99. package/lib/types/with-schemas/ui-react-dom.d.ts +278 -18
  100. package/lib/types/with-schemas/ui-react.d.ts +576 -2
  101. package/lib/ui-react-dom.js +1 -1
  102. package/lib/ui-react-dom.js.gz +0 -0
  103. package/lib/ui-react.js +1 -1
  104. package/lib/ui-react.js.gz +0 -0
  105. package/lib/umd/checkpoints.js +1 -1
  106. package/lib/umd/checkpoints.js.gz +0 -0
  107. package/lib/umd/common.js +1 -1
  108. package/lib/umd/common.js.gz +0 -0
  109. package/lib/umd/indexes.js +1 -1
  110. package/lib/umd/indexes.js.gz +0 -0
  111. package/lib/umd/metrics.js +1 -1
  112. package/lib/umd/metrics.js.gz +0 -0
  113. package/lib/umd/queries.js +1 -1
  114. package/lib/umd/queries.js.gz +0 -0
  115. package/lib/umd/relationships.js +1 -1
  116. package/lib/umd/relationships.js.gz +0 -0
  117. package/lib/umd/store.js +1 -1
  118. package/lib/umd/store.js.gz +0 -0
  119. package/lib/umd/tinybase.js +1 -1
  120. package/lib/umd/tinybase.js.gz +0 -0
  121. package/lib/umd/ui-react-dom-debug.js +1 -0
  122. package/lib/umd/ui-react-dom-debug.js.gz +0 -0
  123. package/lib/umd/ui-react-dom.js +1 -1
  124. package/lib/umd/ui-react-dom.js.gz +0 -0
  125. package/lib/umd/ui-react.js +1 -1
  126. package/lib/umd/ui-react.js.gz +0 -0
  127. package/lib/umd-es6/checkpoints.js +1 -1
  128. package/lib/umd-es6/checkpoints.js.gz +0 -0
  129. package/lib/umd-es6/common.js +1 -1
  130. package/lib/umd-es6/common.js.gz +0 -0
  131. package/lib/umd-es6/indexes.js +1 -1
  132. package/lib/umd-es6/indexes.js.gz +0 -0
  133. package/lib/umd-es6/metrics.js +1 -1
  134. package/lib/umd-es6/metrics.js.gz +0 -0
  135. package/lib/umd-es6/queries.js +1 -1
  136. package/lib/umd-es6/queries.js.gz +0 -0
  137. package/lib/umd-es6/relationships.js +1 -1
  138. package/lib/umd-es6/relationships.js.gz +0 -0
  139. package/lib/umd-es6/store.js +1 -1
  140. package/lib/umd-es6/store.js.gz +0 -0
  141. package/lib/umd-es6/tinybase.js +1 -1
  142. package/lib/umd-es6/tinybase.js.gz +0 -0
  143. package/lib/umd-es6/ui-react-dom-debug.js +1 -0
  144. package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
  145. package/lib/umd-es6/ui-react-dom.js +1 -1
  146. package/lib/umd-es6/ui-react-dom.js.gz +0 -0
  147. package/lib/umd-es6/ui-react.js +1 -1
  148. package/lib/umd-es6/ui-react.js.gz +0 -0
  149. package/package.json +10 -9
  150. 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
- useValue,
15
- useSetValueCallback,
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 getCellOrValueType = (cell) => {
36
- const type = getTypeOf(cell);
37
- return isTypeStringOrBoolean(type) || (type == NUMBER && isFiniteNumber(cell))
38
- ? type
39
- : void 0;
40
- };
41
- const getTypeCase = (type, stringCase, numberCase, booleanCase) =>
42
- type == STRING ? stringCase : type == NUMBER ? numberCase : booleanCase;
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 {createContext, useContext} = React;
52
- createContext([]);
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 {createElement, useCallback, useMemo, useState} = React;
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 sortedClassName = (sorting, cellId) =>
63
- isUndefined(sorting)
64
- ? void 0
65
- : sorting[0] != cellId
66
- ? void 0
67
- : `sorted ${sorting[1] ? 'de' : 'a'}scending`;
68
- const HtmlHeaderTh = ({
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
- sorting,
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
- !isUndefined(onClick),
312
+ onClick,
81
313
  ),
82
- className: sortedClassName(sorting, cellId),
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
- storeTableIdOrQueriesQueryId,
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(HtmlHeaderTh, {
131
- sorting,
377
+ : /* @__PURE__ */ createElement(HtmlHeader, {
378
+ sort: sortAndOffset ?? [],
132
379
  label: 'Id',
133
- onClick: onHeaderThClick,
380
+ onClick: handleSort,
134
381
  }),
135
382
  objMap(customCellConfigurations, ({label}, cellId) =>
136
- /* @__PURE__ */ createElement(HtmlHeaderTh, {
383
+ /* @__PURE__ */ createElement(HtmlHeader, {
137
384
  key: cellId,
138
385
  cellId,
139
386
  label,
140
- sorting,
141
- onClick: onHeaderThClick,
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
- ...storeTableIdOrQueriesQueryId,
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
- storeTableIdOrQueriesQueryId: useMemo(
269
- () => ({store, tableId}),
270
- [store, tableId],
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 [sorting, setSorting] = useState([cellId, descending ? true : false]);
288
- const handleHeaderThClick = useCallbackOrUndefined(
289
- (cellId2) =>
290
- setSorting([cellId2, cellId2 == sorting[0] ? !sorting[1] : false]),
291
- [sorting],
292
- sortOnClick,
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
- storeTableIdOrQueriesQueryId: useMemo(
297
- () => ({store, tableId}),
298
- [store, tableId],
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
- defaultCellComponent: editable ? EditableCellView : CellView,
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
- storeTableIdOrQueriesQueryId: useMemo(
360
- () => ({queries, queryId}),
361
- [queries, queryId],
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 [sorting, setSorting] = useState([cellId, descending ? true : false]);
378
- const handleHeaderThClick = useCallbackOrUndefined(
379
- (cellId2) =>
380
- setSorting([cellId2, cellId2 == sorting[0] ? !sorting[1] : false]),
381
- [sorting],
382
- sortOnClick,
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
- storeTableIdOrQueriesQueryId: useMemo(
387
- () => ({queries, queryId}),
388
- [queries, queryId],
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
- defaultCellComponent: ResultCellView,
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
  };