@rune-hub/react 1.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/LICENSE +21 -0
- package/README.md +336 -0
- package/context/HubContext/HubContext.d.ts +27 -0
- package/context/HubContext/HubContext.es6.js +31 -0
- package/context/HubContext/HubContext.js +36 -0
- package/context/HubContext/index.d.ts +1 -0
- package/context/HubContext/index.es6.js +1 -0
- package/context/HubContext/index.js +10 -0
- package/context/index.d.ts +1 -0
- package/context/index.es6.js +1 -0
- package/context/index.js +4 -0
- package/hooks/index.d.ts +5 -0
- package/hooks/index.es6.js +5 -0
- package/hooks/index.js +8 -0
- package/hooks/useAction/index.d.ts +1 -0
- package/hooks/useAction/index.es6.js +1 -0
- package/hooks/useAction/index.js +9 -0
- package/hooks/useAction/useAction.d.ts +24 -0
- package/hooks/useAction/useAction.es6.js +39 -0
- package/hooks/useAction/useAction.js +43 -0
- package/hooks/useHub/index.d.ts +1 -0
- package/hooks/useHub/index.es6.js +1 -0
- package/hooks/useHub/index.js +9 -0
- package/hooks/useHub/useHub.d.ts +20 -0
- package/hooks/useHub/useHub.es6.js +28 -0
- package/hooks/useHub/useHub.js +32 -0
- package/hooks/useOn/index.d.ts +1 -0
- package/hooks/useOn/index.es6.js +1 -0
- package/hooks/useOn/index.js +9 -0
- package/hooks/useOn/useOn.d.ts +23 -0
- package/hooks/useOn/useOn.es6.js +31 -0
- package/hooks/useOn/useOn.js +35 -0
- package/hooks/useRune/index.d.ts +1 -0
- package/hooks/useRune/index.es6.js +1 -0
- package/hooks/useRune/index.js +9 -0
- package/hooks/useRune/useRune.d.ts +24 -0
- package/hooks/useRune/useRune.es6.js +37 -0
- package/hooks/useRune/useRune.js +41 -0
- package/hooks/useSlot/index.d.ts +1 -0
- package/hooks/useSlot/index.es6.js +1 -0
- package/hooks/useSlot/index.js +9 -0
- package/hooks/useSlot/useSlot.d.ts +34 -0
- package/hooks/useSlot/useSlot.es6.js +43 -0
- package/hooks/useSlot/useSlot.js +47 -0
- package/index.d.ts +2 -0
- package/index.es6.js +8 -0
- package/index.js +22 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mike Lysikov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<a href="https://github.com/d8corp/rune-hub">
|
|
3
|
+
<img src="https://cdn.jsdelivr.net/gh/d8corp/rune-hub@main/logo.svg" width="80">
|
|
4
|
+
</a>
|
|
5
|
+
<br>
|
|
6
|
+
@rune-hub/react
|
|
7
|
+
</h1>
|
|
8
|
+
|
|
9
|
+
<div align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/@rune-hub/react" target="_blank">
|
|
11
|
+
<img src="https://img.shields.io/npm/v/@rune-hub/react.svg" alt="rune-hub npm">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://github.com/d8corp/rune-hub-react" target="_blank">
|
|
14
|
+
<img src="https://img.shields.io/badge/-GitHub-181717?logo=github&logoColor=white" alt="rune-hub source code">
|
|
15
|
+
</a>
|
|
16
|
+
<a href="https://www.npmtrends.com/@rune-hub/react" target="_blank">
|
|
17
|
+
<img src="https://img.shields.io/npm/dm/@rune-hub/react.svg" alt="rune-hub downloads">
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://github.com/d8corp/rune-hub-react/tree/main/release" target="_blank">
|
|
20
|
+
<img src="https://packagephobia.com/badge?p=@rune-hub/react" alt="rune-hub install size">
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://www.typescriptlang.org" target="_blank">
|
|
23
|
+
<img src="https://img.shields.io/npm/types/@rune-hub/react" alt="TypeScript">
|
|
24
|
+
</a>
|
|
25
|
+
<a href="https://github.com/d8corp/rune-hub-react/blob/main/LICENSE" target="_blank">
|
|
26
|
+
<img src="https://img.shields.io/npm/l/@rune-hub/react" alt="rune-hub license">
|
|
27
|
+
</a>
|
|
28
|
+
<a href="https://github.com/d8corp/rune-hub-react/blob/main/CHANGELOG.md" target="_blank">
|
|
29
|
+
<img src="https://img.shields.io/badge/Changelog-⋮-brightgreen" alt="rune-hub changelog">
|
|
30
|
+
</a>
|
|
31
|
+
<a href="https://d8corp.github.io/rune-hub-react/coverage/lcov-report" target="_blank">
|
|
32
|
+
<img src="https://github.com/d8corp/rune-hub-react/actions/workflows/tests.yml/badge.svg" alt="rune-hub tests">
|
|
33
|
+
</a>
|
|
34
|
+
<a href="https://github.com/d8corp/rune-hub-react/issues" target="_blank">
|
|
35
|
+
<img src="https://img.shields.io/github/issues-raw/d8corp/rune-hub-react" alt="Open issues">
|
|
36
|
+
</a>
|
|
37
|
+
<a href="https://github.com/d8corp/rune-hub-react/pulls" target="_blank">
|
|
38
|
+
<img src="https://img.shields.io/github/issues-pr-raw/d8corp/rune-hub-react" alt="Pull requests">
|
|
39
|
+
</a>
|
|
40
|
+
</div>
|
|
41
|
+
<br>
|
|
42
|
+
|
|
43
|
+
`@rune-hub/react` provides [React](https://www.npmjs.com/package/react) integration for the reactive [rune-hub](https://www.npmjs.com/package/rune-hub) store, implementing a flexible subscription mechanism for state changes and mutation calls via specialized hooks.
|
|
44
|
+
The [HubProvider](#hubprovider) component injects the store instance into the React context, while the [useRune](#userune) and [useAction](#useaction) hooks ensure reactive data synchronization and stable references to action functions, minimizing unnecessary re-renders.
|
|
45
|
+
With full TypeScript support and straightforward integration, the library enables predictable state management architecture without boilerplate, while maintaining high performance and compatibility with modern build tools.
|
|
46
|
+
|
|
47
|
+
[](https://github.com/d8corp/rune-hub-react/stargazers)
|
|
48
|
+
[](https://github.com/d8corp/rune-hub-react/watchers)
|
|
49
|
+
|
|
50
|
+
## Index
|
|
51
|
+
|
|
52
|
+
<sup>**[ [Install](#install) ]**</sup>
|
|
53
|
+
<sup>**[ [Examples](#examples) ]** [Basic Counter](#basic-counter) • [Todo List](#todo-list)</sup>
|
|
54
|
+
<sup>**[ [API](#api) ]** [HubProvider](#hubprovider) • [useRune](#userune) • [useOn](#useon) • [useAction](#useaction) • [useHub](#usehub) • [useSlot](#useslot)</sup>
|
|
55
|
+
<sup>**[ [Links](#links) ]**</sup>
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
###### [🏠︎](#index) / Install [↓](#examples)
|
|
59
|
+
|
|
60
|
+
**Requires [React 18+](https://www.npmjs.com/package/react) and [rune-hub 1.0+](https://www.npmjs.com/package/rune-hub).**
|
|
61
|
+
|
|
62
|
+
Use with any modern bundler (Vite, Webpack, Rollup, etc.) or framework (Next.js, Remix, etc.).
|
|
63
|
+
|
|
64
|
+
```shell
|
|
65
|
+
npm i rune-hub @rune-hub/react
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
###### [🏠︎](#index) / Examples [↑](#install) [↓](#api)
|
|
70
|
+
|
|
71
|
+
<sup>[Basic Counter](#basic-counter) • [Todo List](#todo-list)</sup>
|
|
72
|
+
|
|
73
|
+
### Basic Counter
|
|
74
|
+
###### [🏠︎](#index) / [Examples](#examples) / Basic Counter [↓](#todo-list)
|
|
75
|
+
|
|
76
|
+
A simple counter demonstrating.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { slot } from 'rune-hub'
|
|
80
|
+
import { useRune } from '@rune-hub/react'
|
|
81
|
+
|
|
82
|
+
const count = () => 0
|
|
83
|
+
const increment = () => slot(count).value++
|
|
84
|
+
const decrement = () => slot(count).value--
|
|
85
|
+
|
|
86
|
+
function Counter () {
|
|
87
|
+
const value = useRune(count)
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div>
|
|
91
|
+
<button onClick={decrement}>-</button>
|
|
92
|
+
<span>{value}</span>
|
|
93
|
+
<button onClick={increment}>+</button>
|
|
94
|
+
</div>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Todo List
|
|
100
|
+
###### [🏠︎](#index) / [Examples](#examples) / Todo List [↑](#basic-counter)
|
|
101
|
+
|
|
102
|
+
A todo list showcasing rune-hub features.
|
|
103
|
+
|
|
104
|
+
Store:
|
|
105
|
+
```ts
|
|
106
|
+
import { get, set, update } from 'rune-hub'
|
|
107
|
+
|
|
108
|
+
export interface Todo {
|
|
109
|
+
id: number
|
|
110
|
+
text: string
|
|
111
|
+
done: boolean
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let nextId = 1
|
|
115
|
+
export const todos = (): Todo[] => []
|
|
116
|
+
|
|
117
|
+
export const addTodo = (text: string) => {
|
|
118
|
+
get(todos).push({ id: nextId++, text, done: false })
|
|
119
|
+
update(todos)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const toggleTodo = (todoId: number) => {
|
|
123
|
+
set(todos, get(todos).map(todo =>
|
|
124
|
+
todoId === todo.id ? { ...todo, done: !todo.done } : todo,
|
|
125
|
+
))
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Component:
|
|
130
|
+
```tsx
|
|
131
|
+
import { useState } from 'react'
|
|
132
|
+
import { useRune } from '@rune-hub/react'
|
|
133
|
+
import { todos, addTodo, toggleTodo } from './store.ts'
|
|
134
|
+
|
|
135
|
+
function TodoList () {
|
|
136
|
+
const todoList = useRune(todos)
|
|
137
|
+
const [text, setText] = useState('')
|
|
138
|
+
|
|
139
|
+
const handleSubmit = (e: any) => {
|
|
140
|
+
e.preventDefault()
|
|
141
|
+
|
|
142
|
+
if (text.trim()) {
|
|
143
|
+
addTodo(text.trim())
|
|
144
|
+
setText('')
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div>
|
|
150
|
+
<form onSubmit={handleSubmit}>
|
|
151
|
+
<input
|
|
152
|
+
value={text}
|
|
153
|
+
onChange={e => setText(e.target.value)}
|
|
154
|
+
placeholder='What needs to be done?'
|
|
155
|
+
/>
|
|
156
|
+
<button type='submit'>Add</button>
|
|
157
|
+
</form>
|
|
158
|
+
<ul>
|
|
159
|
+
{todoList.map(({ id, done, text }) => (
|
|
160
|
+
<li
|
|
161
|
+
key={id}
|
|
162
|
+
onClick={() => toggleTodo(id)}
|
|
163
|
+
style={{ textDecoration: done ? 'line-through' : 'none' }}
|
|
164
|
+
>
|
|
165
|
+
{text}
|
|
166
|
+
</li>
|
|
167
|
+
))}
|
|
168
|
+
</ul>
|
|
169
|
+
</div>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API
|
|
175
|
+
###### [🏠︎](#index) / API [↑](#examples) [↓](#links)
|
|
176
|
+
|
|
177
|
+
<sup>[HubProvider](#hubprovider) • [useRune](#userune) • [useOn](#useon) • [useAction](#useaction) • [useHub](#usehub) • [useSlot](#useslot)</sup>
|
|
178
|
+
|
|
179
|
+
### HubProvider
|
|
180
|
+
###### [🏠︎](#index) / [API](#api) / HubProvider [↓](#userune)
|
|
181
|
+
|
|
182
|
+
The `HubProvider` wraps your component tree and makes a Hub instance available to all child components via [useHub](#usehub) hook.
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { Hub } from 'rune-hub'
|
|
186
|
+
import { HubProvider } from '@rune-hub/react'
|
|
187
|
+
|
|
188
|
+
const myHub = new Hub()
|
|
189
|
+
|
|
190
|
+
function App () {
|
|
191
|
+
return (
|
|
192
|
+
<HubProvider value={myHub}>
|
|
193
|
+
<YourComponents />
|
|
194
|
+
</HubProvider>
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
If you don't provide a Hub, the default `Hub.root` will be used.
|
|
200
|
+
|
|
201
|
+
### useRune
|
|
202
|
+
###### [🏠︎](#index) / [API](#api) / useRune [↑](#hubprovider) [↓](#useon)
|
|
203
|
+
|
|
204
|
+
Uses `useSyncExternalStore` for proper synchronization with React's rendering cycle.
|
|
205
|
+
Automatically subscribes to the Rune's slot and unsubscribes on unmount.
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
import { rune, get } from 'rune-hub'
|
|
209
|
+
import { useRune } from '@rune-hub/react'
|
|
210
|
+
|
|
211
|
+
const count = () => 0
|
|
212
|
+
const log = () => console.log(get(count))
|
|
213
|
+
|
|
214
|
+
function Counter () {
|
|
215
|
+
const value = useRune(count)
|
|
216
|
+
// Subscribe to count changes
|
|
217
|
+
|
|
218
|
+
useRune(log)
|
|
219
|
+
// Activate log effect
|
|
220
|
+
|
|
221
|
+
return <div>Count: {value}</div>
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### useOn
|
|
226
|
+
###### [🏠︎](#index) / [API](#api) / useOn [↑](#userune) [↓](#useaction)
|
|
227
|
+
|
|
228
|
+
Use `useOn` when you need to run side effects (like logging, analytics, or synchronization) that depend on other Runes, but don't need the return value in your component.
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
import { rune, get } from 'rune-hub'
|
|
232
|
+
import { useRune, useOn } from '@rune-hub/react'
|
|
233
|
+
|
|
234
|
+
const count = () => 0
|
|
235
|
+
const log = () => console.log(get(count))
|
|
236
|
+
|
|
237
|
+
function Counter () {
|
|
238
|
+
const value = useRune(count)
|
|
239
|
+
// Subscribe to count changes
|
|
240
|
+
|
|
241
|
+
useOn(log)
|
|
242
|
+
// Activate log effect
|
|
243
|
+
|
|
244
|
+
return <div>Count: {value}</div>
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### useAction
|
|
249
|
+
###### [🏠︎](#index) / [API](#api) / useAction [↑](#useon) [↓](#usehub)
|
|
250
|
+
|
|
251
|
+
The hook automatically binds your action to context Hub.
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import { slot } from 'rune-hub'
|
|
255
|
+
import { useRune, useAction } from '@rune-hub/react'
|
|
256
|
+
|
|
257
|
+
const count = () => 0
|
|
258
|
+
const increment = () => slot(count).value++
|
|
259
|
+
const decrement = () => slot(count).value--
|
|
260
|
+
|
|
261
|
+
function Counter () {
|
|
262
|
+
const value = useRune(count)
|
|
263
|
+
const inc = useAction(increment)
|
|
264
|
+
const dec = useAction(decrement)
|
|
265
|
+
|
|
266
|
+
return (
|
|
267
|
+
<div>
|
|
268
|
+
<button onClick={dec}>-</button>
|
|
269
|
+
<span>{value}</span>
|
|
270
|
+
<button onClick={inc}>+</button>
|
|
271
|
+
</div>
|
|
272
|
+
)
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### useHub
|
|
277
|
+
###### [🏠︎](#index) / [API](#api) / useHub [↑](#useaction) [↓](#useslot)
|
|
278
|
+
|
|
279
|
+
Returns the current Hub instance from context.
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
import { useHub } from '@rune-hub/react'
|
|
283
|
+
|
|
284
|
+
function MyComponent () {
|
|
285
|
+
const hub = useHub()
|
|
286
|
+
|
|
287
|
+
console.log(hub)
|
|
288
|
+
|
|
289
|
+
return <h1>Hello World!</h1>
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### useSlot
|
|
294
|
+
###### [🏠︎](#index) / [API](#api) / useSlot [↑](#usehub)
|
|
295
|
+
|
|
296
|
+
**Returns a Slot instance for a given Rune within the current Hub context.**
|
|
297
|
+
|
|
298
|
+
A Slot is a Hub-scoped reactive container that tracks changes to a Rune. Use this when you need direct access to the [Slot API](https://github.com/d8corp/rune-hub#slot-api) rather than just the value.
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
import { useEffect } from 'react'
|
|
302
|
+
import { useSlot } from '@rune-hub/react'
|
|
303
|
+
|
|
304
|
+
const count = () => 0
|
|
305
|
+
|
|
306
|
+
function Counter () {
|
|
307
|
+
const slot = useSlot(count)
|
|
308
|
+
|
|
309
|
+
useEffect(() => {
|
|
310
|
+
// Access raw value without subscribing
|
|
311
|
+
console.log(slot.raw)
|
|
312
|
+
|
|
313
|
+
// Manually listen to changes
|
|
314
|
+
return slot.on('change', () => {
|
|
315
|
+
console.log('Count changed:', slot.raw)
|
|
316
|
+
})
|
|
317
|
+
}, [slot])
|
|
318
|
+
|
|
319
|
+
return <div>Count: {slot.raw}</div>
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The Slot instance is memoized and stable for the Rune and Hub combination.
|
|
324
|
+
|
|
325
|
+
## Links
|
|
326
|
+
###### [🏠︎](#index) / Links [↑](#examples)
|
|
327
|
+
|
|
328
|
+
- **Creator**: [Mike Lysikov](http://github.com/d8corp)
|
|
329
|
+
- **Source Code**: [GitHub](https://github.com/d8corp/rune-hub-react)
|
|
330
|
+
- **Repository**: [npm](https://www.npmjs.com/package/@rune-hub/react) • [npmx](https://npmx.dev/package/@rune-hub/react)
|
|
331
|
+
- **Utils**: [@rune-hub/utils](https://github.com/d8corp/rune-hub-utils)
|
|
332
|
+
|
|
333
|
+
**Contributions are welcome!** Please feel free to submit [issues](https://github.com/d8corp/rune-hub-react/issues) and [pull requests](https://github.com/d8corp/rune-hub-react/pulls).
|
|
334
|
+
|
|
335
|
+
[](https://github.com/d8corp/rune-hub-react/issues)
|
|
336
|
+
[](https://github.com/d8corp/rune-hub-react/pulls)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Hub } from 'rune-hub';
|
|
2
|
+
export declare const HubContext: import("react").Context<Hub>;
|
|
3
|
+
/**
|
|
4
|
+
* Wraps your component tree and makes a Hub instance available to all child components.
|
|
5
|
+
*
|
|
6
|
+
* If you don't provide a Hub via the `value` prop, the default `Hub.root` will be used.
|
|
7
|
+
* All hooks like `useRune`, `useAction`, and `useHub` will use the Hub from this context.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#hubprovider}
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { Hub } from 'rune-hub'
|
|
14
|
+
* import { HubProvider } from '@rune-hub/react'
|
|
15
|
+
*
|
|
16
|
+
* const myHub = new Hub()
|
|
17
|
+
*
|
|
18
|
+
* function App () {
|
|
19
|
+
* return (
|
|
20
|
+
* <HubProvider value={myHub}>
|
|
21
|
+
* <YourComponents />
|
|
22
|
+
* </HubProvider>
|
|
23
|
+
* )
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const HubProvider: import("react").Provider<Hub>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
import { Hub } from 'rune-hub';
|
|
3
|
+
|
|
4
|
+
var HubContext = createContext(Hub.root);
|
|
5
|
+
/**
|
|
6
|
+
* Wraps your component tree and makes a Hub instance available to all child components.
|
|
7
|
+
*
|
|
8
|
+
* If you don't provide a Hub via the `value` prop, the default `Hub.root` will be used.
|
|
9
|
+
* All hooks like `useRune`, `useAction`, and `useHub` will use the Hub from this context.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#hubprovider}
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { Hub } from 'rune-hub'
|
|
16
|
+
* import { HubProvider } from '@rune-hub/react'
|
|
17
|
+
*
|
|
18
|
+
* const myHub = new Hub()
|
|
19
|
+
*
|
|
20
|
+
* function App () {
|
|
21
|
+
* return (
|
|
22
|
+
* <HubProvider value={myHub}>
|
|
23
|
+
* <YourComponents />
|
|
24
|
+
* </HubProvider>
|
|
25
|
+
* )
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
var HubProvider = HubContext.Provider;
|
|
30
|
+
|
|
31
|
+
export { HubContext, HubProvider };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var runeHub = require('rune-hub');
|
|
7
|
+
|
|
8
|
+
var HubContext = react.createContext(runeHub.Hub.root);
|
|
9
|
+
/**
|
|
10
|
+
* Wraps your component tree and makes a Hub instance available to all child components.
|
|
11
|
+
*
|
|
12
|
+
* If you don't provide a Hub via the `value` prop, the default `Hub.root` will be used.
|
|
13
|
+
* All hooks like `useRune`, `useAction`, and `useHub` will use the Hub from this context.
|
|
14
|
+
*
|
|
15
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#hubprovider}
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import { Hub } from 'rune-hub'
|
|
20
|
+
* import { HubProvider } from '@rune-hub/react'
|
|
21
|
+
*
|
|
22
|
+
* const myHub = new Hub()
|
|
23
|
+
*
|
|
24
|
+
* function App () {
|
|
25
|
+
* return (
|
|
26
|
+
* <HubProvider value={myHub}>
|
|
27
|
+
* <YourComponents />
|
|
28
|
+
* </HubProvider>
|
|
29
|
+
* )
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
var HubProvider = HubContext.Provider;
|
|
34
|
+
|
|
35
|
+
exports.HubContext = HubContext;
|
|
36
|
+
exports.HubProvider = HubProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './HubContext';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HubContext, HubProvider } from './HubContext.es6.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './HubContext';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './HubContext/index.es6.js';
|
package/context/index.js
ADDED
package/hooks/index.d.ts
ADDED
package/hooks/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useAction';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useAction } from './useAction.es6.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Fn } from 'rune-hub';
|
|
2
|
+
/**
|
|
3
|
+
* The hook automatically binds your action to context Hub, ensuring all Rune mutations
|
|
4
|
+
* triggered inside the action are tracked within the same Hub instance.
|
|
5
|
+
*
|
|
6
|
+
* @template T - The action function type
|
|
7
|
+
* @param action - The action function to bind to the Hub
|
|
8
|
+
* @returns A stable callback that executes the action in the Hub context
|
|
9
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useaction}
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const count = () => 0
|
|
14
|
+
* const increment = () => slot(count).value++
|
|
15
|
+
*
|
|
16
|
+
* function Counter () {
|
|
17
|
+
* const value = useRune(count)
|
|
18
|
+
* const inc = useAction(increment)
|
|
19
|
+
*
|
|
20
|
+
* return <button onClick={inc}>Count: {value}</button>
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function useAction<T extends Fn>(action: T): T;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { __spreadArray, __read } from 'tslib';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import '../useHub/index.es6.js';
|
|
4
|
+
import { useHub } from '../useHub/useHub.es6.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The hook automatically binds your action to context Hub, ensuring all Rune mutations
|
|
8
|
+
* triggered inside the action are tracked within the same Hub instance.
|
|
9
|
+
*
|
|
10
|
+
* @template T - The action function type
|
|
11
|
+
* @param action - The action function to bind to the Hub
|
|
12
|
+
* @returns A stable callback that executes the action in the Hub context
|
|
13
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useaction}
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const count = () => 0
|
|
18
|
+
* const increment = () => slot(count).value++
|
|
19
|
+
*
|
|
20
|
+
* function Counter () {
|
|
21
|
+
* const value = useRune(count)
|
|
22
|
+
* const inc = useAction(increment)
|
|
23
|
+
*
|
|
24
|
+
* return <button onClick={inc}>Count: {value}</button>
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function useAction(action) {
|
|
29
|
+
var hub = useHub();
|
|
30
|
+
return useCallback((function () {
|
|
31
|
+
var args = [];
|
|
32
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
33
|
+
args[_i] = arguments[_i];
|
|
34
|
+
}
|
|
35
|
+
return hub.use(function () { return action.apply(void 0, __spreadArray([], __read(args), false)); });
|
|
36
|
+
}), [hub, action]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { useAction };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
require('../useHub/index.js');
|
|
8
|
+
var useHub = require('../useHub/useHub.js');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The hook automatically binds your action to context Hub, ensuring all Rune mutations
|
|
12
|
+
* triggered inside the action are tracked within the same Hub instance.
|
|
13
|
+
*
|
|
14
|
+
* @template T - The action function type
|
|
15
|
+
* @param action - The action function to bind to the Hub
|
|
16
|
+
* @returns A stable callback that executes the action in the Hub context
|
|
17
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useaction}
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const count = () => 0
|
|
22
|
+
* const increment = () => slot(count).value++
|
|
23
|
+
*
|
|
24
|
+
* function Counter () {
|
|
25
|
+
* const value = useRune(count)
|
|
26
|
+
* const inc = useAction(increment)
|
|
27
|
+
*
|
|
28
|
+
* return <button onClick={inc}>Count: {value}</button>
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function useAction(action) {
|
|
33
|
+
var hub = useHub.useHub();
|
|
34
|
+
return react.useCallback((function () {
|
|
35
|
+
var args = [];
|
|
36
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
37
|
+
args[_i] = arguments[_i];
|
|
38
|
+
}
|
|
39
|
+
return hub.use(function () { return action.apply(void 0, tslib.__spreadArray([], tslib.__read(args), false)); });
|
|
40
|
+
}), [hub, action]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
exports.useAction = useAction;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useHub';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useHub } from './useHub.es6.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the current Hub instance from context.
|
|
3
|
+
*
|
|
4
|
+
* If no Hub is provided via HubProvider, returns the default `Hub.root` instance.
|
|
5
|
+
*
|
|
6
|
+
* @returns The current Hub instance
|
|
7
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#usehub}
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* function MyComponent () {
|
|
12
|
+
* const hub = useHub()
|
|
13
|
+
*
|
|
14
|
+
* console.log(hub)
|
|
15
|
+
*
|
|
16
|
+
* return <h1>Hello World!</h1>
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function useHub(): import("rune-hub").Hub;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import '../../context/index.es6.js';
|
|
3
|
+
import { HubContext } from '../../context/HubContext/HubContext.es6.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current Hub instance from context.
|
|
7
|
+
*
|
|
8
|
+
* If no Hub is provided via HubProvider, returns the default `Hub.root` instance.
|
|
9
|
+
*
|
|
10
|
+
* @returns The current Hub instance
|
|
11
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#usehub}
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* function MyComponent () {
|
|
16
|
+
* const hub = useHub()
|
|
17
|
+
*
|
|
18
|
+
* console.log(hub)
|
|
19
|
+
*
|
|
20
|
+
* return <h1>Hello World!</h1>
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function useHub() {
|
|
25
|
+
return useContext(HubContext);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { useHub };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
require('../../context/index.js');
|
|
7
|
+
var HubContext = require('../../context/HubContext/HubContext.js');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns the current Hub instance from context.
|
|
11
|
+
*
|
|
12
|
+
* If no Hub is provided via HubProvider, returns the default `Hub.root` instance.
|
|
13
|
+
*
|
|
14
|
+
* @returns The current Hub instance
|
|
15
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#usehub}
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* function MyComponent () {
|
|
20
|
+
* const hub = useHub()
|
|
21
|
+
*
|
|
22
|
+
* console.log(hub)
|
|
23
|
+
*
|
|
24
|
+
* return <h1>Hello World!</h1>
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function useHub() {
|
|
29
|
+
return react.useContext(HubContext.HubContext);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
exports.useHub = useHub;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useOn';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useOn } from './useOn.es6.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Rune } from 'rune-hub';
|
|
2
|
+
/**
|
|
3
|
+
* Activates a Rune effect without subscribing to its value.
|
|
4
|
+
* The hook automatically subscribes to the Rune's slot on mount and unsubscribes on unmount.
|
|
5
|
+
*
|
|
6
|
+
* @param rune - The Rune to activate
|
|
7
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useon}
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const count = () => 0
|
|
12
|
+
* const log = () => console.log(get(count))
|
|
13
|
+
*
|
|
14
|
+
* function Counter () {
|
|
15
|
+
* const value = useRune(count)
|
|
16
|
+
*
|
|
17
|
+
* useOn(log)
|
|
18
|
+
*
|
|
19
|
+
* return <div>Count: {value}</div>
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function useOn(rune: Rune): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import '../useSlot/index.es6.js';
|
|
3
|
+
import { useSlot } from '../useSlot/useSlot.es6.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Activates a Rune effect without subscribing to its value.
|
|
7
|
+
* The hook automatically subscribes to the Rune's slot on mount and unsubscribes on unmount.
|
|
8
|
+
*
|
|
9
|
+
* @param rune - The Rune to activate
|
|
10
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useon}
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const count = () => 0
|
|
15
|
+
* const log = () => console.log(get(count))
|
|
16
|
+
*
|
|
17
|
+
* function Counter () {
|
|
18
|
+
* const value = useRune(count)
|
|
19
|
+
*
|
|
20
|
+
* useOn(log)
|
|
21
|
+
*
|
|
22
|
+
* return <div>Count: {value}</div>
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function useOn(rune) {
|
|
27
|
+
var slot = useSlot(rune);
|
|
28
|
+
useEffect(function () { return slot.on(); }, [slot]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { useOn };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
require('../useSlot/index.js');
|
|
7
|
+
var useSlot = require('../useSlot/useSlot.js');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Activates a Rune effect without subscribing to its value.
|
|
11
|
+
* The hook automatically subscribes to the Rune's slot on mount and unsubscribes on unmount.
|
|
12
|
+
*
|
|
13
|
+
* @param rune - The Rune to activate
|
|
14
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useon}
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const count = () => 0
|
|
19
|
+
* const log = () => console.log(get(count))
|
|
20
|
+
*
|
|
21
|
+
* function Counter () {
|
|
22
|
+
* const value = useRune(count)
|
|
23
|
+
*
|
|
24
|
+
* useOn(log)
|
|
25
|
+
*
|
|
26
|
+
* return <div>Count: {value}</div>
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function useOn(rune) {
|
|
31
|
+
var slot = useSlot.useSlot(rune);
|
|
32
|
+
react.useEffect(function () { return slot.on(); }, [slot]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.useOn = useOn;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useRune';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useRune } from './useRune.es6.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Rune } from 'rune-hub';
|
|
2
|
+
/**
|
|
3
|
+
* Subscribes to a Rune and returns its current value.
|
|
4
|
+
*
|
|
5
|
+
* Uses `useSyncExternalStore` for proper synchronization with React's rendering cycle.
|
|
6
|
+
* Automatically subscribes to the Rune's slot and unsubscribes on unmount.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The Rune type
|
|
9
|
+
* @param rune - The Rune to subscribe to
|
|
10
|
+
* @returns The current value of the Rune
|
|
11
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#userune}
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const count = () => 0
|
|
16
|
+
*
|
|
17
|
+
* function Counter () {
|
|
18
|
+
* const value = useRune(count)
|
|
19
|
+
*
|
|
20
|
+
* return <div>Count: {value}</div>
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function useRune<T extends Rune>(rune: T): ReturnType<T>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useMemo, useEffect, useCallback, useSyncExternalStore } from 'react';
|
|
2
|
+
import '../useSlot/index.es6.js';
|
|
3
|
+
import { useSlot } from '../useSlot/useSlot.es6.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Subscribes to a Rune and returns its current value.
|
|
7
|
+
*
|
|
8
|
+
* Uses `useSyncExternalStore` for proper synchronization with React's rendering cycle.
|
|
9
|
+
* Automatically subscribes to the Rune's slot and unsubscribes on unmount.
|
|
10
|
+
*
|
|
11
|
+
* @template T - The Rune type
|
|
12
|
+
* @param rune - The Rune to subscribe to
|
|
13
|
+
* @returns The current value of the Rune
|
|
14
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#userune}
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const count = () => 0
|
|
19
|
+
*
|
|
20
|
+
* function Counter () {
|
|
21
|
+
* const value = useRune(count)
|
|
22
|
+
*
|
|
23
|
+
* return <div>Count: {value}</div>
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function useRune(rune) {
|
|
28
|
+
var slot = useSlot(rune);
|
|
29
|
+
var stop = useMemo(function () { return slot.on(); }, [slot]);
|
|
30
|
+
useEffect(function () { return stop; }, [stop]);
|
|
31
|
+
var subscribe = useCallback(function (callback) {
|
|
32
|
+
return slot.on('change', callback);
|
|
33
|
+
}, [slot]);
|
|
34
|
+
return useSyncExternalStore(subscribe, function () { return slot.raw; });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { useRune };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
require('../useSlot/index.js');
|
|
7
|
+
var useSlot = require('../useSlot/useSlot.js');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Subscribes to a Rune and returns its current value.
|
|
11
|
+
*
|
|
12
|
+
* Uses `useSyncExternalStore` for proper synchronization with React's rendering cycle.
|
|
13
|
+
* Automatically subscribes to the Rune's slot and unsubscribes on unmount.
|
|
14
|
+
*
|
|
15
|
+
* @template T - The Rune type
|
|
16
|
+
* @param rune - The Rune to subscribe to
|
|
17
|
+
* @returns The current value of the Rune
|
|
18
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#userune}
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const count = () => 0
|
|
23
|
+
*
|
|
24
|
+
* function Counter () {
|
|
25
|
+
* const value = useRune(count)
|
|
26
|
+
*
|
|
27
|
+
* return <div>Count: {value}</div>
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
function useRune(rune) {
|
|
32
|
+
var slot = useSlot.useSlot(rune);
|
|
33
|
+
var stop = react.useMemo(function () { return slot.on(); }, [slot]);
|
|
34
|
+
react.useEffect(function () { return stop; }, [stop]);
|
|
35
|
+
var subscribe = react.useCallback(function (callback) {
|
|
36
|
+
return slot.on('change', callback);
|
|
37
|
+
}, [slot]);
|
|
38
|
+
return react.useSyncExternalStore(subscribe, function () { return slot.raw; });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.useRune = useRune;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useSlot';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSlot } from './useSlot.es6.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Rune, Slot } from 'rune-hub';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a Slot instance for a given Rune within the current Hub context.
|
|
4
|
+
*
|
|
5
|
+
* A Slot is a Hub-scoped reactive container that tracks changes to a Rune.
|
|
6
|
+
* The Slot instance is memoized and stable for the Rune and Hub combination.
|
|
7
|
+
*
|
|
8
|
+
* @template T - The Rune value type
|
|
9
|
+
* @param rune - The Rune to get a Slot for
|
|
10
|
+
* @returns A memoized Slot instance for the Rune
|
|
11
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useslot}
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const count = () => 0
|
|
16
|
+
*
|
|
17
|
+
* function Counter () {
|
|
18
|
+
* const slot = useSlot(count)
|
|
19
|
+
*
|
|
20
|
+
* useEffect(() => {
|
|
21
|
+
* // Access raw value without subscribing
|
|
22
|
+
* console.log(slot.raw)
|
|
23
|
+
*
|
|
24
|
+
* // Manually listen to changes
|
|
25
|
+
* return slot.on('change', () => {
|
|
26
|
+
* console.log('Count changed:', slot.raw)
|
|
27
|
+
* })
|
|
28
|
+
* }, [slot])
|
|
29
|
+
*
|
|
30
|
+
* return <div>Count: {slot.raw}</div>
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function useSlot<T>(rune: Rune<T>): Slot<T>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { slot } from 'rune-hub';
|
|
3
|
+
import '../useHub/index.es6.js';
|
|
4
|
+
import { useHub } from '../useHub/useHub.es6.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Returns a Slot instance for a given Rune within the current Hub context.
|
|
8
|
+
*
|
|
9
|
+
* A Slot is a Hub-scoped reactive container that tracks changes to a Rune.
|
|
10
|
+
* The Slot instance is memoized and stable for the Rune and Hub combination.
|
|
11
|
+
*
|
|
12
|
+
* @template T - The Rune value type
|
|
13
|
+
* @param rune - The Rune to get a Slot for
|
|
14
|
+
* @returns A memoized Slot instance for the Rune
|
|
15
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useslot}
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const count = () => 0
|
|
20
|
+
*
|
|
21
|
+
* function Counter () {
|
|
22
|
+
* const slot = useSlot(count)
|
|
23
|
+
*
|
|
24
|
+
* useEffect(() => {
|
|
25
|
+
* // Access raw value without subscribing
|
|
26
|
+
* console.log(slot.raw)
|
|
27
|
+
*
|
|
28
|
+
* // Manually listen to changes
|
|
29
|
+
* return slot.on('change', () => {
|
|
30
|
+
* console.log('Count changed:', slot.raw)
|
|
31
|
+
* })
|
|
32
|
+
* }, [slot])
|
|
33
|
+
*
|
|
34
|
+
* return <div>Count: {slot.raw}</div>
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function useSlot(rune) {
|
|
39
|
+
var hub = useHub();
|
|
40
|
+
return useMemo(function () { return hub.use(function () { return slot(rune); }); }, [rune, hub]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { useSlot };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var runeHub = require('rune-hub');
|
|
7
|
+
require('../useHub/index.js');
|
|
8
|
+
var useHub = require('../useHub/useHub.js');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns a Slot instance for a given Rune within the current Hub context.
|
|
12
|
+
*
|
|
13
|
+
* A Slot is a Hub-scoped reactive container that tracks changes to a Rune.
|
|
14
|
+
* The Slot instance is memoized and stable for the Rune and Hub combination.
|
|
15
|
+
*
|
|
16
|
+
* @template T - The Rune value type
|
|
17
|
+
* @param rune - The Rune to get a Slot for
|
|
18
|
+
* @returns A memoized Slot instance for the Rune
|
|
19
|
+
* @see {@link https://github.com/d8corp/rune-hub-react#useslot}
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* const count = () => 0
|
|
24
|
+
*
|
|
25
|
+
* function Counter () {
|
|
26
|
+
* const slot = useSlot(count)
|
|
27
|
+
*
|
|
28
|
+
* useEffect(() => {
|
|
29
|
+
* // Access raw value without subscribing
|
|
30
|
+
* console.log(slot.raw)
|
|
31
|
+
*
|
|
32
|
+
* // Manually listen to changes
|
|
33
|
+
* return slot.on('change', () => {
|
|
34
|
+
* console.log('Count changed:', slot.raw)
|
|
35
|
+
* })
|
|
36
|
+
* }, [slot])
|
|
37
|
+
*
|
|
38
|
+
* return <div>Count: {slot.raw}</div>
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
function useSlot(rune) {
|
|
43
|
+
var hub = useHub.useHub();
|
|
44
|
+
return react.useMemo(function () { return hub.use(function () { return runeHub.slot(rune); }); }, [rune, hub]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
exports.useSlot = useSlot;
|
package/index.d.ts
ADDED
package/index.es6.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import './context/index.es6.js';
|
|
2
|
+
import './hooks/index.es6.js';
|
|
3
|
+
export { HubContext, HubProvider } from './context/HubContext/HubContext.es6.js';
|
|
4
|
+
export { useAction } from './hooks/useAction/useAction.es6.js';
|
|
5
|
+
export { useHub } from './hooks/useHub/useHub.es6.js';
|
|
6
|
+
export { useOn } from './hooks/useOn/useOn.es6.js';
|
|
7
|
+
export { useRune } from './hooks/useRune/useRune.es6.js';
|
|
8
|
+
export { useSlot } from './hooks/useSlot/useSlot.es6.js';
|
package/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
require('./context/index.js');
|
|
6
|
+
require('./hooks/index.js');
|
|
7
|
+
var HubContext = require('./context/HubContext/HubContext.js');
|
|
8
|
+
var useAction = require('./hooks/useAction/useAction.js');
|
|
9
|
+
var useHub = require('./hooks/useHub/useHub.js');
|
|
10
|
+
var useOn = require('./hooks/useOn/useOn.js');
|
|
11
|
+
var useRune = require('./hooks/useRune/useRune.js');
|
|
12
|
+
var useSlot = require('./hooks/useSlot/useSlot.js');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
exports.HubContext = HubContext.HubContext;
|
|
17
|
+
exports.HubProvider = HubContext.HubProvider;
|
|
18
|
+
exports.useAction = useAction.useAction;
|
|
19
|
+
exports.useHub = useHub.useHub;
|
|
20
|
+
exports.useOn = useOn.useOn;
|
|
21
|
+
exports.useRune = useRune.useRune;
|
|
22
|
+
exports.useSlot = useSlot.useSlot;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rune-hub/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Integrating RuneHub with React",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"module": "index.es6.js",
|
|
7
|
+
"jsnext:main": "index.es6.js",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "innetjs release",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"test:coverage": "jest --coverage",
|
|
13
|
+
"speed": "innetjs run speed.test.ts",
|
|
14
|
+
"release": "innetjs release -p",
|
|
15
|
+
"patch": "innetjs patch",
|
|
16
|
+
"minor": "innetjs minor",
|
|
17
|
+
"major": "innetjs major",
|
|
18
|
+
"lint": "eslint",
|
|
19
|
+
"lint:fix": "eslint --fix"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/d8corp/rune-hub-react.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"watch",
|
|
27
|
+
"state",
|
|
28
|
+
"stateful",
|
|
29
|
+
"reaction",
|
|
30
|
+
"reactions",
|
|
31
|
+
"react",
|
|
32
|
+
"reactive",
|
|
33
|
+
"observe",
|
|
34
|
+
"observable",
|
|
35
|
+
"front-end"
|
|
36
|
+
],
|
|
37
|
+
"author": "Mikhail Lysikov <d8corp@mail.ru>",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/d8corp/rune-hub-react/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/d8corp/rune-hub-react",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"react": ">=18",
|
|
45
|
+
"rune-hub": "^1.0.0"
|
|
46
|
+
}
|
|
47
|
+
}
|