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.
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
package/README.md CHANGED
@@ -1,383 +1,384 @@
1
- Вот расширенное руководство по API типизацией и примерами использования). Этот формат отлично подойдет для документации, чтобы другие разработчики (или AI-ассистенты) могли сразу понимать, какие пропсы принимает компонент и как его внедрять.
2
-
3
- ---
4
-
5
- ## 🛠 Справочник API (Components & Hooks)
6
-
7
- ### 🪟 Модальные и плавающие окна (MDI)
8
-
9
- #### `DivRnd3`
10
- Обертка для создания окон со свободным перемещением, изменением размеров (resize) и сохранением состояния.
11
-
12
- **Типизация:**
13
- ```typescript
14
- type tDivRndBase = {
15
- children: React.ReactElement | ((update: number) => React.ReactElement);
16
- position?: { x: number; y: number };
17
- size?: { height: number | string; width: number | string };
18
- keyForSave?: string; // Ключ для кэширования позиции/размера в памяти
19
- limit?: { x?: { max?: number; min?: number }, y?: { max?: number; min?: number } };
20
- onCLickClose?: () => void; // Добавляет крестик закрытия окна
21
- header?: React.ReactElement | boolean; // Шапка для перетаскивания (иначе тянется за весь блок)
22
- zIndex?: number;
23
- }
24
- ```
25
-
26
- **Пример:**
27
- ```textmate
28
- <DivRnd3
29
- keyForSave="my_tool_window"
30
- size={{ width: 300, height: 200 }}
31
- onCLickClose={() => setOpen(false)}
32
- header={<div>Мой инструмент</div>}
33
- >
34
- <div>Контент окна</div>
35
- </DivRnd3>
36
- ```
37
-
38
-
39
- #### `GetModalJSX()`
40
- Фабрика глобальных модальных окон. Позволяет вызывать окна из бизнес-логики без привязки к локальному стейту компонента.
41
-
42
- **Пример:**
43
- ```textmate
44
- const myModal = GetModalJSX();
45
-
46
- // 1. В корневом файле приложения (App.tsx):
47
- <myModal.Render />
48
-
49
- // 2. В любом месте логики:
50
- myModal.set(<div onClick={() => myModal.set(null)}>Закрыть меня</div>);
51
- // Для множественных окон: myModal.addJSX( <Component/> )
52
- ```
53
-
54
-
55
- ---
56
-
57
- ### 🖱 Drag-and-Drop и Взаимодействие (Hooks & Wrappers)
58
-
59
- #### `useOutside` / `DivOutsideClick`
60
- Отслеживание клика вне элемента (полезно для закрытия дропдаунов и меню).
61
-
62
- **Типизация:**
63
- ```typescript
64
- // Hook
65
- function useOutside(params: { outsideClick: () => void, status?: boolean, ref?: RefObject }): RefObject;
66
-
67
- // Component
68
- type Props = { outsideClick: () => void, status?: boolean, zIndex?: number } & HTMLAttributes;
69
- ```
70
-
71
- **Пример:**
72
- ```textmate
73
- <DivOutsideClick outsideClick={() => setDropdownOpen(false)} status={isOpen}>
74
- <div className="dropdown-menu">...</div>
75
- </DivOutsideClick>
76
- ```
77
-
78
-
79
- #### `Drag22`
80
- Отслеживает сдвиг мыши/пальца и возвращает новые координаты, не вмешиваясь в CSS напрямую.
81
-
82
- **Типизация:**
83
- ```typescript
84
- type Drag2Props = {
85
- x?: number; y?: number; // Стартовые/текущие координаты
86
- onX?: (val: number) => void; // Коллбек изменения X
87
- onY?: (val: number) => void; // Коллбек изменения Y
88
- onStart?: () => void; onStop?: () => void;
89
- children: ReactNode;
90
- };
91
- ```
92
-
93
-
94
- ---
95
-
96
- ### 📋 Контекстные меню (`MenuR` / `mouseMenuApi`)
97
-
98
- Умные контекстные меню. Вызываются на ПК (ПКМ) и мобилках (долгий тап / дабл-тап). Поддерживают асинхронную генерацию элементов.
99
-
100
- **Типизация элемента меню (`tMenuReactStrictly`):**
101
- ```typescript
102
- type tMenuReactStrictly = {
103
- name: string | ((status?: any) => string);
104
- onClick?: (e: any) => void | Promise<any> | Promise<any>[]; // Поддержка промисов со счетчиком ok/error
105
- status?: boolean; // Раскрыто ли подменю
106
- next?: () => tMenuReact[] | Promise<tMenuReact[]>; // Вложенное меню
107
- func?: () => React.ReactElement | Promise<React.ReactElement>; // Кастомный рендер при наведении
108
- };
109
- ```
110
-
111
- **Примеры:**
112
- ```textmate
113
- // 1. Использование компонента-обертки
114
- const menuItems = () => [
115
- { name: "Копировать", onClick: () => copy() },
116
- { name: "Опции", next: () => [{ name: "Опция 1", onClick: () => {} }] }
117
- ];
118
-
119
- <MenuR other={menuItems}>
120
- <div className="item">Кликни меня правой кнопкой</div>
121
- </MenuR>
122
-
123
- // 2. Глобальный вызов через API
124
- mouseMenuApi.map.set("global_action", [{ name: "Глобальное действие", onClick: () => {} }]);
125
- ```
126
-
127
-
128
- ---
129
-
130
- ### 📊 Обновление таблиц Ag-Grid (`applyTransactionAsyncUpdate2`)
131
-
132
- Функция для безопасного, пакетного и асинхронного обновления данных таблицы, синхронизированного с локальным буфером (кэшем).
133
-
134
- **Типизация:**
135
- ```typescript
136
- type Params<T> = {
137
- gridRef?: React.RefObject<GridReadyEvent<T, any>>;
138
- newData: Partial<T>[]; // Массив новых данных
139
- getId: (row: Partial<T>) => string; // Функция получения ID
140
- bufTable: { [id: string]: Partial<T> }; // Локальный кэш-словарь
141
- option?: { update?: boolean, add?: boolean, updateBuffer?: boolean, sync?: boolean };
142
- };
143
- ```
144
-
145
- **Пример:**
146
- ```textmate
147
- // Мгновенно обновляет кэш и отправляет транзакцию в Ag-Grid
148
- applyTransactionAsyncUpdate2({
149
- gridRef: apiGrid,
150
- newData: [{ id: "user_1", balance: 500 }],
151
- getId: (e) => e.id,
152
- bufTable: myLocalBuffer,
153
- option: { update: true, add: true }
154
- });
155
- ```
156
-
157
-
158
- ---
159
-
160
- ### ⚙️ Автогенерация UI настроек (`ParametersReact`)
161
-
162
- Движок, который принимает объект со схемой данных и рендерит готовую форму управления (инпуты, слайдеры, селекты).
163
-
164
- **Типизация:**
165
- Схема строится на основе типов `Params.IParamsExpandableReadonly`.
166
- Поддерживаются типы: `number`, `string`, `boolean`, `Date`, массивы, вложенные объекты.
167
-
168
- **Пример:**
169
- ```textmate
170
- const mySettings = {
171
- showGrid: true, // Сгенерирует Checkbox
172
- opacity: {
173
- value: 0.5,
174
- range: { min: 0, max: 1, step: 0.1 },
175
- name: "Прозрачность"
176
- }, // Сгенерирует Range Slider + Number Input
177
- theme: {
178
- value: "dark",
179
- range: ["dark", "light", "system"]
180
- } // Сгенерирует Select
181
- };
182
-
183
- <ParametersReact
184
- params={mySettings}
185
- onChange={(newParams) => {
186
- console.log("Новое значение:", newParams.opacity.value);
187
- }}
188
- />
189
- ```
190
-
191
-
192
- ---
193
-
194
- ### 📜 Система логирования (`logsApi`)
195
-
196
- Регистрация логов, таблица их просмотра и система всплывающих уведомлений (toasts).
197
-
198
- **API:**
199
- ```typescript
200
- // 1. Добавление лога
201
- logsApi.addLogs({
202
- id: "system",
203
- var: 10, // Важность (важно для фильтрации уведомлений)
204
- time: new Date(),
205
- txt: "Соединение разорвано"
206
- });
207
-
208
- // 2. Рендер компонентов (обычно где-то в корне):
209
- <logsApi.React.Message zIndex={9999} /> // Всплывающие уведомления справа сверху
210
- <logsApi.React.PageLogs /> // Таблица всех логов Ag-Grid
211
- ```
212
- Да, в кодовой базе есть еще несколько очень важных архитектурных паттернов и UI-компонентов, которые активно используются и обязательно должны быть в документации, чтобы другой разработчик (или ИИ) понимал, как строить интерфейсы в этом проекте.
213
-
214
- Вот вторая часть дополнений для `README.md`:
215
-
216
- ---
217
-
218
- ### 🗂 Боковая навигация (Sidebar)
219
-
220
- #### `ApiLeftMenu`
221
- Готовое API для управления левым выдвижным меню (Sidebar). Поддерживает свайпы, плавную доводку (snap scrolling) и императивное управление вкладками.
222
-
223
- **API и Типизация:**
224
- ```typescript
225
- type MenuItem = {
226
- el: () => React.JSX.Element; // Компонент вкладки
227
- button?: React.JSX.Element; // Кастомная кнопка (опционально)
228
- color?: ColorString; // Цвет фона
229
- textB?: string; // Текст по умолчанию для кнопки
230
- };
231
-
232
- // Регистрация пунктов меню:
233
- ApiLeftMenu.setMenu(items: MenuItem[], key?: string);
234
- ```
235
-
236
- **Пример использования:**
237
- ```textmate
238
- // 1. Регистрация вкладок (можно делать где угодно в логике):
239
- ApiLeftMenu.setMenu([
240
- { textB: "Дашборд", el: () => <Dashboard />, color: "rgb(92,50,213)" },
241
- { textB: "Настройки", el: () => <Settings /> }
242
- ], "main_menu");
243
-
244
- // 2. Рендер самого меню в корневом Layout:
245
- export function AppLayout() {
246
- return <ApiLeftMenu.Modal2 zIndex={20} />;
247
- }
248
- ```
249
-
250
-
251
- ---
252
-
253
- ### 🎛 Интерактивные элементы и Кнопки
254
-
255
- #### `Button` (из `useOutside.tsx`) / `MiniButton`
256
- Продвинутые компоненты кнопок, которые инкапсулируют логику раскрывающихся списков (dropdowns), всплывающих панелей и отслеживают клик снаружи для автоматического закрытия.
257
-
258
- **Типизация `Button`:**
259
- ```typescript
260
- type tButton = {
261
- button: ReactElement | ((status: boolean) => ReactElement); // Сама кнопка (может менять вид от статуса)
262
- children: ReactNode | ((api: {onClose: () => void}) => ReactNode); // Выпадающий контент
263
- outClick?: boolean | (() => void); // Закрывать ли по клику вне области (true по умолчанию)
264
- statusDef?: boolean; // Начальное состояние (открыто/закрыто)
265
- };
266
- ```
267
-
268
- **Пример:**
269
- ```textmate
270
- <Button
271
- outClick={true}
272
- button={(isOpen) => <div className={isOpen ? "active" : ""}>Опции</div>}
273
- >
274
- {({ onClose }) => (
275
- <div className="dropdown-panel">
276
- <div onClick={() => { doSomething(); onClose(); }}>Действие 1</div>
277
- </div>
278
- )}
279
- </Button>
280
- ```
281
-
282
-
283
- #### `FResizableReact`
284
- Обертка над `re-resizable`. Позволяет делать панели с изменяемым размером (например, колонки или нижние логи), сохраняя их размер в кэш.
285
-
286
- **Пример:**
287
- ```textmate
288
- <FResizableReact
289
- keyForSave="bottom_panel_size"
290
- size={{ height: 200, width: "100%" }}
291
- moveWith={false} // Разрешить ресайз только по высоте
292
- >
293
- <LogsTable />
294
- </FResizableReact>
295
- ```
296
-
297
-
298
- ---
299
-
300
- ### 🔄 Глобальная реактивность (Паттерн `renderBy` / `updateBy`)
301
-
302
- *(Примечание: это важнейший концепт проекта, используемый вместо классического `useState` / `Redux` для сложной бизнес-логики).*
303
-
304
- Во многих местах проекта используется мутабельный подход к состоянию: вы меняете свойства обычного JS-объекта и вызываете `renderBy(obj)`, чтобы принудительно обновить все компоненты, которые подписаны на этот объект через `updateBy(obj)`.
305
-
306
- **Пример паттерна:**
307
- ```textmate
308
- import { renderBy, updateBy } from "./updateBy";
309
-
310
- // 1. Глобальное или локальное состояние (обычный объект)
311
- const myState = {
312
- count: 0,
313
- text: "hello"
314
- };
315
-
316
- // 2. Компонент-потребитель
317
- function CounterViewer() {
318
- // Компонент подписывается на изменения myState
319
- updateBy(myState);
320
-
321
- return <div>{myState.count}</div>;
322
- }
323
-
324
- // 3. Изменение состояния (где угодно, даже вне React)
325
- function increment() {
326
- myState.count += 1;
327
- renderBy(myState); // Триггерит ререндер CounterViewer
328
- }
329
- ```
330
-
331
-
332
- ---
333
-
334
- ### 📊 Полезные утилиты для Ag-Grid
335
-
336
- #### `GridStyleDefault` и `StyleCSSHeadGrid`
337
- Быстрое применение единого корпоративного стиля ко всем таблицам приложения.
338
-
339
- **Пример внедрения в корень проекта:**
340
- ```typescript
341
- import { GridStyleDefault, StyleCSSHeadGrid } from "./styleGrid";
342
-
343
- // Применяет темную тему, сжимает отступы, центрирует заголовки
344
- GridStyleDefault();
345
- StyleCSSHeadGrid();
346
- ```
347
-
348
-
349
- #### `getComparatorGrid`
350
- Фабрика для создания кастомных функций сортировки колонок Ag-Grid, корректно обрабатывающая `undefined`, `NaN` и инверсию.
351
- **Пример:**
352
- ```textmate
353
- const columnDefs = [
354
- {
355
- field: "price",
356
- comparator: getComparatorGrid() // Безопасная сортировка чисел
357
- }
358
- ];
359
- ```
360
-
361
-
362
- ---
363
-
364
- ### ⌨️ Глобальные хуки
365
-
366
- #### `useAddDownAnyKey`
367
- Регистрирует глобальный слушатель нажатий клавиатуры и сохраняет последнюю нажатую клавишу в экспортируемый реактивный объект `KeyDown`.
368
-
369
- **Пример использования:**
370
- ```textmate
371
- import { KeyDown, useAddDownAnyKey } from "./useAddDownAnyKey";
372
- import { updateBy } from "./updateBy";
373
-
374
- function HotkeyListener() {
375
- useAddDownAnyKey(); // Инициализация хука
376
- updateBy(KeyDown); // Подписка на нажатия
377
-
378
- if (KeyDown.key === "Escape") {
379
- return <div>Нажат Escape!</div>;
380
- }
381
- return null;
382
- }
1
+ Here is an expanded API guide with typings and usage examples. This format is suitable for documentation so other developers or AI assistants can quickly understand which props a component accepts and how to integrate it.
2
+
3
+ ---
4
+
5
+ ## API Reference (Components & Hooks)
6
+
7
+ ### Modal and Floating Windows (MDI)
8
+
9
+ #### `DivRnd3`
10
+ Wrapper for creating freely movable, resizable windows with state persistence.
11
+
12
+ **Typing:**
13
+ ```typescript
14
+ type tDivRndBase = {
15
+ children: React.ReactElement | ((update: number) => React.ReactElement);
16
+ position?: { x: number; y: number };
17
+ size?: { height: number | string; width: number | string };
18
+ keyForSave?: string; // Key for caching the position/size in memory
19
+ limit?: { x?: { max?: number; min?: number }, y?: { max?: number; min?: number } };
20
+ onCLickClose?: () => void; // Adds a close button to the window
21
+ header?: React.ReactElement | boolean; // Drag handle header; otherwise the whole block is draggable
22
+ zIndex?: number;
23
+ }
24
+ ```
25
+
26
+ **Example:**
27
+ ```textmate
28
+ <DivRnd3
29
+ keyForSave="my_tool_window"
30
+ size={{ width: 300, height: 200 }}
31
+ onCLickClose={() => setOpen(false)}
32
+ header={<div>My tool</div>}
33
+ >
34
+ <div>Window content</div>
35
+ </DivRnd3>
36
+ ```
37
+
38
+
39
+ #### `GetModalJSX()`
40
+ Factory for global modal windows. It lets business logic open windows without being tied to local component state.
41
+
42
+ **Example:**
43
+ ```textmate
44
+ const myModal = GetModalJSX();
45
+
46
+ // 1. In the app root file (App.tsx):
47
+ <myModal.Render />
48
+
49
+ // 2. Anywhere in the logic:
50
+ myModal.set(<div onClick={() => myModal.set(null)}>Close me</div>);
51
+ // For multiple windows: myModal.addJSX(<Component/>)
52
+ ```
53
+
54
+
55
+ ---
56
+
57
+ ### Drag-and-Drop and Interaction (Hooks & Wrappers)
58
+
59
+ #### `useOutside` / `DivOutsideClick`
60
+ Tracks clicks outside an element, useful for closing dropdowns and menus.
61
+
62
+ **Typing:**
63
+ ```typescript
64
+ // Hook
65
+ function useOutside(params: { outsideClick: () => void, status?: boolean, ref?: RefObject }): RefObject;
66
+
67
+ // Component
68
+ type Props = { outsideClick: () => void, status?: boolean, zIndex?: number } & HTMLAttributes;
69
+ ```
70
+
71
+ **Example:**
72
+ ```textmate
73
+ <DivOutsideClick outsideClick={() => setDropdownOpen(false)} status={isOpen}>
74
+ <div className="dropdown-menu">...</div>
75
+ </DivOutsideClick>
76
+ ```
77
+
78
+
79
+ #### `Drag22`
80
+ Tracks mouse/finger movement and returns new coordinates without touching CSS directly.
81
+
82
+ **Typing:**
83
+ ```typescript
84
+ type Drag2Props = {
85
+ x?: number; y?: number; // Start/current coordinates
86
+ onX?: (val: number) => void; // X change callback
87
+ onY?: (val: number) => void; // Y change callback
88
+ onStart?: () => void; onStop?: () => void;
89
+ children: ReactNode;
90
+ };
91
+ ```
92
+
93
+
94
+ ---
95
+
96
+ ### Context Menus (`MenuR` / `mouseMenuApi`)
97
+
98
+ Smart context menus. They open on desktop via right click and on mobile via long tap / double tap. They support asynchronous item generation.
99
+
100
+ **Menu item typing (`tMenuReactStrictly`):**
101
+ ```typescript
102
+ type tMenuReactStrictly = {
103
+ name: string | ((status?: any) => string);
104
+ onClick?: (e: any) => void | Promise<any> | Promise<any>[]; // Promise support with ok/error counters
105
+ status?: boolean; // Whether the submenu is expanded
106
+ next?: () => tMenuReact[] | Promise<tMenuReact[]>; // Nested menu
107
+ func?: () => React.ReactElement | Promise<React.ReactElement>; // Custom hover render
108
+ };
109
+ ```
110
+
111
+ **Examples:**
112
+ ```textmate
113
+ // 1. Using the wrapper component
114
+ const menuItems = () => [
115
+ { name: "Copy", onClick: () => copy() },
116
+ { name: "Options", next: () => [{ name: "Option 1", onClick: () => {} }] }
117
+ ];
118
+
119
+ <MenuR other={menuItems}>
120
+ <div className="item">Right-click me</div>
121
+ </MenuR>
122
+
123
+ // 2. Global call through the API
124
+ mouseMenuApi.map.set("global_action", [{ name: "Global action", onClick: () => {} }]);
125
+ ```
126
+
127
+
128
+ ---
129
+
130
+ ### Ag-Grid Table Updates (`applyTransactionAsyncUpdate2`)
131
+
132
+ Function for safe batched asynchronous table data updates synchronized with a local buffer/cache.
133
+
134
+ **Typing:**
135
+ ```typescript
136
+ type Params<T> = {
137
+ gridRef?: React.RefObject<GridReadyEvent<T, any>>;
138
+ newData: Partial<T>[]; // New data array
139
+ getId: (row: Partial<T>) => string; // ID getter
140
+ bufTable: { [id: string]: Partial<T> }; // Local cache dictionary
141
+ option?: { update?: boolean, add?: boolean, updateBuffer?: boolean, sync?: boolean };
142
+ };
143
+ ```
144
+
145
+ **Example:**
146
+ ```textmate
147
+ // Immediately updates the cache and sends a transaction to Ag-Grid
148
+ applyTransactionAsyncUpdate2({
149
+ gridRef: apiGrid,
150
+ newData: [{ id: "user_1", balance: 500 }],
151
+ getId: (e) => e.id,
152
+ bufTable: myLocalBuffer,
153
+ option: { update: true, add: true }
154
+ });
155
+ ```
156
+
157
+
158
+ ---
159
+
160
+ ### UI Settings Autogeneration (`ParametersReact`)
161
+
162
+ Engine that accepts an object with a data schema and renders a ready-to-use control form with inputs, sliders, and selects.
163
+
164
+ **Typing:**
165
+ The schema is built from `Params.IParamsExpandableReadonly` types.
166
+ Supported types: `number`, `string`, `boolean`, `Date`, arrays, and nested objects.
167
+
168
+ **Example:**
169
+ ```textmate
170
+ const mySettings = {
171
+ showGrid: true, // Generates a Checkbox
172
+ opacity: {
173
+ value: 0.5,
174
+ range: { min: 0, max: 1, step: 0.1 },
175
+ name: "Opacity"
176
+ }, // Generates a Range Slider + Number Input
177
+ theme: {
178
+ value: "dark",
179
+ range: ["dark", "light", "system"]
180
+ } // Generates a Select
181
+ };
182
+
183
+ <ParametersReact
184
+ params={mySettings}
185
+ onChange={(newParams) => {
186
+ console.log("New value:", newParams.opacity.value);
187
+ }}
188
+ />
189
+ ```
190
+
191
+
192
+ ---
193
+
194
+ ### Logging System (`logsApi`)
195
+
196
+ Log registration, log viewer table, and toast notification system.
197
+
198
+ **API:**
199
+ ```typescript
200
+ // 1. Adding a log
201
+ logsApi.addLogs({
202
+ id: "system",
203
+ var: 10, // Severity, important for notification filtering
204
+ time: new Date(),
205
+ txt: "Connection lost"
206
+ });
207
+
208
+ // 2. Rendering components, usually somewhere near the root:
209
+ <logsApi.React.Message zIndex={9999} /> // Toast notifications in the top-right corner
210
+ <logsApi.React.PageLogs /> // Ag-Grid table with all logs
211
+ ```
212
+
213
+ There are several other important architectural patterns and UI components actively used in the codebase. They should be documented so another developer or AI assistant can understand how interfaces are built in this project.
214
+
215
+ Here is the second part of the `README.md` additions:
216
+
217
+ ---
218
+
219
+ ### Sidebar Navigation
220
+
221
+ #### `ApiLeftMenu`
222
+ Ready-made API for controlling the left slide-out sidebar menu. It supports swipes, smooth snap scrolling, and imperative tab control.
223
+
224
+ **API and Typing:**
225
+ ```typescript
226
+ type MenuItem = {
227
+ el: () => React.JSX.Element; // Tab component
228
+ button?: React.JSX.Element; // Custom button, optional
229
+ color?: ColorString; // Background color
230
+ textB?: string; // Default button text
231
+ };
232
+
233
+ // Register menu items:
234
+ ApiLeftMenu.setMenu(items: MenuItem[], key?: string);
235
+ ```
236
+
237
+ **Usage example:**
238
+ ```textmate
239
+ // 1. Register tabs, can be done anywhere in the logic:
240
+ ApiLeftMenu.setMenu([
241
+ { textB: "Dashboard", el: () => <Dashboard />, color: "rgb(92,50,213)" },
242
+ { textB: "Settings", el: () => <Settings /> }
243
+ ], "main_menu");
244
+
245
+ // 2. Render the menu itself in the root Layout:
246
+ export function AppLayout() {
247
+ return <ApiLeftMenu.Modal2 zIndex={20} />;
248
+ }
249
+ ```
250
+
251
+
252
+ ---
253
+
254
+ ### Interactive Elements and Buttons
255
+
256
+ #### `Button` (from `useOutside.tsx`) / `MiniButton`
257
+ Advanced button components that encapsulate dropdown logic, popover panels, and outside-click tracking for automatic closing.
258
+
259
+ **`Button` typing:**
260
+ ```typescript
261
+ type tButton = {
262
+ button: ReactElement | ((status: boolean) => ReactElement); // The button itself; can change by status
263
+ children: ReactNode | ((api: {onClose: () => void}) => ReactNode); // Dropdown content
264
+ outClick?: boolean | (() => void); // Whether to close on outside click; true by default
265
+ statusDef?: boolean; // Initial state, open/closed
266
+ };
267
+ ```
268
+
269
+ **Example:**
270
+ ```textmate
271
+ <Button
272
+ outClick={true}
273
+ button={(isOpen) => <div className={isOpen ? "active" : ""}>Options</div>}
274
+ >
275
+ {({ onClose }) => (
276
+ <div className="dropdown-panel">
277
+ <div onClick={() => { doSomething(); onClose(); }}>Action 1</div>
278
+ </div>
279
+ )}
280
+ </Button>
281
+ ```
282
+
283
+
284
+ #### `FResizableReact`
285
+ Wrapper over `re-resizable`. It creates resizable panels, for example columns or lower log panes, and stores their size in cache.
286
+
287
+ **Example:**
288
+ ```textmate
289
+ <FResizableReact
290
+ keyForSave="bottom_panel_size"
291
+ size={{ height: 200, width: "100%" }}
292
+ moveWith={false} // Allow resize only by height
293
+ >
294
+ <LogsTable />
295
+ </FResizableReact>
296
+ ```
297
+
298
+
299
+ ---
300
+
301
+ ### Global Reactivity (`renderBy` / `updateBy` Pattern)
302
+
303
+ *(Note: this is a key project concept used instead of classic `useState` / `Redux` for complex business logic.)*
304
+
305
+ Many places in the project use a mutable state approach: you mutate properties of a plain JS object and call `renderBy(obj)` to force an update of all components subscribed to that object through `updateBy(obj)`.
306
+
307
+ **Pattern example:**
308
+ ```textmate
309
+ import { renderBy, updateBy } from "./updateBy";
310
+
311
+ // 1. Global or local state, a plain object
312
+ const myState = {
313
+ count: 0,
314
+ text: "hello"
315
+ };
316
+
317
+ // 2. Consumer component
318
+ function CounterViewer() {
319
+ // The component subscribes to myState changes
320
+ updateBy(myState);
321
+
322
+ return <div>{myState.count}</div>;
323
+ }
324
+
325
+ // 3. State change, anywhere, even outside React
326
+ function increment() {
327
+ myState.count += 1;
328
+ renderBy(myState); // Triggers a CounterViewer rerender
329
+ }
330
+ ```
331
+
332
+
333
+ ---
334
+
335
+ ### Useful Ag-Grid Utilities
336
+
337
+ #### `GridStyleDefault` and `StyleCSSHeadGrid`
338
+ Quickly apply the common corporate style to all application tables.
339
+
340
+ **Root integration example:**
341
+ ```typescript
342
+ import { GridStyleDefault, StyleCSSHeadGrid } from "./styleGrid";
343
+
344
+ // Applies the dark theme, compresses spacing, and centers headers
345
+ GridStyleDefault();
346
+ StyleCSSHeadGrid();
347
+ ```
348
+
349
+
350
+ #### `getComparatorGrid`
351
+ Factory for creating custom Ag-Grid column sort functions that correctly handle `undefined`, `NaN`, and inversion.
352
+ **Example:**
353
+ ```textmate
354
+ const columnDefs = [
355
+ {
356
+ field: "price",
357
+ comparator: getComparatorGrid() // Safe numeric sorting
358
+ }
359
+ ];
360
+ ```
361
+
362
+
363
+ ---
364
+
365
+ ### Global Hooks
366
+
367
+ #### `useAddDownAnyKey`
368
+ Registers a global keyboard listener and stores the last pressed key in the exported reactive object `KeyDown`.
369
+
370
+ **Usage example:**
371
+ ```textmate
372
+ import { KeyDown, useAddDownAnyKey } from "./useAddDownAnyKey";
373
+ import { updateBy } from "./updateBy";
374
+
375
+ function HotkeyListener() {
376
+ useAddDownAnyKey(); // Hook initialization
377
+ updateBy(KeyDown); // Subscribe to key presses
378
+
379
+ if (KeyDown.key === "Escape") {
380
+ return <div>Escape pressed!</div>;
381
+ }
382
+ return null;
383
+ }
383
384
  ```