wenay-react2 1.0.20 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +383 -382
- package/lib/common/api.d.ts +28 -0
- package/lib/common/api.js +41 -16
- package/lib/common/src/components/Buttons/MiniButton.d.ts +1 -0
- package/lib/common/src/components/Buttons/MiniButton.js +2 -2
- package/lib/common/src/components/Dnd/DraggableOutlineDiv.d.ts +1 -0
- package/lib/common/src/components/Dnd/DraggableOutlineDiv.js +7 -6
- package/lib/common/src/components/Dnd/RNDFunc.js +28 -17
- package/lib/common/src/components/Dnd/RNDFunc3.d.ts +27 -17
- package/lib/common/src/components/Dnd/RNDFunc3.js +107 -105
- package/lib/common/src/components/Dnd/Resizable.js +3 -3
- package/lib/common/src/components/Menu/RightMenu.js +11 -17
- package/lib/common/src/components/Menu/StickerMenu.js +42 -28
- package/lib/common/src/components/Menu/index.d.ts +1 -1
- package/lib/common/src/components/Menu/index.js +1 -1
- package/lib/common/src/components/Modal/LeftModal.d.ts +14 -12
- package/lib/common/src/components/Modal/LeftModal.js +30 -16
- package/lib/common/src/components/Modal/Modal.d.ts +26 -12
- package/lib/common/src/components/Modal/Modal.js +66 -89
- package/lib/common/src/components/Modal/ModalContextProvider.d.ts +20 -3
- package/lib/common/src/components/Modal/ModalContextProvider.js +35 -8
- package/lib/common/src/components/MyResizeObserver.js +15 -18
- package/lib/common/src/components/Other.js +3 -2
- package/lib/common/src/components/Parameters.js +7 -6
- package/lib/common/src/components/ParametersEngine.js +25 -54
- package/lib/common/src/grid/agGrid4/agGrid4.d.ts +53 -0
- package/lib/common/src/grid/agGrid4/agGrid4.js +132 -0
- package/lib/common/src/grid/agGrid4/core.d.ts +56 -0
- package/lib/common/src/grid/agGrid4/core.js +127 -0
- package/lib/common/src/grid/agGrid4/index.d.ts +6 -0
- package/lib/common/src/grid/agGrid4/index.js +3 -0
- package/lib/common/src/grid/agGrid4/theme.d.ts +7 -0
- package/lib/common/src/grid/agGrid4/theme.js +18 -0
- package/lib/common/src/hooks/useAddDownAnyKey.d.ts +21 -2
- package/lib/common/src/hooks/useAddDownAnyKey.js +46 -8
- package/lib/common/src/hooks/useDraggable.d.ts +20 -2
- package/lib/common/src/hooks/useDraggable.js +146 -115
- package/lib/common/src/hooks/useOutside.d.ts +24 -4
- package/lib/common/src/hooks/useOutside.js +76 -27
- package/lib/common/src/logs/logs.d.ts +5 -2
- package/lib/common/src/logs/logs.js +15 -31
- package/lib/common/src/logs/logs3.d.ts +9 -9
- package/lib/common/src/logs/logs3.js +47 -38
- package/lib/common/src/logs/miniLogs.d.ts +3 -3
- package/lib/common/src/logs/miniLogs.js +28 -36
- package/lib/common/src/menu/menu.d.ts +18 -18
- package/lib/common/src/menu/menu.js +48 -24
- package/lib/common/src/menu/menuMouse.js +4 -1
- package/lib/common/src/menu/menuR.d.ts +2 -2
- package/lib/common/src/menu/menuR.js +34 -34
- package/lib/common/src/myChart/1/myChart.d.ts +5 -5
- package/lib/common/src/myChart/1/myChart.js +58 -47
- package/lib/common/src/myChart/1/myChartTest.js +8 -4
- package/lib/common/src/myChart/chartEngine/chartEngineReact.d.ts +24 -27
- package/lib/common/src/myChart/chartEngine/chartEngineReact.js +166 -117
- package/lib/common/src/styles/styleGrid.d.ts +2 -1
- package/lib/common/src/styles/styleGrid.js +10 -12
- package/lib/common/src/styles/tokens.d.ts +39 -0
- package/lib/common/src/styles/tokens.js +40 -0
- package/lib/common/src/utils/applyTransactionAsyncUpdate.d.ts +7 -0
- package/lib/common/src/utils/applyTransactionAsyncUpdate.js +19 -12
- package/lib/common/src/utils/arrayPromise.d.ts +6 -0
- package/lib/common/src/utils/arrayPromise.js +7 -1
- package/lib/common/src/utils/cache.js +24 -21
- package/lib/common/src/utils/inputAutoStep.d.ts +1 -1
- package/lib/common/src/utils/inputAutoStep.js +30 -19
- package/lib/common/src/utils/mapMemory.js +9 -10
- package/lib/common/updateBy.d.ts +21 -2
- package/lib/common/updateBy.js +66 -31
- package/lib/index.js +0 -2
- package/lib/style/menuRight.css +13 -26
- package/lib/style/style.css +51 -39
- package/lib/style/tokens.css +34 -0
- package/package.json +2 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// TS mirror of design tokens (src/style/tokens.css). Values must match CSS.
|
|
2
|
+
// For inline styles, ag-grid themes (styleGrid.ts, grid/agGrid4/theme.ts), and layers (z-index).
|
|
3
|
+
export const tokens = {
|
|
4
|
+
color: {
|
|
5
|
+
bgDark: '#131821',
|
|
6
|
+
bgLight: '#17202e',
|
|
7
|
+
scrollbarTrack: 'rgba(255, 255, 255, 0)',
|
|
8
|
+
scrollbarThumb: '#1d262c',
|
|
9
|
+
scrollbarThumbAlt: '#4c4562',
|
|
10
|
+
textBase: '#c4c4c4',
|
|
11
|
+
textTheme: '#5D9FFA',
|
|
12
|
+
borderCommon: 'rgb(50, 62, 71)',
|
|
13
|
+
},
|
|
14
|
+
menu: {
|
|
15
|
+
bgColor: 'rgba(12, 12, 12, 0.91)',
|
|
16
|
+
blur: '10px',
|
|
17
|
+
border: '1px solid rgba(255, 255, 255, 0.41)',
|
|
18
|
+
activeBackground: 'rgba(255, 255, 255, 0.23)',
|
|
19
|
+
itemColor: '#fff',
|
|
20
|
+
itemHoverColor: '#101010',
|
|
21
|
+
itemHoverBgColor: '#fff',
|
|
22
|
+
},
|
|
23
|
+
font: {
|
|
24
|
+
family: 'Roboto',
|
|
25
|
+
sizeBase: '12px',
|
|
26
|
+
},
|
|
27
|
+
zIndex: {
|
|
28
|
+
/** CSS variable --wenay-z-modal; fallback in ModalProvider */
|
|
29
|
+
modal: 9999,
|
|
30
|
+
},
|
|
31
|
+
/** ag-grid theme params shared by GridStyleDefault (legacy) and agGrid4 buildAgTheme */
|
|
32
|
+
grid: {
|
|
33
|
+
fontFamily: 'Roboto',
|
|
34
|
+
textColor: 'rgba(214,214,214,0.9)',
|
|
35
|
+
tabTextColor: 'rgba(227,227,227,0.9)',
|
|
36
|
+
fontSize: '10px',
|
|
37
|
+
spacing: '3px',
|
|
38
|
+
backgroundColor: 'rgb(19,24,33)',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -6,9 +6,15 @@ declare const optionsDef: {
|
|
|
6
6
|
sync: boolean;
|
|
7
7
|
};
|
|
8
8
|
type options = Partial<typeof optionsDef>;
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated v1: does not support row removal and silently loses data while the grid is not ready.
|
|
11
|
+
* Use `useAgGrid`/`createGridBuffer` (grid/agGrid4) - buffer + attach/sync,
|
|
12
|
+
* or at least `applyTransactionAsyncUpdate2`.
|
|
13
|
+
*/
|
|
9
14
|
export declare function applyTransactionAsyncUpdate<T>(grid: GridReadyEvent<T, any> | null | undefined, newData: (Partial<T>)[], getId: (...a: any[]) => string, bufTable: {
|
|
10
15
|
[id: string]: Partial<T>;
|
|
11
16
|
}, option?: options): void;
|
|
17
|
+
/** @deprecated No-op stub: always returns {}. Never implemented; will be removed in a major version. */
|
|
12
18
|
export declare function getUpdateTable<T>(grid: GridReadyEvent<T, any> | null | undefined, newData: (Partial<T>)[], getId: (...a: any[]) => string, bufTable: {
|
|
13
19
|
[id: string]: Partial<T>;
|
|
14
20
|
}, option?: options): {};
|
|
@@ -42,5 +48,6 @@ export declare function applyTransactionAsyncUpdate2<T>(params: params<T>): void
|
|
|
42
48
|
type UnUndefined<T extends (any | undefined)> = T extends undefined ? never : T;
|
|
43
49
|
type t1<T = any> = ColDef<T>["comparator"];
|
|
44
50
|
type paramsCompare<TData = any> = Parameters<Extract<UnUndefined<t1>, (...args: any) => any>>;
|
|
51
|
+
/** @deprecated Duplicate of `numericComparator` from grid/agGrid4 (core.ts) - use that instead. */
|
|
45
52
|
export declare function getComparatorGrid<T = any>(func?: (...param: paramsCompare<T>) => [a: number, b: number]): t1;
|
|
46
53
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Wrapper to simplify working with the grid through a memory point
|
|
2
2
|
const optionsDef = {
|
|
3
3
|
update: true,
|
|
4
4
|
add: true,
|
|
@@ -9,7 +9,7 @@ function applyTransactionAsyncUpdate3({ getId, bufTable, option, newData, grid,
|
|
|
9
9
|
const op = { ...optionsDef, ...(option ?? {}) };
|
|
10
10
|
if (!grid?.api.getRowNode)
|
|
11
11
|
return;
|
|
12
|
-
//
|
|
12
|
+
// Determine which rows must be added and which only need updates
|
|
13
13
|
const arrNew = [];
|
|
14
14
|
const arr = newData.map(e => {
|
|
15
15
|
const id = getId(e);
|
|
@@ -31,16 +31,22 @@ function applyTransactionAsyncUpdate3({ getId, bufTable, option, newData, grid,
|
|
|
31
31
|
});
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
// remove
|
|
34
|
+
// Apply remove once and independently: otherwise removal was lost with empty add/update and duplicated with both
|
|
35
35
|
if ((arrNew.length && op.add) || remove?.length)
|
|
36
36
|
grid.api.applyTransaction({ add: (arrNew.length && op.add) ? arrNew : [], remove: remove });
|
|
37
37
|
if (arr.length && op.update)
|
|
38
38
|
grid.api.applyTransactionAsync({ update: arr });
|
|
39
39
|
}
|
|
40
|
-
//
|
|
40
|
+
// There is no removal here, but this version may still be used somewhere
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated v1: does not support row removal and silently loses data while the grid is not ready.
|
|
43
|
+
* Use `useAgGrid`/`createGridBuffer` (grid/agGrid4) - buffer + attach/sync,
|
|
44
|
+
* or at least `applyTransactionAsyncUpdate2`.
|
|
45
|
+
*/
|
|
41
46
|
export function applyTransactionAsyncUpdate(grid, newData, getId, bufTable, option) {
|
|
42
47
|
return applyTransactionAsyncUpdate3({ getId, option, newData, grid, bufTable });
|
|
43
48
|
}
|
|
49
|
+
/** @deprecated No-op stub: always returns {}. Never implemented; will be removed in a major version. */
|
|
44
50
|
export function getUpdateTable(grid, newData, getId, bufTable, option) {
|
|
45
51
|
return {};
|
|
46
52
|
}
|
|
@@ -57,7 +63,7 @@ export function applyTransactionAsyncUpdate2(params) {
|
|
|
57
63
|
const g = resolveGrid(params);
|
|
58
64
|
if (g && params.onlyMemo != true) {
|
|
59
65
|
if (params.synchronization) {
|
|
60
|
-
// ===
|
|
66
|
+
// === SYNCHRONIZATION: bufTable is the source of truth ===
|
|
61
67
|
const bufIds = new Set(Object.keys(bufTable));
|
|
62
68
|
const gridIds = new Set();
|
|
63
69
|
const arrAdd = [];
|
|
@@ -106,17 +112,18 @@ export function applyTransactionAsyncUpdate2(params) {
|
|
|
106
112
|
});
|
|
107
113
|
}
|
|
108
114
|
}
|
|
115
|
+
/** @deprecated Duplicate of `numericComparator` from grid/agGrid4 (core.ts) - use that instead. */
|
|
109
116
|
export function getComparatorGrid(func) {
|
|
110
117
|
return (...param) => {
|
|
111
|
-
const [a1, b1, modeA, modeB, inv] = param; //
|
|
112
|
-
const [a, b] = func ? func(...param) : [a1, b1]; //
|
|
118
|
+
const [a1, b1, modeA, modeB, inv] = param; // Unpack parameters into the function
|
|
119
|
+
const [a, b] = func ? func(...param) : [a1, b1]; // Use the transforming func if provided
|
|
113
120
|
return ((typeof a == "number" && !Number.isNaN(a)) &&
|
|
114
|
-
(typeof b == "number" && !Number.isNaN(b))) //
|
|
115
|
-
? a - b //
|
|
121
|
+
(typeof b == "number" && !Number.isNaN(b))) // If both a and b are valid numbers
|
|
122
|
+
? a - b // Difference between numbers
|
|
116
123
|
: a == b
|
|
117
|
-
? 0 //
|
|
124
|
+
? 0 // If values are equal, return 0
|
|
118
125
|
: (!Number.isNaN(b) && b != undefined)
|
|
119
|
-
? (inv ? -1 : 1) //
|
|
120
|
-
: (inv ? 1 : -1); //
|
|
126
|
+
? (inv ? -1 : 1) // If b exists: order is determined by inv
|
|
127
|
+
: (inv ? 1 : -1); // If b is missing: order is determined by inv
|
|
121
128
|
};
|
|
122
129
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps an array of promise thunks with progress callbacks.
|
|
3
|
+
* CONTRACT: countOk/countError counters are correct only when thunks are run
|
|
4
|
+
* STRICTLY SEQUENTIALLY (one after another). During parallel execution (Promise.all),
|
|
5
|
+
* counter values in callbacks are a race and must not be relied on.
|
|
6
|
+
*/
|
|
1
7
|
export declare function ArrayPromise<T = unknown>({ arr, catchF, thenF }: {
|
|
2
8
|
arr: (() => Promise<T>)[];
|
|
3
9
|
thenF?: (data: T, i: number, countOk: number, countError: number, count: number) => unknown;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps an array of promise thunks with progress callbacks.
|
|
3
|
+
* CONTRACT: countOk/countError counters are correct only when thunks are run
|
|
4
|
+
* STRICTLY SEQUENTIALLY (one after another). During parallel execution (Promise.all),
|
|
5
|
+
* counter values in callbacks are a race and must not be relied on.
|
|
6
|
+
*/
|
|
1
7
|
export function ArrayPromise({ arr, catchF, thenF }) {
|
|
2
8
|
let ok = 0, countError = 0;
|
|
3
9
|
const count = arr.length;
|
|
@@ -8,7 +14,7 @@ export function ArrayPromise({ arr, catchF, thenF }) {
|
|
|
8
14
|
const b = (error, i) => {
|
|
9
15
|
++countError;
|
|
10
16
|
if (catchF)
|
|
11
|
-
return catchF
|
|
17
|
+
return catchF(error, i, ok, countError, count);
|
|
12
18
|
else
|
|
13
19
|
throw error;
|
|
14
20
|
};
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { renderBy } from "../../updateBy";
|
|
2
|
-
|
|
2
|
+
function getHostName() {
|
|
3
|
+
return typeof location != "undefined" ? location.toString() : "wenay-react2";
|
|
4
|
+
}
|
|
3
5
|
export class CSaveToCache {
|
|
4
6
|
async set(key, value) {
|
|
5
7
|
const t = new Response(JSON.stringify(value));
|
|
6
|
-
if (
|
|
8
|
+
if (typeof caches != "undefined") {
|
|
7
9
|
const Cache = await caches.open(key);
|
|
8
|
-
await Cache.put(
|
|
10
|
+
await Cache.put(getHostName(), t);
|
|
9
11
|
return true;
|
|
10
12
|
}
|
|
11
13
|
return false;
|
|
12
14
|
}
|
|
13
15
|
async get(key) {
|
|
14
|
-
if (
|
|
16
|
+
if (typeof caches != "undefined") {
|
|
15
17
|
const Cache = await caches.open(key);
|
|
16
|
-
const cachedResponse = await Cache.match(
|
|
18
|
+
const cachedResponse = await Cache.match(getHostName());
|
|
17
19
|
if (cachedResponse) {
|
|
18
20
|
return (await cachedResponse.json());
|
|
19
21
|
}
|
|
@@ -21,7 +23,7 @@ export class CSaveToCache {
|
|
|
21
23
|
return null;
|
|
22
24
|
}
|
|
23
25
|
async delete(key) {
|
|
24
|
-
if (
|
|
26
|
+
if (typeof caches != "undefined") {
|
|
25
27
|
return await caches.delete(key);
|
|
26
28
|
}
|
|
27
29
|
return false;
|
|
@@ -29,14 +31,14 @@ export class CSaveToCache {
|
|
|
29
31
|
}
|
|
30
32
|
export class CSaveToLocalStorage {
|
|
31
33
|
async set(key, value) {
|
|
32
|
-
if (
|
|
34
|
+
if (typeof localStorage != "undefined") {
|
|
33
35
|
await localStorage.setItem(key, JSON.stringify(value));
|
|
34
36
|
return true;
|
|
35
37
|
}
|
|
36
38
|
return false;
|
|
37
39
|
}
|
|
38
40
|
async get(key) {
|
|
39
|
-
if (
|
|
41
|
+
if (typeof localStorage != "undefined") {
|
|
40
42
|
const st = await localStorage.getItem(key);
|
|
41
43
|
if (st) {
|
|
42
44
|
try {
|
|
@@ -50,14 +52,14 @@ export class CSaveToLocalStorage {
|
|
|
50
52
|
return null;
|
|
51
53
|
}
|
|
52
54
|
async delete(key) {
|
|
53
|
-
if (
|
|
55
|
+
if (typeof localStorage != "undefined") {
|
|
54
56
|
localStorage.removeItem(key);
|
|
55
57
|
return true;
|
|
56
58
|
}
|
|
57
59
|
return false;
|
|
58
60
|
}
|
|
59
61
|
async deleteAll() {
|
|
60
|
-
if (
|
|
62
|
+
if (typeof localStorage != "undefined") {
|
|
61
63
|
await localStorage.clear();
|
|
62
64
|
return true;
|
|
63
65
|
}
|
|
@@ -66,14 +68,12 @@ export class CSaveToLocalStorage {
|
|
|
66
68
|
}
|
|
67
69
|
export const CacheG = new CSaveToCache();
|
|
68
70
|
export const CacheLocal = new CSaveToLocalStorage();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
renderBy(tr);
|
|
76
|
-
}
|
|
71
|
+
function addDataToMap(data, map) {
|
|
72
|
+
for (let [k, v] of data) {
|
|
73
|
+
const tr = map.has(k) ? map.get(k) : map.set(k, v).get(k);
|
|
74
|
+
if (tr && typeof tr === 'object') {
|
|
75
|
+
Object.assign(tr, v);
|
|
76
|
+
renderBy(tr);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -93,17 +93,20 @@ export const ObjectStringToDate = (obj) => {
|
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
95
|
};
|
|
96
|
+
// module-level constant: this runs for every string of every cached object on load
|
|
97
|
+
const ISO_DATE_RE = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z)?$/;
|
|
96
98
|
function isDate(_date) {
|
|
97
|
-
|
|
98
|
-
return _regExp.test(_date);
|
|
99
|
+
return ISO_DATE_RE.test(_date);
|
|
99
100
|
}
|
|
100
101
|
export function CacheFuncMapBase(arr, Save) {
|
|
101
102
|
return {
|
|
102
103
|
async load() {
|
|
103
104
|
for (let [k, v] of arr) {
|
|
104
105
|
const t = await Save.get(k);
|
|
106
|
+
if (!t)
|
|
107
|
+
continue;
|
|
105
108
|
ObjectStringToDate(t);
|
|
106
|
-
|
|
109
|
+
addDataToMap(t, v);
|
|
107
110
|
}
|
|
108
111
|
},
|
|
109
112
|
async save() {
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
|
-
//
|
|
2
|
+
// Set automatic step control for an input element
|
|
3
3
|
import { GetDblPrecision, GetDblPrecision2, NormalizeDouble } from "wenay-common2";
|
|
4
|
+
// step is a power of 0.1 (0.1, 0.01, ...) - resilient to float noise,
|
|
5
|
+
// unlike the previous Math.log10(step)%1==0
|
|
6
|
+
function isPowerOfTenth(step) {
|
|
7
|
+
if (!(step > 0 && step < 1))
|
|
8
|
+
return false;
|
|
9
|
+
const digits = Math.round(-Math.log10(step));
|
|
10
|
+
return Math.abs(Math.pow(0.1, digits) - step) < step * 1e-9;
|
|
11
|
+
}
|
|
12
|
+
// Own handlers on the element: repeated calls remove previous ones (like the old on* overwrite)
|
|
13
|
+
const appliedHandlers = new WeakMap();
|
|
4
14
|
export function SetAutoStepForElement(element, params = { maxStep: 1 }) {
|
|
15
|
+
appliedHandlers.get(element)?.();
|
|
5
16
|
function parse(valueStr) { let val = parseFloat(valueStr); return isNaN(val) ? null : val; }
|
|
6
17
|
const { minStep, maxStep = 1 } = params;
|
|
7
18
|
const maxDigits = minStep ? GetDblPrecision(minStep) : undefined;
|
|
@@ -16,7 +27,7 @@ export function SetAutoStepForElement(element, params = { maxStep: 1 }) {
|
|
|
16
27
|
//function NormalizeDouble(value :number, digits :number) { let factor=Math.pow(10, digits); return Math.round(value * factor)/factor; }
|
|
17
28
|
//if (dotPos===valueStr.length-1) dotPos--;
|
|
18
29
|
//let digits= GetDblPrecision2(parseFloat(valueStr), minDigits, 10);
|
|
19
|
-
let dotPos = valueStr.search(/\.|,/); //
|
|
30
|
+
let dotPos = valueStr.search(/\.|,/); // Find a dot or comma
|
|
20
31
|
let digits = (dotPos >= 0) ? valueStr.length - dotPos - 1 : 0;
|
|
21
32
|
digits = Math.max(digits, minDigits);
|
|
22
33
|
if (digits > 10)
|
|
@@ -34,20 +45,15 @@ export function SetAutoStepForElement(element, params = { maxStep: 1 }) {
|
|
|
34
45
|
//if (Math.abs(min) < step) min= Math.floor(Math.abs(min)/step)*step * Math.sign(min);
|
|
35
46
|
if (_min != null) {
|
|
36
47
|
if (Math.abs(_min) % step != 0)
|
|
37
|
-
_min = Math.floor(Math.abs(_min) / step) * step * Math.sign(
|
|
48
|
+
_min = Math.floor(Math.abs(_min) / step) * step * Math.sign(_min);
|
|
38
49
|
element.min = _min + "";
|
|
39
50
|
}
|
|
40
|
-
//console.log("step:",element.step+"->"+step," min:",element.min+"->"+min);
|
|
41
|
-
//console.log("minDefault:",_minDefault,parseFloat(_minDefault));
|
|
42
51
|
element.step = step + "";
|
|
43
|
-
|
|
44
|
-
return step; ////lib.GetDblPrecision($fee[0].value)); }
|
|
52
|
+
return step;
|
|
45
53
|
}
|
|
46
|
-
let modeAuto = !_step || (_step
|
|
47
|
-
const modeAuto0 = modeAuto;
|
|
54
|
+
let modeAuto = !_step || isPowerOfTenth(_step);
|
|
48
55
|
if (modeAuto) {
|
|
49
56
|
calculateStep((_step ? (Math.round(parseFloat(element.value) / _step) * _step) : element.value) + "");
|
|
50
|
-
//console.log(element.value, step);
|
|
51
57
|
}
|
|
52
58
|
if (_step && minDefault && Math.abs(minDefault % _step) > 1e-10)
|
|
53
59
|
modeAuto = false;
|
|
@@ -55,16 +61,13 @@ export function SetAutoStepForElement(element, params = { maxStep: 1 }) {
|
|
|
55
61
|
modeAuto = false;
|
|
56
62
|
else
|
|
57
63
|
modeAuto ||= (_step != null && (minStep == null || _step > minStep));
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
calculateStep(element.value); }; // console.log(element.step); }// console.log(element.value, element.step); }
|
|
63
|
-
element.onchange = () => {
|
|
64
|
+
// addEventListener instead of on*=: do not overwrite other handlers; return a disposer
|
|
65
|
+
const onKeyUp = () => { if (modeAuto)
|
|
66
|
+
calculateStep(element.value); };
|
|
67
|
+
const onChange = () => {
|
|
64
68
|
let digits = _digits;
|
|
65
69
|
if (digits != null)
|
|
66
70
|
element.value = parseFloat(element.value).toFixed(digits);
|
|
67
|
-
//console.log("change", {value: element.value, digits, minDigits});
|
|
68
71
|
if (minDefault != null && parseFloat(element.value) < minDefault) {
|
|
69
72
|
element.step = stepDefault + "";
|
|
70
73
|
element.value = minDefault + "";
|
|
@@ -72,8 +75,16 @@ export function SetAutoStepForElement(element, params = { maxStep: 1 }) {
|
|
|
72
75
|
_digits = null;
|
|
73
76
|
}
|
|
74
77
|
element.setAttribute("value", element.value);
|
|
75
|
-
};
|
|
76
|
-
|
|
78
|
+
};
|
|
79
|
+
element.addEventListener("keyup", onKeyUp);
|
|
80
|
+
element.addEventListener("change", onChange);
|
|
81
|
+
const dispose = () => {
|
|
82
|
+
element.removeEventListener("keyup", onKeyUp);
|
|
83
|
+
element.removeEventListener("change", onChange);
|
|
84
|
+
appliedHandlers.delete(element);
|
|
85
|
+
};
|
|
86
|
+
appliedHandlers.set(element, dispose);
|
|
87
|
+
return dispose;
|
|
77
88
|
}
|
|
78
89
|
//import * as Time from "./Time"
|
|
79
90
|
//import {const_Date} from "./Time";
|
|
@@ -36,20 +36,19 @@ export function deepMergeWithMap(target, source, visited = new Map()) {
|
|
|
36
36
|
}
|
|
37
37
|
return target;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
// WeakSet: a strict Map kept every def object alive forever
|
|
40
|
+
const merged = new WeakSet();
|
|
40
41
|
export function staticGetAdd(key, def, options = { reversDeep: false }) {
|
|
41
|
-
if (options.deepAutoMerge && !
|
|
42
|
-
|
|
43
|
-
if (options.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
staticProps.set(key, deepMergeWithMap(deepClone(def), staticProps.get(key) ?? {}));
|
|
48
|
-
}
|
|
42
|
+
if (options.deepAutoMerge && !merged.has(def)) {
|
|
43
|
+
merged.add(def);
|
|
44
|
+
if (!options.reversDeep)
|
|
45
|
+
staticProps.set(key, deepMergeWithMap(staticProps.get(key) ?? {}, def));
|
|
46
|
+
else
|
|
47
|
+
staticProps.set(key, deepMergeWithMap(deepClone(def), staticProps.get(key) ?? {}));
|
|
49
48
|
}
|
|
50
49
|
if (options.abs)
|
|
51
50
|
staticProps.set(key, def);
|
|
52
|
-
const t = (staticProps.get(key)
|
|
51
|
+
const t = (staticProps.has(key) ? staticProps.get(key) : staticProps.set(key, def).get(key));
|
|
53
52
|
return t; // Object.assign(def, t) // t //
|
|
54
53
|
}
|
|
55
54
|
export function staticGetById(key, def, id) {
|
package/lib/common/updateBy.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
type Listener = (a?: any) => void;
|
|
2
3
|
interface ObserverState {
|
|
3
4
|
listeners: Set<Listener>;
|
|
@@ -8,9 +9,27 @@ export declare const mapWait: Map<object, {
|
|
|
8
9
|
refreshAsync: (ms: number, func: () => any) => void;
|
|
9
10
|
refreshAsync2: (ms: number, func: () => any) => Promise<void>;
|
|
10
11
|
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Ветка Dispatch<SetStateAction<T>>: listener получает тот же мутированный объект,
|
|
14
|
+
* setState(тот же ref) React бэйлаутит без ререндера — используйте (a: T) => void.
|
|
15
|
+
*/
|
|
16
|
+
export type UpdateCallback<T extends object> = React.Dispatch<React.SetStateAction<T>> | ((a: T) => void);
|
|
11
17
|
export declare function renderBy(a: object, ms?: number): void;
|
|
12
18
|
export declare function renderByRevers(a: object, ms?: number, reverse?: boolean): void;
|
|
13
19
|
export declare function renderByLast(a: object, ms?: number): void;
|
|
14
|
-
export declare function useUpdateBy<T extends object>(a: T, f?:
|
|
15
|
-
export declare function updateBy<T extends object>(a: T, f?:
|
|
20
|
+
export declare function useUpdateBy<T extends object>(a: T, f?: UpdateCallback<T>): void;
|
|
21
|
+
export declare function updateBy<T extends object>(a: T, f?: UpdateCallback<T>): void;
|
|
22
|
+
export type UpdateApi<T extends object> = {
|
|
23
|
+
object: T;
|
|
24
|
+
emit(ms?: number): void;
|
|
25
|
+
render(ms?: number): void;
|
|
26
|
+
renderReverse(ms?: number, reverse?: boolean): void;
|
|
27
|
+
renderLast(ms?: number): void;
|
|
28
|
+
on(listener: (obj: T) => void): () => void;
|
|
29
|
+
subscribe(listener: (obj: T) => void): () => void;
|
|
30
|
+
use(f?: UpdateCallback<T>): void;
|
|
31
|
+
useSubscribe(f?: UpdateCallback<T>): void;
|
|
32
|
+
};
|
|
33
|
+
export declare function createUpdateApi<T extends object>(obj: T): UpdateApi<T>;
|
|
34
|
+
export declare function useUpdateByApi<T extends object>(obj: T, f?: UpdateCallback<T>): UpdateApi<T>;
|
|
16
35
|
export {};
|
package/lib/common/updateBy.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { useLayoutEffect, useSyncExternalStore } from "react";
|
|
2
|
-
import { waitRun } from "wenay-common2";
|
|
1
|
+
import { useCallback, useLayoutEffect, useSyncExternalStore } from "react";
|
|
2
|
+
import { UseListen, waitRun } from "wenay-common2";
|
|
3
3
|
export const map3 = new WeakMap();
|
|
4
4
|
export const mapWait = new Map();
|
|
5
|
+
const updateListens = new WeakMap();
|
|
6
|
+
function getUpdateListen(obj) {
|
|
7
|
+
let listen = updateListens.get(obj);
|
|
8
|
+
if (!listen) {
|
|
9
|
+
listen = UseListen();
|
|
10
|
+
updateListens.set(obj, listen);
|
|
11
|
+
}
|
|
12
|
+
return listen;
|
|
13
|
+
}
|
|
5
14
|
function getObserverState(obj) {
|
|
6
15
|
let state = map3.get(obj);
|
|
7
16
|
if (!state) {
|
|
@@ -10,68 +19,64 @@ function getObserverState(obj) {
|
|
|
10
19
|
}
|
|
11
20
|
return state;
|
|
12
21
|
}
|
|
22
|
+
// reverse/lastOnly действуют только на React-подписчиков (useUpdateBy);
|
|
23
|
+
// императивные on-подписчики вызываются всегда все, в порядке подписки
|
|
13
24
|
function triggerUpdate(obj, reverse = false, lastOnly = false) {
|
|
14
|
-
const
|
|
15
|
-
|
|
25
|
+
const listen = updateListens.get(obj);
|
|
26
|
+
let state = map3.get(obj);
|
|
27
|
+
if ((!state || state.listeners.size === 0) && !listen?.[1].count())
|
|
16
28
|
return;
|
|
29
|
+
state ??= getObserverState(obj);
|
|
17
30
|
state.version += 1;
|
|
18
31
|
let listenersArray = Array.from(state.listeners);
|
|
19
32
|
if (lastOnly) {
|
|
20
33
|
const last = listenersArray.at(-1);
|
|
21
34
|
if (last)
|
|
22
35
|
last(obj);
|
|
36
|
+
listen?.[0](obj);
|
|
23
37
|
return;
|
|
24
38
|
}
|
|
25
39
|
if (reverse) {
|
|
26
40
|
listenersArray.reverse();
|
|
27
41
|
}
|
|
28
42
|
listenersArray.forEach(listener => listener(obj));
|
|
43
|
+
listen?.[0](obj);
|
|
29
44
|
}
|
|
30
|
-
|
|
45
|
+
function schedule(a, ms, reverse = false, lastOnly = false) {
|
|
31
46
|
if (ms) {
|
|
32
47
|
(mapWait.get(a) || mapWait.set(a, waitRun()).get(a))
|
|
33
48
|
.refreshAsync(ms, () => {
|
|
34
49
|
mapWait.delete(a);
|
|
35
|
-
triggerUpdate(a);
|
|
50
|
+
triggerUpdate(a, reverse, lastOnly);
|
|
36
51
|
});
|
|
37
52
|
}
|
|
38
53
|
else
|
|
39
|
-
triggerUpdate(a);
|
|
54
|
+
triggerUpdate(a, reverse, lastOnly);
|
|
55
|
+
}
|
|
56
|
+
export function renderBy(a, ms) {
|
|
57
|
+
schedule(a, ms);
|
|
40
58
|
}
|
|
41
59
|
export function renderByRevers(a, ms, reverse = true) {
|
|
42
|
-
|
|
43
|
-
(mapWait.get(a) || mapWait.set(a, waitRun()).get(a))
|
|
44
|
-
.refreshAsync(ms, () => {
|
|
45
|
-
mapWait.delete(a);
|
|
46
|
-
triggerUpdate(a, reverse);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
else
|
|
50
|
-
triggerUpdate(a, reverse);
|
|
60
|
+
schedule(a, ms, reverse);
|
|
51
61
|
}
|
|
52
62
|
export function renderByLast(a, ms) {
|
|
53
|
-
|
|
54
|
-
(mapWait.get(a) || mapWait.set(a, waitRun()).get(a))
|
|
55
|
-
.refreshAsync(ms, () => {
|
|
56
|
-
mapWait.delete(a);
|
|
57
|
-
triggerUpdate(a, false, true);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
else
|
|
61
|
-
triggerUpdate(a, false, true);
|
|
63
|
+
schedule(a, ms, false, true);
|
|
62
64
|
}
|
|
63
65
|
export function useUpdateBy(a, f) {
|
|
64
|
-
|
|
66
|
+
// стабильный subscribe: без useCallback React переподписывается на каждый рендер,
|
|
67
|
+
// а удаление state из map3 при этом сбрасывало бы version → лишний форс-ререндер
|
|
68
|
+
const subscribe = useCallback((listener) => {
|
|
65
69
|
if (f)
|
|
66
70
|
return () => { };
|
|
67
71
|
const state = getObserverState(a);
|
|
68
72
|
state.listeners.add(listener);
|
|
69
73
|
return () => {
|
|
70
74
|
state.listeners.delete(listener);
|
|
71
|
-
if (state.listeners.size === 0)
|
|
72
|
-
map3.delete(a);
|
|
73
75
|
};
|
|
74
|
-
},
|
|
76
|
+
}, [a, f]);
|
|
77
|
+
useSyncExternalStore(subscribe,
|
|
78
|
+
// getSnapshot must be pure: only read the version, subscribe creates the state
|
|
79
|
+
() => (f ? 0 : (map3.get(a)?.version ?? 0)));
|
|
75
80
|
useLayoutEffect(() => {
|
|
76
81
|
if (!f)
|
|
77
82
|
return;
|
|
@@ -79,11 +84,41 @@ export function useUpdateBy(a, f) {
|
|
|
79
84
|
state.listeners.add(f);
|
|
80
85
|
return () => {
|
|
81
86
|
state.listeners.delete(f);
|
|
82
|
-
if (state.listeners.size === 0)
|
|
83
|
-
map3.delete(a);
|
|
84
87
|
};
|
|
85
88
|
}, [a, f]);
|
|
86
89
|
}
|
|
87
90
|
export function updateBy(a, f) {
|
|
88
91
|
useUpdateBy(a, f);
|
|
89
92
|
}
|
|
93
|
+
const apiCache = new WeakMap();
|
|
94
|
+
export function createUpdateApi(obj) {
|
|
95
|
+
const cached = apiCache.get(obj);
|
|
96
|
+
if (cached)
|
|
97
|
+
return cached;
|
|
98
|
+
const [, listen] = getUpdateListen(obj);
|
|
99
|
+
const api = {
|
|
100
|
+
object: obj,
|
|
101
|
+
emit(ms) { renderBy(obj, ms); },
|
|
102
|
+
render(ms) { renderBy(obj, ms); },
|
|
103
|
+
renderReverse(ms, reverse = true) { renderByRevers(obj, ms, reverse); },
|
|
104
|
+
renderLast(ms) { renderByLast(obj, ms); },
|
|
105
|
+
on(listener) {
|
|
106
|
+
return listen.on((value) => listener(value));
|
|
107
|
+
},
|
|
108
|
+
subscribe(listener) {
|
|
109
|
+
return api.on(listener);
|
|
110
|
+
},
|
|
111
|
+
use(f) {
|
|
112
|
+
useUpdateBy(obj, f);
|
|
113
|
+
},
|
|
114
|
+
useSubscribe(f) {
|
|
115
|
+
useUpdateBy(obj, f);
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
apiCache.set(obj, api);
|
|
119
|
+
return api;
|
|
120
|
+
}
|
|
121
|
+
export function useUpdateByApi(obj, f) {
|
|
122
|
+
useUpdateBy(obj, f);
|
|
123
|
+
return createUpdateApi(obj);
|
|
124
|
+
}
|
package/lib/index.js
CHANGED