wenay-react2 1.0.19 → 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.
Files changed (77) hide show
  1. package/README.md +383 -382
  2. package/lib/common/api.d.ts +28 -0
  3. package/lib/common/api.js +41 -16
  4. package/lib/common/src/components/Buttons/MiniButton.d.ts +1 -0
  5. package/lib/common/src/components/Buttons/MiniButton.js +2 -2
  6. package/lib/common/src/components/Dnd/DraggableOutlineDiv.d.ts +1 -0
  7. package/lib/common/src/components/Dnd/DraggableOutlineDiv.js +10 -7
  8. package/lib/common/src/components/Dnd/RNDFunc.js +28 -17
  9. package/lib/common/src/components/Dnd/RNDFunc3.d.ts +27 -17
  10. package/lib/common/src/components/Dnd/RNDFunc3.js +107 -107
  11. package/lib/common/src/components/Dnd/Resizable.js +3 -3
  12. package/lib/common/src/components/Input.js +3 -3
  13. package/lib/common/src/components/Menu/RightMenu.js +17 -18
  14. package/lib/common/src/components/Menu/StickerMenu.d.ts +1 -3
  15. package/lib/common/src/components/Menu/StickerMenu.js +42 -28
  16. package/lib/common/src/components/Menu/index.d.ts +1 -1
  17. package/lib/common/src/components/Menu/index.js +1 -1
  18. package/lib/common/src/components/Modal/LeftModal.d.ts +14 -12
  19. package/lib/common/src/components/Modal/LeftModal.js +34 -52
  20. package/lib/common/src/components/Modal/Modal.d.ts +26 -12
  21. package/lib/common/src/components/Modal/Modal.js +66 -89
  22. package/lib/common/src/components/Modal/ModalContextProvider.d.ts +20 -3
  23. package/lib/common/src/components/Modal/ModalContextProvider.js +35 -8
  24. package/lib/common/src/components/MyResizeObserver.js +15 -18
  25. package/lib/common/src/components/Other.js +6 -5
  26. package/lib/common/src/components/Parameters.js +8 -7
  27. package/lib/common/src/components/ParametersEngine.js +36 -59
  28. package/lib/common/src/grid/agGrid4/agGrid4.d.ts +53 -0
  29. package/lib/common/src/grid/agGrid4/agGrid4.js +132 -0
  30. package/lib/common/src/grid/agGrid4/core.d.ts +56 -0
  31. package/lib/common/src/grid/agGrid4/core.js +127 -0
  32. package/lib/common/src/grid/agGrid4/index.d.ts +6 -0
  33. package/lib/common/src/grid/agGrid4/index.js +3 -0
  34. package/lib/common/src/grid/agGrid4/theme.d.ts +7 -0
  35. package/lib/common/src/grid/agGrid4/theme.js +18 -0
  36. package/lib/common/src/hooks/useAddDownAnyKey.d.ts +21 -2
  37. package/lib/common/src/hooks/useAddDownAnyKey.js +46 -9
  38. package/lib/common/src/hooks/useDraggable.d.ts +20 -2
  39. package/lib/common/src/hooks/useDraggable.js +146 -115
  40. package/lib/common/src/hooks/useOutside.d.ts +24 -4
  41. package/lib/common/src/hooks/useOutside.js +77 -26
  42. package/lib/common/src/logs/logs.d.ts +5 -2
  43. package/lib/common/src/logs/logs.js +18 -34
  44. package/lib/common/src/logs/logs3.d.ts +9 -9
  45. package/lib/common/src/logs/logs3.js +48 -39
  46. package/lib/common/src/logs/miniLogs.d.ts +3 -3
  47. package/lib/common/src/logs/miniLogs.js +28 -36
  48. package/lib/common/src/menu/menu.d.ts +18 -18
  49. package/lib/common/src/menu/menu.js +49 -25
  50. package/lib/common/src/menu/menuMouse.d.ts +2 -1
  51. package/lib/common/src/menu/menuMouse.js +5 -4
  52. package/lib/common/src/menu/menuR.d.ts +4 -3
  53. package/lib/common/src/menu/menuR.js +42 -38
  54. package/lib/common/src/myChart/1/myChart.d.ts +5 -5
  55. package/lib/common/src/myChart/1/myChart.js +58 -47
  56. package/lib/common/src/myChart/1/myChartTest.js +8 -4
  57. package/lib/common/src/myChart/chartEngine/chartEngineReact.d.ts +24 -27
  58. package/lib/common/src/myChart/chartEngine/chartEngineReact.js +189 -118
  59. package/lib/common/src/styles/styleGrid.d.ts +2 -1
  60. package/lib/common/src/styles/styleGrid.js +10 -12
  61. package/lib/common/src/styles/tokens.d.ts +39 -0
  62. package/lib/common/src/styles/tokens.js +40 -0
  63. package/lib/common/src/utils/applyTransactionAsyncUpdate.d.ts +7 -0
  64. package/lib/common/src/utils/applyTransactionAsyncUpdate.js +25 -19
  65. package/lib/common/src/utils/arrayPromise.d.ts +6 -0
  66. package/lib/common/src/utils/arrayPromise.js +7 -1
  67. package/lib/common/src/utils/cache.js +32 -24
  68. package/lib/common/src/utils/inputAutoStep.d.ts +1 -1
  69. package/lib/common/src/utils/inputAutoStep.js +30 -19
  70. package/lib/common/src/utils/mapMemory.js +15 -15
  71. package/lib/common/updateBy.d.ts +21 -2
  72. package/lib/common/updateBy.js +66 -131
  73. package/lib/index.js +0 -2
  74. package/lib/style/menuRight.css +13 -26
  75. package/lib/style/style.css +51 -39
  76. package/lib/style/tokens.css +34 -0
  77. package/package.json +2 -2
@@ -0,0 +1,39 @@
1
+ export declare const tokens: {
2
+ readonly color: {
3
+ readonly bgDark: "#131821";
4
+ readonly bgLight: "#17202e";
5
+ readonly scrollbarTrack: "rgba(255, 255, 255, 0)";
6
+ readonly scrollbarThumb: "#1d262c";
7
+ readonly scrollbarThumbAlt: "#4c4562";
8
+ readonly textBase: "#c4c4c4";
9
+ readonly textTheme: "#5D9FFA";
10
+ readonly borderCommon: "rgb(50, 62, 71)";
11
+ };
12
+ readonly menu: {
13
+ readonly bgColor: "rgba(12, 12, 12, 0.91)";
14
+ readonly blur: "10px";
15
+ readonly border: "1px solid rgba(255, 255, 255, 0.41)";
16
+ readonly activeBackground: "rgba(255, 255, 255, 0.23)";
17
+ readonly itemColor: "#fff";
18
+ readonly itemHoverColor: "#101010";
19
+ readonly itemHoverBgColor: "#fff";
20
+ };
21
+ readonly font: {
22
+ readonly family: "Roboto";
23
+ readonly sizeBase: "12px";
24
+ };
25
+ readonly zIndex: {
26
+ /** CSS variable --wenay-z-modal; fallback in ModalProvider */
27
+ readonly modal: 9999;
28
+ };
29
+ /** ag-grid theme params shared by GridStyleDefault (legacy) and agGrid4 buildAgTheme */
30
+ readonly grid: {
31
+ readonly fontFamily: "Roboto";
32
+ readonly textColor: "rgba(214,214,214,0.9)";
33
+ readonly tabTextColor: "rgba(227,227,227,0.9)";
34
+ readonly fontSize: "10px";
35
+ readonly spacing: "3px";
36
+ readonly backgroundColor: "rgb(19,24,33)";
37
+ };
38
+ };
39
+ export type Tokens = typeof tokens;
@@ -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);
@@ -27,19 +27,26 @@ function applyTransactionAsyncUpdate3({ getId, bufTable, option, newData, grid,
27
27
  grid.api.applyTransaction({
28
28
  add: op.add ? arrNew : [],
29
29
  update: op.update ? arr : [],
30
+ remove: remove,
30
31
  });
31
32
  return;
32
33
  }
33
- if (arrNew.length && op.add)
34
- grid.api.applyTransaction({ add: arrNew, remove: remove }); // для удаления важно только получить ид
34
+ // Apply remove once and independently: otherwise removal was lost with empty add/update and duplicated with both
35
+ if ((arrNew.length && op.add) || remove?.length)
36
+ grid.api.applyTransaction({ add: (arrNew.length && op.add) ? arrNew : [], remove: remove });
35
37
  if (arr.length && op.update)
36
- grid.api.applyTransactionAsync({ update: arr, remove: remove });
38
+ grid.api.applyTransactionAsync({ update: arr });
37
39
  }
38
- // тут нет удаления но эта версия может использовать где то
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
+ */
39
46
  export function applyTransactionAsyncUpdate(grid, newData, getId, bufTable, option) {
40
47
  return applyTransactionAsyncUpdate3({ getId, option, newData, grid, bufTable });
41
48
  }
42
- const map = new WeakMap();
49
+ /** @deprecated No-op stub: always returns {}. Never implemented; will be removed in a major version. */
43
50
  export function getUpdateTable(grid, newData, getId, bufTable, option) {
44
51
  return {};
45
52
  }
@@ -56,7 +63,7 @@ export function applyTransactionAsyncUpdate2(params) {
56
63
  const g = resolveGrid(params);
57
64
  if (g && params.onlyMemo != true) {
58
65
  if (params.synchronization) {
59
- // === СИНХРОНИЗАЦИЯ: bufTable истина ===
66
+ // === SYNCHRONIZATION: bufTable is the source of truth ===
60
67
  const bufIds = new Set(Object.keys(bufTable));
61
68
  const gridIds = new Set();
62
69
  const arrAdd = [];
@@ -91,13 +98,11 @@ export function applyTransactionAsyncUpdate2(params) {
91
98
  if (existing)
92
99
  toRemove.push(existing);
93
100
  });
94
- if (newData?.length)
95
- applyTransactionAsyncUpdate3({ grid: g, newData, getId, bufTable, option: op, remove: toRemove });
101
+ if (newData?.length || toRemove.length)
102
+ applyTransactionAsyncUpdate3({ grid: g, newData: newData ?? [], getId, bufTable, option: op, remove: toRemove });
96
103
  }
97
104
  }
98
105
  else {
99
- if (!map.has(bufTable))
100
- map.set(bufTable, new Set());
101
106
  newData?.forEach(e => {
102
107
  const id = getId(e);
103
108
  bufTable[id] = { ...(bufTable[id] ?? {}), ...e };
@@ -107,17 +112,18 @@ export function applyTransactionAsyncUpdate2(params) {
107
112
  });
108
113
  }
109
114
  }
115
+ /** @deprecated Duplicate of `numericComparator` from grid/agGrid4 (core.ts) - use that instead. */
110
116
  export function getComparatorGrid(func) {
111
117
  return (...param) => {
112
- const [a1, b1, modeA, modeB, inv] = param; // Распаковка параметров в функцию
113
- const [a, b] = func ? func(...param) : [a1, b1]; // Использование преобразующей функции func, если передана
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
114
120
  return ((typeof a == "number" && !Number.isNaN(a)) &&
115
- (typeof b == "number" && !Number.isNaN(b))) // Если оба a и b - валидные числа
116
- ? a - b // Разница между числами
121
+ (typeof b == "number" && !Number.isNaN(b))) // If both a and b are valid numbers
122
+ ? a - b // Difference between numbers
117
123
  : a == b
118
- ? 0 // Если значения равны, возвращаем 0
124
+ ? 0 // If values are equal, return 0
119
125
  : (!Number.isNaN(b) && b != undefined)
120
- ? (inv ? -1 : 1) // Если b существует: порядок определяется inv
121
- : (inv ? 1 : -1); // Если b отсутствует: порядок определяется inv
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
122
128
  };
123
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?.(error, i, ok, countError, count);
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
- const HostName = location.toString();
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 (window.caches) {
8
+ if (typeof caches != "undefined") {
7
9
  const Cache = await caches.open(key);
8
- await Cache.put(HostName, t);
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 (window.caches) {
16
+ if (typeof caches != "undefined") {
15
17
  const Cache = await caches.open(key);
16
- const cachedResponse = await Cache.match(HostName);
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 (window.caches) {
26
+ if (typeof caches != "undefined") {
25
27
  return await caches.delete(key);
26
28
  }
27
29
  return false;
@@ -29,30 +31,35 @@ export class CSaveToCache {
29
31
  }
30
32
  export class CSaveToLocalStorage {
31
33
  async set(key, value) {
32
- const t = new Response(JSON.stringify(value));
33
- if (window.localStorage) {
34
+ if (typeof localStorage != "undefined") {
34
35
  await localStorage.setItem(key, JSON.stringify(value));
35
36
  return true;
36
37
  }
37
38
  return false;
38
39
  }
39
40
  async get(key) {
40
- if (window.localStorage) {
41
+ if (typeof localStorage != "undefined") {
41
42
  const st = await localStorage.getItem(key);
42
- if (st)
43
- return JSON.parse(st);
43
+ if (st) {
44
+ try {
45
+ return JSON.parse(st);
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
44
51
  }
45
52
  return null;
46
53
  }
47
54
  async delete(key) {
48
- if (window.localStorage) {
55
+ if (typeof localStorage != "undefined") {
49
56
  localStorage.removeItem(key);
50
57
  return true;
51
58
  }
52
59
  return false;
53
60
  }
54
61
  async deleteAll() {
55
- if (window.localStorage) {
62
+ if (typeof localStorage != "undefined") {
56
63
  await localStorage.clear();
57
64
  return true;
58
65
  }
@@ -61,14 +68,12 @@ export class CSaveToLocalStorage {
61
68
  }
62
69
  export const CacheG = new CSaveToCache();
63
70
  export const CacheLocal = new CSaveToLocalStorage();
64
- async function addDataToMap(data, map) {
65
- if (data) {
66
- for (let [k, v] of data) {
67
- const tr = (map.get(k) || map.set(k, v).get(k));
68
- if (tr && typeof tr === 'object') {
69
- Object.assign(tr, v);
70
- renderBy(tr);
71
- }
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);
72
77
  }
73
78
  }
74
79
  }
@@ -88,17 +93,20 @@ export const ObjectStringToDate = (obj) => {
88
93
  });
89
94
  }
90
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)?$/;
91
98
  function isDate(_date) {
92
- const _regExp = new RegExp('^(-?(?:[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)?$');
93
- return _regExp.test(_date);
99
+ return ISO_DATE_RE.test(_date);
94
100
  }
95
101
  export function CacheFuncMapBase(arr, Save) {
96
102
  return {
97
103
  async load() {
98
104
  for (let [k, v] of arr) {
99
105
  const t = await Save.get(k);
106
+ if (!t)
107
+ continue;
100
108
  ObjectStringToDate(t);
101
- await addDataToMap(t, v);
109
+ addDataToMap(t, v);
102
110
  }
103
111
  },
104
112
  async save() {
@@ -7,5 +7,5 @@ interface IStepInputElement extends HTMLElement {
7
7
  export declare function SetAutoStepForElement(element: IStepInputElement, params?: {
8
8
  minStep?: number | undefined;
9
9
  maxStep?: number;
10
- }): void;
10
+ }): () => void;
11
11
  export {};
@@ -1,7 +1,18 @@
1
1
  /// <reference lib="dom" />
2
- // задать автоматическое управление шагом для элемента input
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(minDefault);
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
- //console.log("dotPos:",dotPos," _digits:",_digits, "minDigits:",minDigits);
44
- return step; ////lib.GetDblPrecision($fee[0].value)); }
52
+ return step;
45
53
  }
46
- let modeAuto = !_step || (_step < 1 && Math.log10(_step - Math.trunc(_step)) % 1 == 0); // является степенью 0.1
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
- //console.log("###",{value: element.value, modeAuto0, modeAuto, _step, _digits});
59
- //element.onkeydown= (e)=> { if (_step) element.step = "0.00000001"; /*String(_step/10);*/ console.log("keydown", {value: element.value}); }
60
- //element.onkeyup= ()=>{ if (_step) element.step= _step+""; console.log("keyup", {modeAuto, value: element.value, step: calculateStep(element.value), _digits}); if (modeAuto) calculateStep(element.value); }// console.log(element.step); }// console.log(element.value, element.step); }
61
- element.onkeyup = () => { if (modeAuto)
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
- }; //Math.round($fee[0].value/$fee[0].step)*$fee[0].step; }
76
- //element.onkeyup();
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,29 +36,29 @@ export function deepMergeWithMap(target, source, visited = new Map()) {
36
36
  }
37
37
  return target;
38
38
  }
39
- const map = new Map;
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 && !map.get(def)) {
42
- map.set(def, true);
43
- if (options.deepAutoMerge) {
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) ?? {}));
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) || staticProps.set(key, def).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) {
56
- const t = map.get(key);
57
- const el = { __id: id, data: def };
58
- if ((el && el.__id != id) || !el) {
59
- return staticGetAdd(key, el, { abs: true }).data;
55
+ const stored = staticProps.get(key);
56
+ if (!stored || stored.__id !== id) {
57
+ const fresh = { __id: id, data: def };
58
+ staticProps.set(key, fresh);
59
+ return fresh.data;
60
60
  }
61
- return el.data;
61
+ return stored.data;
62
62
  }
63
63
  export const Cash = CacheFuncMap([
64
64
  ["mapResiReact", mapResiReact],
@@ -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?: React.Dispatch<React.SetStateAction<T>> | ((a: T) => void)): void;
15
- export declare function updateBy<T extends object>(a: T, f?: React.Dispatch<React.SetStateAction<T>> | ((a: T) => void)): void;
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 {};