@qtpy/use-ref-map 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.mjs +14 -0
- package/package.json +57 -0
package/README.md
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
# Документация по хуку useRefMap
|
2
|
+
|
3
|
+
`useRefMap` — это пользовательский React-хук для управления множеством ссылок (`RefObject`) с использованием ключей. Он позволяет динамически создавать, получать и удалять ссылки, а также предоставляет список всех ключей. Хук полезен для императивного управления компонентами или DOM-элементами, например, для вызова методов компонентов, фокусировки или обработки событий прокрутки.
|
4
|
+
|
5
|
+
## Содержание
|
6
|
+
- [Возвращаемые значения](#возвращаемые-значения)
|
7
|
+
- [Использование](#использование)
|
8
|
+
- [Базовое использование](#базовое-использование)
|
9
|
+
- [Императивное управление (вызов метода компонента)](#императивное-управление-вызов-метода-компонента)
|
10
|
+
- [Удаление ссылки](#удаление-ссылки)
|
11
|
+
- [Получение всех ключей](#получение-всех-ключей)
|
12
|
+
- [Типы](#типы)
|
13
|
+
- [Примечания](#примечания)
|
14
|
+
|
15
|
+
## Возвращаемые значения
|
16
|
+
|
17
|
+
Хук `useRefMap` возвращает объект со следующими методами:
|
18
|
+
|
19
|
+
| Метод | Тип | Описание |
|
20
|
+
|----------------|------------------------------------------|--------------------------------------------------------------------------|
|
21
|
+
| `getRef` | `(key: string) => RefObject<Partial<T>>` | Возвращает ссылку (`RefObject`) для указанного ключа. Если ссылка не существует, создаётся новая с `current: null`. |
|
22
|
+
| `deleteRef` | `(key: string) => void` | Удаляет ссылку и соответствующий ключ из внутреннего хранилища. |
|
23
|
+
| `getAllKeys` | `() => string[]` | Возвращает массив всех ключей, связанных с существующими ссылками. |
|
24
|
+
|
25
|
+
## Использование
|
26
|
+
|
27
|
+
### Базовое использование
|
28
|
+
|
29
|
+
Пример использования `useRefMap` с `map` для создания ссылок на элементы и обработки события прокрутки:
|
30
|
+
|
31
|
+
```jsx
|
32
|
+
import { useRefMap } from './useRefMap';
|
33
|
+
import { useState } from 'react';
|
34
|
+
import { useEvent } from './useEvent'; // Предполагаемый хук для обработки событий
|
35
|
+
|
36
|
+
function ProjectsPage() {
|
37
|
+
const { getRef } = useRefMap<HTMLDivElement>();
|
38
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
39
|
+
const projects = ['Проект 1', 'Проект 2', 'Проект 3'];
|
40
|
+
|
41
|
+
useEvent('scroll', () => {
|
42
|
+
for (let i = 0; i < projects.length; i++) {
|
43
|
+
const key = `project_${i}`;
|
44
|
+
const el = getRef(key).current;
|
45
|
+
if (el) {
|
46
|
+
const { top, height } = el.getBoundingClientRect();
|
47
|
+
if (top + height < window.scrollY) {
|
48
|
+
setActiveIndex(i); // Обновляем активный индекс при прокрутке
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}, {});
|
53
|
+
|
54
|
+
return (
|
55
|
+
<div className="ProjectsPage">
|
56
|
+
<h1>Проекты</h1>
|
57
|
+
<div className="ProjectsPage_container">
|
58
|
+
{projects.map((title, index) => (
|
59
|
+
<div
|
60
|
+
key={index}
|
61
|
+
ref={getRef(`project_${index}`)}
|
62
|
+
style={{ background: index === activeIndex ? '#e0e0e0' : 'white' }}
|
63
|
+
>
|
64
|
+
<h2>{title}</h2>
|
65
|
+
</div>
|
66
|
+
))}
|
67
|
+
</div>
|
68
|
+
<p>Активный проект: {projects[activeIndex]}</p>
|
69
|
+
</div>
|
70
|
+
);
|
71
|
+
}
|
72
|
+
```
|
73
|
+
|
74
|
+
В этом примере хук `useRefMap` используется для создания ссылок на элементы `<div>` с помощью метода `map` и ключей вида `project_${index}`. При прокрутке страницы хук `useEvent` проверяет положение каждого элемента через `getBoundingClientRect` и обновляет `activeIndex`, если элемент выходит за верхнюю границу окна, подсвечивая активный проект.
|
75
|
+
|
76
|
+
### Императивное управление (вызов метода компонента)
|
77
|
+
|
78
|
+
Пример императивного вызова метода компонента через `useRefMap`:
|
79
|
+
|
80
|
+
```jsx
|
81
|
+
import { useRefMap } from './useRefMap';
|
82
|
+
|
83
|
+
interface AnimatedLabelComponent {
|
84
|
+
setIsActive: (value: boolean) => void;
|
85
|
+
}
|
86
|
+
|
87
|
+
function AccordionCard({ keyName, title }: { keyName: string; title: string }) {
|
88
|
+
const { getRef } = useRefMap<AnimatedLabelComponent>();
|
89
|
+
|
90
|
+
return (
|
91
|
+
<Accordion onClick={(value) => getRef(keyName).current?.setIsActive?.(value)}>
|
92
|
+
<Accordion.Header>
|
93
|
+
<AnimatedLabel ref={getRef(keyName)} title={title} />
|
94
|
+
</Accordion.Header>
|
95
|
+
<Accordion.Content>
|
96
|
+
<div>Контент аккордеона</div>
|
97
|
+
</Accordion.Content>
|
98
|
+
</Accordion>
|
99
|
+
);
|
100
|
+
}
|
101
|
+
```
|
102
|
+
|
103
|
+
В этом примере хук `useRefMap` используется для хранения ссылки на компонент `AnimatedLabel` по ключу `keyName`. При клике на аккордеон вызывается метод `setIsActive` компонента `AnimatedLabel` для управления его состоянием.
|
104
|
+
|
105
|
+
### Удаление ссылки
|
106
|
+
|
107
|
+
Удаление ненужной ссылки из хранилища:
|
108
|
+
|
109
|
+
```jsx
|
110
|
+
import { useRefMap } from './useRefMap';
|
111
|
+
|
112
|
+
function Component() {
|
113
|
+
const { getRef, deleteRef } = useRefMap<HTMLElement>();
|
114
|
+
|
115
|
+
const removeRef = () => {
|
116
|
+
deleteRef('section1');
|
117
|
+
console.log('Ссылка на section1 удалена');
|
118
|
+
};
|
119
|
+
|
120
|
+
return (
|
121
|
+
<div>
|
122
|
+
<section ref={getRef('section1')}>Секция 1</section>
|
123
|
+
<button onClick={removeRef}>Удалить ссылку</button>
|
124
|
+
</div>
|
125
|
+
);
|
126
|
+
}
|
127
|
+
```
|
128
|
+
|
129
|
+
### Получение всех ключей
|
130
|
+
|
131
|
+
Получение списка всех ключей для проверки существующих ссылок:
|
132
|
+
|
133
|
+
```jsx
|
134
|
+
import { useRefMap } from './useRefMap';
|
135
|
+
|
136
|
+
function Component() {
|
137
|
+
const { getRef, getAllKeys } = useRefMap<HTMLElement>();
|
138
|
+
|
139
|
+
const logKeys = () => {
|
140
|
+
console.log('Текущие ключи:', getAllKeys());
|
141
|
+
};
|
142
|
+
|
143
|
+
return (
|
144
|
+
<div>
|
145
|
+
<section ref={getRef('section1')}>Секция 1</section>
|
146
|
+
<section ref={getRef('section2')}>Секция 2</section>
|
147
|
+
<button onClick={logKeys}>Вывести ключи</button>
|
148
|
+
</div>
|
149
|
+
);
|
150
|
+
}
|
151
|
+
```
|
152
|
+
|
153
|
+
## Типы
|
154
|
+
|
155
|
+
Хук `useRefMap` использует следующие TypeScript-типы:
|
156
|
+
|
157
|
+
```typescript
|
158
|
+
export type RefMap<T> = Record<string, RefObject<T>>;
|
159
|
+
|
160
|
+
export type RefMapMethods<T> = {
|
161
|
+
getRef: (key: string) => RefObject<Partial<T>>;
|
162
|
+
deleteRef: (key: string) => void;
|
163
|
+
getAllKeys: () => string[];
|
164
|
+
};
|
165
|
+
|
166
|
+
export type UseRefMapReturn<T, E extends keyof RefMapMethods<T>> = Pick<RefMapMethods<T>, E>;
|
167
|
+
```
|
168
|
+
|
169
|
+
- `RefMap<T>`: Объект, где ключи — это строки, а значения — `RefObject<T>`.
|
170
|
+
- `RefMapMethods<T>`: Интерфейс, описывающий методы, возвращаемые хуком.
|
171
|
+
- `UseRefMapReturn<T, E>`: Тип возвращаемого значения хука, который позволяет указать подмножество методов через `E`.
|
172
|
+
|
173
|
+
## Примечания
|
174
|
+
|
175
|
+
- **Императивное управление**: Хук удобен для вызова методов компонентов (например, `setIsActive`) или DOM-операций, таких как `scrollIntoView`, `focus` или `getBoundingClientRect`, через свойство `current`.
|
176
|
+
- **Инициализация ссылок**: Метод `getRef` создаёт новую ссылку с `current: null`, если ссылка для указанного ключа ещё не существует.
|
177
|
+
- **Типизация**: Хук поддерживает обобщённый тип `T` для работы с любыми типами данных (например, пользовательскими интерфейсами компонентов или `HTMLElement`).
|
178
|
+
- **Управление памятью**: Метод `deleteRef` предотвращает утечки памяти, удаляя ненужные ссылки.
|
179
|
+
- **Сохранение состояния**: Хук использует `useRef` для хранения ссылок и ключей, что обеспечивает их неизменность между рендерами без лишних обновлений.
|
180
|
+
- **Ограничение типизации**: `RefObject` возвращает `Partial<T>`, чтобы учесть случаи, когда `current` может быть `null`.
|
package/dist/index.cjs
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";const n=require("react");function u(){const r=n.useRef({}),t=n.useRef(new Set);return{getRef:e=>(r.current[e]||(r.current[e]={current:null},t.current.add(e)),r.current[e]),deleteRef:e=>{r.current[e]&&(delete r.current[e],t.current.delete(e))},getAllKeys:()=>Array.from(t.current)}}module.exports=u;
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
import { RefObject } from "react";
|
2
|
+
export type RefMap<T> = Record<string, RefObject<T>>;
|
3
|
+
export default function useRefMap<T>(): {
|
4
|
+
getRef: (key: string) => RefObject<T>;
|
5
|
+
deleteRef: (key: string) => void;
|
6
|
+
getAllKeys: () => string[];
|
7
|
+
};
|
8
|
+
export type RefMapMethods<T> = {
|
9
|
+
getRef: (key: string) => RefObject<Partial<T>>;
|
10
|
+
deleteRef: (key: string) => RefObject<Partial<T>>;
|
11
|
+
getAllKeys: () => string[];
|
12
|
+
};
|
13
|
+
export type UseRefMapReturn<T, E extends keyof RefMapMethods<T>> = Pick<RefMapMethods<T>, E>;
|
package/dist/index.mjs
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
import { useRef as n } from "react";
|
2
|
+
function s() {
|
3
|
+
const r = n({}), t = n(/* @__PURE__ */ new Set());
|
4
|
+
return {
|
5
|
+
getRef: (e) => (r.current[e] || (r.current[e] = { current: null }, t.current.add(e)), r.current[e]),
|
6
|
+
deleteRef: (e) => {
|
7
|
+
r.current[e] && (delete r.current[e], t.current.delete(e));
|
8
|
+
},
|
9
|
+
getAllKeys: () => Array.from(t.current)
|
10
|
+
};
|
11
|
+
}
|
12
|
+
export {
|
13
|
+
s as default
|
14
|
+
};
|
package/package.json
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
{
|
2
|
+
"name": "@qtpy/use-ref-map",
|
3
|
+
"version": "0.0.0",
|
4
|
+
"author": "QtPy",
|
5
|
+
"license": "MIT",
|
6
|
+
"homepage": "https://github.com/TheOnlyFastCoder2/QtPy-library/tree/main/useRefMap",
|
7
|
+
"main": "./dist/index.cjs",
|
8
|
+
"module": "./dist/index.mjs",
|
9
|
+
"types": "./dist/index.d.ts",
|
10
|
+
"private": false,
|
11
|
+
"exports": {
|
12
|
+
".": {
|
13
|
+
"types": "./dist/index.d.ts",
|
14
|
+
"import": "./dist/index.mjs",
|
15
|
+
"require": "./dist/index.cjs"
|
16
|
+
}
|
17
|
+
},
|
18
|
+
"files": [
|
19
|
+
"dist"
|
20
|
+
],
|
21
|
+
"keywords": [
|
22
|
+
"react useRefMap",
|
23
|
+
"react refs",
|
24
|
+
"dynamic refs",
|
25
|
+
"react scroll handling",
|
26
|
+
"imperative react",
|
27
|
+
"react DOM manipulation",
|
28
|
+
"typescript refs",
|
29
|
+
"react accordion"
|
30
|
+
],
|
31
|
+
"dependencies": {
|
32
|
+
"react": ">=18.0",
|
33
|
+
"react-dom": ">=18.0"
|
34
|
+
},
|
35
|
+
"scripts": {
|
36
|
+
"dev": "vite",
|
37
|
+
"build": "vite build && tsc --declaration --emitDeclarationOnly --outDir dist",
|
38
|
+
"prepublishOnly": "npm run build",
|
39
|
+
"type-check": "tsc --noEmit",
|
40
|
+
"lint": "eslint src --ext ts,tsx --fix"
|
41
|
+
},
|
42
|
+
"devDependencies": {
|
43
|
+
"@eslint/js": "^9.30.1",
|
44
|
+
"@types/node": "^24.1.0",
|
45
|
+
"@types/react": "^19.1.8",
|
46
|
+
"@types/react-dom": "^19.1.6",
|
47
|
+
"@vitejs/plugin-react": "^4.6.0",
|
48
|
+
"eslint": "^9.30.1",
|
49
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
50
|
+
"eslint-plugin-react-refresh": "^0.4.20",
|
51
|
+
"globals": "^16.3.0",
|
52
|
+
"typescript": "~5.8.3",
|
53
|
+
"typescript-eslint": "^8.35.1",
|
54
|
+
"vite": "^7.0.4",
|
55
|
+
"vite-plugin-dts": "^4.5.4"
|
56
|
+
}
|
57
|
+
}
|