wenay-react2 1.0.1 → 1.0.2

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 (2) hide show
  1. package/README.md +383 -0
  2. package/package.json +1 -2
package/README.md ADDED
@@ -0,0 +1,383 @@
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
+ }
383
+ ```
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "wenay-react2",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Common react",
5
5
  "strict": true,
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "files": [
9
9
  "lib/**/*",
10
- "README.md",
11
10
  "!**/*.tsbuildinfo"
12
11
  ],
13
12
  "author": "wenay",