wenay-react2 1.0.20 → 1.0.22

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 (74) 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 +7 -6
  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 -105
  11. package/lib/common/src/components/Dnd/Resizable.js +3 -3
  12. package/lib/common/src/components/Menu/RightMenu.js +11 -17
  13. package/lib/common/src/components/Menu/StickerMenu.js +42 -28
  14. package/lib/common/src/components/Menu/index.d.ts +1 -1
  15. package/lib/common/src/components/Menu/index.js +1 -1
  16. package/lib/common/src/components/Modal/LeftModal.d.ts +14 -12
  17. package/lib/common/src/components/Modal/LeftModal.js +30 -16
  18. package/lib/common/src/components/Modal/Modal.d.ts +26 -12
  19. package/lib/common/src/components/Modal/Modal.js +66 -89
  20. package/lib/common/src/components/Modal/ModalContextProvider.d.ts +20 -3
  21. package/lib/common/src/components/Modal/ModalContextProvider.js +35 -8
  22. package/lib/common/src/components/MyResizeObserver.js +15 -18
  23. package/lib/common/src/components/Other.js +3 -2
  24. package/lib/common/src/components/Parameters.js +7 -6
  25. package/lib/common/src/components/ParametersEngine.js +25 -54
  26. package/lib/common/src/grid/agGrid4/agGrid4.d.ts +53 -0
  27. package/lib/common/src/grid/agGrid4/agGrid4.js +132 -0
  28. package/lib/common/src/grid/agGrid4/core.d.ts +56 -0
  29. package/lib/common/src/grid/agGrid4/core.js +127 -0
  30. package/lib/common/src/grid/agGrid4/index.d.ts +6 -0
  31. package/lib/common/src/grid/agGrid4/index.js +3 -0
  32. package/lib/common/src/grid/agGrid4/theme.d.ts +7 -0
  33. package/lib/common/src/grid/agGrid4/theme.js +18 -0
  34. package/lib/common/src/hooks/useAddDownAnyKey.d.ts +21 -2
  35. package/lib/common/src/hooks/useAddDownAnyKey.js +46 -8
  36. package/lib/common/src/hooks/useDraggable.d.ts +20 -2
  37. package/lib/common/src/hooks/useDraggable.js +146 -115
  38. package/lib/common/src/hooks/useOutside.d.ts +24 -4
  39. package/lib/common/src/hooks/useOutside.js +76 -27
  40. package/lib/common/src/logs/logs.d.ts +5 -2
  41. package/lib/common/src/logs/logs.js +15 -31
  42. package/lib/common/src/logs/logs3.d.ts +9 -9
  43. package/lib/common/src/logs/logs3.js +47 -38
  44. package/lib/common/src/logs/miniLogs.d.ts +3 -3
  45. package/lib/common/src/logs/miniLogs.js +28 -36
  46. package/lib/common/src/menu/menu.d.ts +18 -18
  47. package/lib/common/src/menu/menu.js +48 -24
  48. package/lib/common/src/menu/menuMouse.js +4 -1
  49. package/lib/common/src/menu/menuR.d.ts +2 -2
  50. package/lib/common/src/menu/menuR.js +34 -34
  51. package/lib/common/src/myChart/1/myChart.d.ts +5 -5
  52. package/lib/common/src/myChart/1/myChart.js +58 -47
  53. package/lib/common/src/myChart/1/myChartTest.js +8 -4
  54. package/lib/common/src/myChart/chartEngine/chartEngineReact.d.ts +24 -27
  55. package/lib/common/src/myChart/chartEngine/chartEngineReact.js +166 -117
  56. package/lib/common/src/styles/styleGrid.d.ts +2 -1
  57. package/lib/common/src/styles/styleGrid.js +10 -12
  58. package/lib/common/src/styles/tokens.d.ts +39 -0
  59. package/lib/common/src/styles/tokens.js +40 -0
  60. package/lib/common/src/utils/applyTransactionAsyncUpdate.d.ts +7 -0
  61. package/lib/common/src/utils/applyTransactionAsyncUpdate.js +19 -12
  62. package/lib/common/src/utils/arrayPromise.d.ts +6 -0
  63. package/lib/common/src/utils/arrayPromise.js +7 -1
  64. package/lib/common/src/utils/cache.js +24 -21
  65. package/lib/common/src/utils/inputAutoStep.d.ts +1 -1
  66. package/lib/common/src/utils/inputAutoStep.js +30 -19
  67. package/lib/common/src/utils/mapMemory.js +9 -10
  68. package/lib/common/updateBy.d.ts +21 -2
  69. package/lib/common/updateBy.js +66 -31
  70. package/lib/index.js +0 -2
  71. package/lib/style/menuRight.css +13 -26
  72. package/lib/style/style.css +51 -39
  73. package/lib/style/tokens.css +34 -0
  74. package/package.json +2 -2
@@ -1,38 +1,76 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useEffect, useRef, useState } from "react";
2
+ import React, { useEffect, useMemo, useRef, useState } from "react";
3
3
  export const StyleOtherRow = { display: "flex", flexDirection: "row", flex: "auto 1 1" };
4
4
  export const StyleOtherColum = { display: "flex", flexDirection: "column", flex: "auto 0 1" };
5
- export function useOutside({ outsideClick, ref, status = true }) {
6
- const internalRef = useRef(null); // useRef всегда в теле, не в дефолте параметра — иначе нарушаются Rules of Hooks
5
+ export function useOutsideApi(options) {
6
+ const { outsideClick, onOutside, ref, status = options.enabled ?? true } = options;
7
+ const internalRef = useRef(null); // useRef is always inside the body, not in a default parameter - otherwise it breaks the Rules of Hooks
7
8
  const r = ref ?? internalRef;
9
+ const outsideClickRef = useRef(outsideClick ?? onOutside);
10
+ const [enabled, setEnabled] = useState(status);
11
+ const enabledRef = useRef(enabled);
12
+ outsideClickRef.current = outsideClick ?? onOutside;
13
+ enabledRef.current = enabled;
8
14
  useEffect(() => {
9
- if (status) {
10
- function handleClickOutside(event) {
11
- if (r.current && event.target instanceof Node && !r.current.contains(event.target))
12
- outsideClick();
13
- }
14
- document.addEventListener("mousedown", handleClickOutside);
15
- return () => document.removeEventListener("mousedown", handleClickOutside);
15
+ setEnabled(status);
16
+ }, [status]);
17
+ useEffect(() => {
18
+ function handleClickOutside(event) {
19
+ if (!enabledRef.current)
20
+ return;
21
+ if (r.current && event.target instanceof Node && !r.current.contains(event.target))
22
+ outsideClickRef.current?.();
16
23
  }
17
- }, [r, status, outsideClick]);
18
- return r;
24
+ document.addEventListener("mousedown", handleClickOutside);
25
+ document.addEventListener("touchstart", handleClickOutside);
26
+ return () => {
27
+ document.removeEventListener("mousedown", handleClickOutside);
28
+ document.removeEventListener("touchstart", handleClickOutside);
29
+ };
30
+ }, [r]);
31
+ const props = useMemo(() => ({ ref: r }), [r]);
32
+ return useMemo(() => {
33
+ const api = {
34
+ ref: r,
35
+ props,
36
+ bind: props,
37
+ contains(target) {
38
+ return !!(r.current && target instanceof Node && r.current.contains(target));
39
+ },
40
+ enable() { setEnabled(true); },
41
+ disable() { setEnabled(false); },
42
+ get enabled() { return enabledRef.current; },
43
+ };
44
+ Object.defineProperty(api, "current", {
45
+ configurable: true,
46
+ get: () => r.current,
47
+ set: (node) => { r.current = node; },
48
+ });
49
+ return api;
50
+ }, [props, r]);
51
+ }
52
+ export function useOutside(options) {
53
+ return useOutsideApi(options);
54
+ }
55
+ /** @deprecated Use `useOutside(options)` and read `api.ref`, `api.props`, or `api.current`. */
56
+ export function useOutsideOld(options) {
57
+ return useOutsideApi(options).ref;
19
58
  }
20
59
  export const DivOutsideClick = React.forwardRef(({ children, outsideClick, zIndex, style = {}, status = true, ...other }, forwardedRef) => {
21
60
  const style2 = zIndex ? { ...style, zIndex } : style;
22
61
  const internalRef = useOutside({ outsideClick: outsideClick, status });
23
- // Combine refs if forwardedRef is provided
24
- const ref = forwardedRef
25
- ? (node) => {
26
- internalRef.current = node;
27
- if (typeof forwardedRef === 'function') {
28
- forwardedRef(node);
29
- }
30
- else if (forwardedRef) {
31
- forwardedRef.current = node;
32
- }
62
+ // Combine refs if forwardedRef is provided; stable identity, otherwise React
63
+ // re-runs the ref (null + node) on every render
64
+ const combinedRef = React.useCallback((node) => {
65
+ internalRef.current = node;
66
+ if (typeof forwardedRef === 'function') {
67
+ forwardedRef(node);
33
68
  }
34
- : internalRef;
35
- return _jsx("div", { ref: ref, style: style2, ...other, children: children });
69
+ else if (forwardedRef) {
70
+ forwardedRef.current = node;
71
+ }
72
+ }, [forwardedRef, internalRef]);
73
+ return _jsx("div", { ref: forwardedRef ? combinedRef : internalRef, style: style2, ...other, children: children });
36
74
  });
37
75
  // Deprecated: Use DivOutsideClick instead
38
76
  export const DivOutsideClick2 = DivOutsideClick;
@@ -41,9 +79,20 @@ function ButtonBase({ children, button, style = {}, className = "", state: [a, s
41
79
  }
42
80
  const saveStatus = {};
43
81
  export function Button({ keySave, statusDef, outClick, ...data }) {
44
- if (keySave && saveStatus[keySave])
82
+ // The keySave feature was dead: saveStatus was read but not written. Now status
83
+ // persists in memory for the session on each toggle.
84
+ if (keySave && saveStatus[keySave] != null)
45
85
  statusDef = saveStatus[keySave];
46
- const state = useState(statusDef ?? false);
86
+ const [status, setStatusRaw] = useState(statusDef ?? false);
87
+ const setStatus = (v) => {
88
+ setStatusRaw(prev => {
89
+ const next = typeof v === "function" ? v(prev) : v;
90
+ if (keySave)
91
+ saveStatus[keySave] = next;
92
+ return next;
93
+ });
94
+ };
95
+ const state = [status, setStatus];
47
96
  const handleOutsideClick = () => {
48
97
  state[1](false);
49
98
  if (typeof outClick == "function")
@@ -53,7 +102,7 @@ export function Button({ keySave, statusDef, outClick, ...data }) {
53
102
  }
54
103
  export function ButtonHover(props) {
55
104
  const [hover, setHover] = useState(false);
56
- return _jsxs("div", { onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: { position: "relative" }, children: [typeof props.button == "function" ? props.button(hover) : props.button, hover &&
105
+ return _jsxs("div", { onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: { position: "relative", width: "min-content" }, children: [typeof props.button == "function" ? props.button(hover) : props.button, hover &&
57
106
  _jsx("div", { style: { position: "absolute" }, children: typeof props.children == "function" ? props.children({ onClose: () => setHover(false) }) : props.children })] });
58
107
  }
59
108
  export const ButtonOutClick = ({ outClick = true, ...a }) => Button({ ...a, outClick });
@@ -89,7 +89,7 @@ export declare function getLogsApi<T extends object = {}>(setting: {
89
89
  set(a: Params.SimpleParams<ReturnType<typeof getSettingLogs>>): void;
90
90
  };
91
91
  React: {
92
- Setting: ({}: {}) => import("react/jsx-runtime").JSX.Element;
92
+ Setting: typeof InputSettingLogs;
93
93
  Message: typeof MessageEventLogs;
94
94
  PageLogs: typeof PageLogs;
95
95
  };
@@ -146,11 +146,14 @@ export declare const logsApi: {
146
146
  set(a: Params.SimpleParams<ReturnType<typeof getSettingLogs>>): void;
147
147
  };
148
148
  React: {
149
- Setting: ({}: {}) => import("react/jsx-runtime").JSX.Element;
149
+ Setting: typeof InputSettingLogs;
150
150
  Message: typeof MessageEventLogs;
151
151
  PageLogs: typeof PageLogs;
152
152
  };
153
153
  };
154
+ declare function InputSettingLogs({}: {
155
+ update?: number;
156
+ }): import("react/jsx-runtime").JSX.Element;
154
157
  export declare function PageLogs({ update }: {
155
158
  update?: number;
156
159
  }): import("react/jsx-runtime").JSX.Element;
@@ -14,13 +14,13 @@ const datumMiniConst = {
14
14
  last: []
15
15
  };
16
16
  const getSettingLogs = () => ({
17
- minVarLogs: { name: "мин. важность для оповещения", range: { min: 0, max: 25, step: 1 }, value: 0 },
18
- minVarMessage: { name: "мин. важность для таблицы логов", range: { min: 0, max: 25, step: 1 }, value: 0 },
19
- timeShow: { name: "время отображение на экране", range: { min: 1, max: 20, step: 1 }, value: 2 },
20
- show: { name: "отображать", value: true }
17
+ minVarLogs: { name: "min. importance for notifications", range: { min: 0, max: 25, step: 1 }, value: 0 },
18
+ minVarMessage: { name: "min. importance for log table", range: { min: 0, max: 25, step: 1 }, value: 0 },
19
+ timeShow: { name: "screen display time", range: { min: 1, max: 20, step: 1 }, value: 2 },
20
+ show: { name: "show", value: true }
21
21
  });
22
22
  const settingLogs = { params: Params.GetSimpleParams(getSettingLogs()) };
23
- // varMin - минимальная важность
23
+ // varMin - minimum importance
24
24
  export function getLogsApi(setting) {
25
25
  const datum = staticGetAdd("settingLogs", settingLogs);
26
26
  function addToArr(arr, data, limit) {
@@ -29,18 +29,10 @@ export function getLogsApi(setting) {
29
29
  arr.length = limit;
30
30
  }
31
31
  let num = 0;
32
- const SettingLogsReact = ({}) => _jsx(ParametersReact
33
- // @ts-ignore
34
- , {
35
- // @ts-ignore
36
- params: Params.mergeParamValuesToInfos(getSettingLogs(), datum.params), onChange: (e) => {
37
- datum.params = Params.GetSimpleParams(e);
38
- renderBy(datum);
39
- } });
40
32
  return {
41
33
  addLogs(a) {
42
34
  const item = { ...a, num: num++ };
43
- addToArr(datumMiniConst.last, item, 50);
35
+ addToArr(datumMiniConst.last, item, setting.limit ?? 50);
44
36
  addToArr(datumConst.map.get(a.id) ?? datumConst.map.set(a.id, []).get(a.id), item, setting.limitPer);
45
37
  renderBy(datumConst);
46
38
  renderBy(datumMiniConst);
@@ -55,7 +47,7 @@ export function getLogsApi(setting) {
55
47
  },
56
48
  },
57
49
  React: {
58
- Setting: SettingLogsReact,
50
+ Setting: InputSettingLogs,
59
51
  Message: MessageEventLogs,
60
52
  PageLogs: PageLogs
61
53
  }
@@ -75,10 +67,7 @@ function InputSettingLogs({}) {
75
67
  }
76
68
  export function PageLogs({ update }) {
77
69
  const datumFull = datumConst;
78
- const rowData = [...datumFull.map.values()].flatMap(e => e.map(e => ({
79
- ...e,
80
- time: (e.time)
81
- })));
70
+ const rowData = [...datumFull.map.values()].flat();
82
71
  const datum = datumMiniConst;
83
72
  const setting = staticGetAdd("settingLogs", settingLogs);
84
73
  const apiGrid = useRef(null);
@@ -103,12 +92,7 @@ export function PageLogs({ update }) {
103
92
  const data = datum.last[0];
104
93
  if (data) { // data.time timeLocalToStr_yyyymmdd_hhmmss_ms
105
94
  apiGrid.current?.api.applyTransactionAsync({
106
- add: [
107
- {
108
- ...data,
109
- time: data.time
110
- }
111
- ]
95
+ add: [{ ...data }]
112
96
  });
113
97
  }
114
98
  });
@@ -193,7 +177,7 @@ function Message({ logs }) {
193
177
  let red = (logs.var ?? 0) * 10;
194
178
  if (red > 255)
195
179
  red = 255;
196
- return _jsxs("div", { className: "testAnime", style: { width: "200px", color: "rgb(255,255,255)", height: "auto", marginTop: "10px", borderRight: "5px solid #5D9FFA", background: `rgb(${red},73,35)` }, children: [_jsx("p", { style: { textAlign: "center", fontSize: "10px", marginBottom: "1px" }, children: "оповещение" }), _jsx("hr", { style: {
180
+ return _jsxs("div", { className: "testAnime", style: { width: "200px", color: "rgb(255,255,255)", height: "auto", marginTop: "10px", borderRight: "5px solid #5D9FFA", background: `rgb(${red},73,35)` }, children: [_jsx("p", { style: { textAlign: "center", fontSize: "10px", marginBottom: "1px" }, children: "notification" }), _jsx("hr", { style: {
197
181
  backgroundImage: "linear-gradient(to right, transparent, rgba(255, 255, 255, 1), transparent)",
198
182
  border: 0,
199
183
  height: "1px",
@@ -205,11 +189,12 @@ function Message({ logs }) {
205
189
  const tt = {};
206
190
  let r = 0;
207
191
  export function MessageEventLogs({ zIndex }) {
208
- let max = 8;
209
192
  const setting = staticGetAdd("settingLogs", settingLogs);
210
193
  updateBy(tt);
211
194
  updateBy(datumMiniConst, () => {
212
195
  const last = datumMiniConst.last[0];
196
+ if (!last)
197
+ return;
213
198
  if (setting.params.minVarMessage && (!last.var || last.var < setting.params.minVarMessage))
214
199
  return;
215
200
  let key = String(r++);
@@ -217,18 +202,17 @@ export function MessageEventLogs({ zIndex }) {
217
202
  setTimeout(() => {
218
203
  if (tt[key]) {
219
204
  delete tt[key];
220
- if (Object.values(tt).length < max)
221
- renderBy(tt);
205
+ renderBy(tt, 100);
222
206
  }
223
207
  }, setting.params.timeShow ? setting.params.timeShow * 1000 : 2000);
224
208
  renderBy(tt);
225
209
  });
226
210
  const tr = [...Object.values(tt)].reverse().slice(0, 10);
227
- return _jsxs("div", { style: { maxHeight: "50vh", position: "absolute", right: "1px", zIndex }, children: [tr && _jsx("div", { onClick: () => { setting.params.show = !setting.params.show; renderBy(tt); }, style: { margin: 3, padding: 3, right: 0, position: "absolute", zIndex: 120,
211
+ return _jsxs("div", { style: { maxHeight: "50vh", position: "absolute", right: "1px", zIndex }, children: [_jsx("div", { onClick: () => { setting.params.show = !setting.params.show; renderBy(tt); }, style: { margin: 3, padding: 3, right: 0, position: "absolute", zIndex: 120,
228
212
  ...setting.params.show ?
229
213
  { background: "rgb(58,58,58)", fontSize: "25px" } :
230
214
  { background: "rgb(144,60,60)" }
231
- }, children: setting.params.show ? "X" : "log" }), tr && _jsx("div", { children: setting.params.show ? [...Object.values(tt)].reverse().slice(0, 10) : null })] });
215
+ }, children: setting.params.show ? "X" : "log" }), _jsx("div", { children: setting.params.show ? tr : null })] });
232
216
  }
233
217
  const defPageBase = {
234
218
  keyPage: "PageLogs"
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  /** -----------------------------
3
- * 1. Типы для логов
3
+ * 1. Log types
4
4
  * -----------------------------
5
5
  */
6
6
  export interface tLogsInput<T extends object = {}> {
@@ -14,7 +14,7 @@ export interface tLogs<T extends object = {}> extends tLogsInput<T> {
14
14
  num: number;
15
15
  }
16
16
  /** -----------------------------
17
- * 3. Интерфейс контекста
17
+ * 3. Context interface
18
18
  * -----------------------------
19
19
  */
20
20
  interface LogsContextValue {
@@ -33,30 +33,30 @@ export declare function LogsProvider({ children }: {
33
33
  children: React.ReactNode;
34
34
  }): import("react/jsx-runtime").JSX.Element;
35
35
  /** -----------------------------
36
- * 5. Хук для удобного доступа к контексту
36
+ * 5. Hook for convenient context access
37
37
  * -----------------------------
38
38
  */
39
39
  export declare function useLogsContext(): LogsContextValue;
40
40
  /** -----------------------------
41
- * 6. Компонент LogsTable
42
- * (аналог PageLogs)
41
+ * 6. LogsTable component
42
+ * (PageLogs equivalent)
43
43
  * -----------------------------
44
44
  */
45
45
  export declare function LogsTable(): import("react/jsx-runtime").JSX.Element;
46
46
  export declare function LogsNotifications(): import("react/jsx-runtime").JSX.Element;
47
47
  /** -----------------------------
48
- * 8. Компонент LogsSettings
49
- * (аналог InputSettingLogs)
48
+ * 8. LogsSettings component
49
+ * (InputSettingLogs equivalent)
50
50
  * -----------------------------
51
51
  */
52
52
  export declare function LogsSettings(): import("react/jsx-runtime").JSX.Element;
53
53
  /** -----------------------------
54
- * 9. MainPage вкладки (Таблица / Настройки)
54
+ * 9. MainPage - tabs (Table / Settings)
55
55
  * -----------------------------
56
56
  */
57
57
  export declare function MainPage(): import("react/jsx-runtime").JSX.Element;
58
58
  /** -----------------------------
59
- * 10. Корневой компонент App
59
+ * 10. Root App component
60
60
  * -----------------------------
61
61
  */
62
62
  export default function AppLogs(): import("react/jsx-runtime").JSX.Element;
@@ -2,52 +2,52 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { AgGridReact } from 'ag-grid-react';
4
4
  /** -----------------------------
5
- * 2. Функция staticGetAdd
6
- * загружает/сохраняет данные в localStorage.
5
+ * 2. staticGetAdd function -
6
+ * loads and saves data in localStorage.
7
7
  * -----------------------------
8
8
  */
9
9
  function staticGetAdd(key, defaultValue) {
10
10
  try {
11
11
  const stored = localStorage.getItem(key);
12
- // Если в localStorage ничего нет, то записываем defaultValue
12
+ // If localStorage has no value, write defaultValue
13
13
  if (!stored) {
14
14
  localStorage.setItem(key, JSON.stringify(defaultValue));
15
15
  return defaultValue;
16
16
  }
17
- // Если что-то нашли, пытаемся объединить с defaultValue
18
- // (на случай, если в defaultValue появились новые поля)
17
+ // If a value was found, try to merge it with defaultValue
18
+ // in case new fields were added to defaultValue
19
19
  const parsed = JSON.parse(stored);
20
20
  return { ...defaultValue, ...parsed };
21
21
  }
22
22
  catch (error) {
23
- console.error("Ошибка чтения localStorage:", error);
23
+ console.error("localStorage read error:", error);
24
24
  return defaultValue;
25
25
  }
26
26
  }
27
27
  /** -----------------------------
28
- * 4. Создаём сам контекст
29
- * и провайдер для логов + настроек
28
+ * 4. Create the context itself
29
+ * and provider for logs and settings
30
30
  * -----------------------------
31
31
  */
32
32
  const LogsContext = createContext(null);
33
33
  export function LogsProvider({ children }) {
34
- // 4.1. Загружаем настройки из localStorage через staticGetAdd
35
- const savedSettings = staticGetAdd("logSettings", {
34
+ // 4.1. Load settings from localStorage once (lazy init: the provider rerenders on every addLog)
35
+ const [savedSettings] = useState(() => staticGetAdd("logSettings", {
36
36
  minVarLogs: 0,
37
37
  minVarMessage: 0,
38
38
  timeShow: 2,
39
39
  showMessages: true
40
- });
41
- // 4.2. Список логов в памяти (не сохраняем логи в localStorage,
42
- // только настройки но можно и логи, если нужно)
40
+ }));
41
+ // 4.2. In-memory log list (logs are not saved to localStorage,
42
+ // only settings are, but logs can be saved too if needed)
43
43
  const [logs, setLogs] = useState([]);
44
44
  const counterRef = useRef(0);
45
- // 4.3. Сами настройки (инициализируем тем, что вернул staticGetAdd)
45
+ // 4.3. Settings themselves, initialized from staticGetAdd output
46
46
  const [minVarLogs, setMinVarLogs] = useState(savedSettings.minVarLogs);
47
47
  const [minVarMessage, setMinVarMessage] = useState(savedSettings.minVarMessage);
48
48
  const [timeShow, setTimeShow] = useState(savedSettings.timeShow);
49
49
  const [showMessages, setShowMessages] = useState(savedSettings.showMessages);
50
- // 4.4. Следим за изменениями настроек и сохраняем их обратно в localStorage
50
+ // 4.4. Watch settings changes and save them back to localStorage
51
51
  useEffect(() => {
52
52
  const toSave = {
53
53
  minVarLogs,
@@ -57,17 +57,17 @@ export function LogsProvider({ children }) {
57
57
  };
58
58
  localStorage.setItem("logSettings", JSON.stringify(toSave));
59
59
  }, [minVarLogs, minVarMessage, timeShow, showMessages]);
60
- // 4.5. Функция добавления лога (генерируем поле num автоматически)
60
+ // 4.5. Function for adding a log, generates the num field automatically
61
61
  const addLog = useCallback((input) => {
62
62
  counterRef.current += 1;
63
63
  const num = counterRef.current;
64
64
  setLogs((prevLogs) => {
65
65
  const newLog = { ...input, num };
66
- // ограничимся 500 логами (можно менять)
66
+ // Limit to 500 logs; this can be changed
67
67
  return [newLog, ...prevLogs].slice(0, 500);
68
68
  });
69
69
  }, []);
70
- // 4.6. Возвращаем провайдер контекста
70
+ // 4.6. Return the context provider
71
71
  return (_jsx(LogsContext.Provider, { value: {
72
72
  logs,
73
73
  addLog,
@@ -82,7 +82,7 @@ export function LogsProvider({ children }) {
82
82
  }, children: children }));
83
83
  }
84
84
  /** -----------------------------
85
- * 5. Хук для удобного доступа к контексту
85
+ * 5. Hook for convenient context access
86
86
  * -----------------------------
87
87
  */
88
88
  export function useLogsContext() {
@@ -93,18 +93,18 @@ export function useLogsContext() {
93
93
  return ctx;
94
94
  }
95
95
  /** -----------------------------
96
- * 6. Компонент LogsTable
97
- * (аналог PageLogs)
96
+ * 6. LogsTable component
97
+ * (PageLogs equivalent)
98
98
  * -----------------------------
99
99
  */
100
100
  export function LogsTable() {
101
101
  const { logs, minVarLogs } = useLogsContext();
102
102
  const gridRef = useRef(null);
103
- // Определения колонок
103
+ // Column definitions
104
104
  const columnDefs = useMemo(() => [
105
105
  {
106
106
  field: 'time',
107
- headerName: 'Время',
107
+ headerName: 'Time',
108
108
  sort: 'desc',
109
109
  valueFormatter: (params) => {
110
110
  const dateObj = params.value;
@@ -115,10 +115,10 @@ export function LogsTable() {
115
115
  width: 120,
116
116
  },
117
117
  { field: 'id', headerName: 'ID', width: 80 },
118
- { field: 'var', headerName: 'Важность', width: 90 },
118
+ { field: 'var', headerName: 'Importance', width: 90 },
119
119
  {
120
120
  field: 'txt',
121
- headerName: 'Сообщение',
121
+ headerName: 'Message',
122
122
  flex: 1,
123
123
  wrapText: true,
124
124
  autoHeight: true
@@ -130,7 +130,7 @@ export function LogsTable() {
130
130
  filter: true,
131
131
  wrapText: true,
132
132
  }), []);
133
- // Следим за minVarLogs и настраиваем фильтр AG Grid
133
+ // Watch minVarLogs and configure the AG Grid filter
134
134
  useEffect(() => {
135
135
  if (gridRef.current?.api) {
136
136
  if (minVarLogs > 0) {
@@ -158,30 +158,39 @@ export function LogsNotifications() {
158
158
  const { logs, minVarMessage, timeShow, showMessages, setShowMessages } = useLogsContext();
159
159
  const [notifications, setNotifications] = useState([]);
160
160
  const counterRef = useRef(0);
161
+ const lastLogRef = useRef(null);
162
+ const timersRef = useRef(new Set());
161
163
  useEffect(() => {
162
164
  if (logs.length === 0)
163
165
  return;
164
166
  const newestLog = logs[0];
167
+ // gate by log identity: a settings change must not re-add the same log
168
+ if (newestLog === lastLogRef.current)
169
+ return;
170
+ lastLogRef.current = newestLog;
165
171
  if ((newestLog.var ?? 0) < minVarMessage)
166
172
  return;
167
173
  counterRef.current += 1;
168
174
  const newItem = { id: counterRef.current, log: newestLog };
169
175
  setNotifications((prev) => [newItem, ...prev]);
170
- // убираем нотификацию через timeShow секунд
176
+ // Remove notification after timeShow seconds; per-item timers are NOT cancelled
177
+ // when the next log arrives - the old cleanup froze every notification but the last
171
178
  const timer = setTimeout(() => {
179
+ timersRef.current.delete(timer);
172
180
  setNotifications((prev) => prev.filter((item) => item.id !== newItem.id));
173
181
  }, timeShow * 1000);
174
- return () => clearTimeout(timer);
182
+ timersRef.current.add(timer);
175
183
  }, [logs, minVarMessage, timeShow]);
184
+ useEffect(() => () => { timersRef.current.forEach(clearTimeout); }, []);
176
185
  if (!showMessages) {
177
- // Если скрыли всплывашки, показываем только "log"
186
+ // If popups are hidden, show only "log"
178
187
  return (_jsx("div", { style: { position: 'absolute', right: 10, top: 10, zIndex: 999 }, children: _jsx("div", { style: {
179
188
  background: 'rgb(144,60,60)',
180
189
  padding: '6px 10px',
181
190
  cursor: 'pointer'
182
191
  }, onClick: () => setShowMessages(true), children: "log" }) }));
183
192
  }
184
- // Иначе выводим список текущих нотификаций
193
+ // Otherwise render the current notification list
185
194
  return (_jsxs("div", { style: { position: 'absolute', right: 10, top: 10, zIndex: 999 }, children: [_jsx("div", { style: {
186
195
  background: 'rgb(58,58,58)',
187
196
  fontSize: '20px',
@@ -199,7 +208,7 @@ export function LogsNotifications() {
199
208
  backgroundColor: `rgb(${red},73,35)`,
200
209
  padding: 8,
201
210
  wordWrap: 'break-word'
202
- }, children: [_jsx("p", { style: { textAlign: 'center', fontSize: 10, marginBottom: 1 }, children: "\u043E\u043F\u043E\u0432\u0435\u0449\u0435\u043D\u0438\u0435" }), _jsx("hr", { style: {
211
+ }, children: [_jsx("p", { style: { textAlign: 'center', fontSize: 10, marginBottom: 1 }, children: "notification" }), _jsx("hr", { style: {
203
212
  backgroundImage: 'linear-gradient(to right, transparent, rgba(255, 255, 255, 1), transparent)',
204
213
  border: 0,
205
214
  height: 1,
@@ -208,16 +217,16 @@ export function LogsNotifications() {
208
217
  }) })] }));
209
218
  }
210
219
  /** -----------------------------
211
- * 8. Компонент LogsSettings
212
- * (аналог InputSettingLogs)
220
+ * 8. LogsSettings component
221
+ * (InputSettingLogs equivalent)
213
222
  * -----------------------------
214
223
  */
215
224
  export function LogsSettings() {
216
225
  const { minVarLogs, setMinVarLogs, minVarMessage, setMinVarMessage, timeShow, setTimeShow, showMessages, setShowMessages } = useLogsContext();
217
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, padding: 10 }, children: [_jsxs("label", { children: ["\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0432\u0430\u0436\u043D\u043E\u0441\u0442\u044C \u0434\u043B\u044F ", _jsx("b", { children: "\u0442\u0430\u0431\u043B\u0438\u0446\u044B" }), " (minVarLogs):", _jsx("input", { type: "number", value: minVarLogs, onChange: (e) => setMinVarLogs(Number(e.target.value)), style: { marginLeft: 8 } })] }), _jsxs("label", { children: ["\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0432\u0430\u0436\u043D\u043E\u0441\u0442\u044C \u0434\u043B\u044F ", _jsx("b", { children: "\u043E\u043F\u043E\u0432\u0435\u0449\u0435\u043D\u0438\u0439" }), " (minVarMessage):", _jsx("input", { type: "number", value: minVarMessage, onChange: (e) => setMinVarMessage(Number(e.target.value)), style: { marginLeft: 8 } })] }), _jsxs("label", { children: ["\u0412\u0440\u0435\u043C\u044F \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F (\u0441\u0435\u043A) (timeShow):", _jsx("input", { type: "number", value: timeShow, onChange: (e) => setTimeShow(Number(e.target.value)), style: { marginLeft: 8 } })] }), _jsxs("label", { children: ["\u041E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0442\u044C \u0432\u0441\u043F\u043B\u044B\u0432\u0430\u0448\u043A\u0438 (showMessages):", _jsx("input", { type: "checkbox", checked: showMessages, onChange: (e) => setShowMessages(e.target.checked), style: { marginLeft: 8 } })] })] }));
226
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, padding: 10 }, children: [_jsxs("label", { children: ["Minimum importance for the ", _jsx("b", { children: "table" }), " (minVarLogs):", _jsx("input", { type: "number", value: minVarLogs, onChange: (e) => setMinVarLogs(Number(e.target.value)), style: { marginLeft: 8 } })] }), _jsxs("label", { children: ["Minimum importance for ", _jsx("b", { children: "notifications" }), " (minVarMessage):", _jsx("input", { type: "number", value: minVarMessage, onChange: (e) => setMinVarMessage(Number(e.target.value)), style: { marginLeft: 8 } })] }), _jsxs("label", { children: ["Display time (sec) (timeShow):", _jsx("input", { type: "number", value: timeShow, onChange: (e) => setTimeShow(Number(e.target.value)), style: { marginLeft: 8 } })] }), _jsxs("label", { children: ["Show popups (showMessages):", _jsx("input", { type: "checkbox", checked: showMessages, onChange: (e) => setShowMessages(e.target.checked), style: { marginLeft: 8 } })] })] }));
218
227
  }
219
228
  /** -----------------------------
220
- * 9. MainPage вкладки (Таблица / Настройки)
229
+ * 9. MainPage - tabs (Table / Settings)
221
230
  * -----------------------------
222
231
  */
223
232
  export function MainPage() {
@@ -228,16 +237,16 @@ export function MainPage() {
228
237
  border: 'none',
229
238
  padding: '8px',
230
239
  cursor: 'pointer'
231
- }, children: "\u0422\u0430\u0431\u043B\u0438\u0446\u0430 \u043B\u043E\u0433\u043E\u0432" }), _jsx("button", { onClick: () => setCurrentTab('settings'), style: {
240
+ }, children: "Log table" }), _jsx("button", { onClick: () => setCurrentTab('settings'), style: {
232
241
  backgroundColor: currentTab === 'settings' ? '#666' : '#444',
233
242
  color: 'white',
234
243
  border: 'none',
235
244
  padding: '8px',
236
245
  cursor: 'pointer'
237
- }, children: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438" })] }), _jsxs("div", { style: { flex: 1, position: 'relative' }, children: [currentTab === 'table' && _jsx(LogsTable, {}), currentTab === 'settings' && _jsx(LogsSettings, {})] })] }));
246
+ }, children: "Settings" })] }), _jsxs("div", { style: { flex: 1, position: 'relative' }, children: [currentTab === 'table' && _jsx(LogsTable, {}), currentTab === 'settings' && _jsx(LogsSettings, {})] })] }));
238
247
  }
239
248
  /** -----------------------------
240
- * 10. Корневой компонент App
249
+ * 10. Root App component
241
250
  * -----------------------------
242
251
  */
243
252
  export default function AppLogs() {
@@ -1,5 +1,5 @@
1
1
  import { CellMouseDownEvent } from "ag-grid-community";
2
- export declare function MiniLogs({ data, onClick }: {
3
- data: any[];
4
- onClick?: (e: CellMouseDownEvent<any, any>) => any;
2
+ export declare function MiniLogs<T = any>({ data, onClick }: {
3
+ data: T[];
4
+ onClick?: (e: CellMouseDownEvent<T>) => any;
5
5
  }): import("react/jsx-runtime").JSX.Element;