@nativewindow/react 0.1.1 → 1.0.1
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 +10 -7
- package/dist/index.d.ts +57 -34
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@nativewindow/react)
|
|
4
4
|
|
|
5
|
-
> [!
|
|
6
|
-
> This project is in **
|
|
5
|
+
> [!NOTE]
|
|
6
|
+
> This project is in **beta**. APIs may change without notice.
|
|
7
7
|
|
|
8
8
|
React hooks for [native-window-ipc](https://github.com/nativewindow/webview/tree/main/packages/ipc). Provides type-safe React bindings for the webview side of the IPC channel.
|
|
9
9
|
|
|
@@ -32,10 +32,12 @@ import { z } from "zod";
|
|
|
32
32
|
import { createChannelHooks } from "@nativewindow/react";
|
|
33
33
|
|
|
34
34
|
export const { ChannelProvider, useChannel, useChannelEvent, useSend } = createChannelHooks({
|
|
35
|
-
|
|
36
|
-
counter: z.number(),
|
|
35
|
+
host: {
|
|
37
36
|
"update-title": z.string(),
|
|
38
37
|
},
|
|
38
|
+
client: {
|
|
39
|
+
counter: z.number(),
|
|
40
|
+
},
|
|
39
41
|
});
|
|
40
42
|
```
|
|
41
43
|
|
|
@@ -64,11 +66,12 @@ function Counter() {
|
|
|
64
66
|
const [count, setCount] = useState(0);
|
|
65
67
|
const send = useSend();
|
|
66
68
|
|
|
67
|
-
// Subscribe to events with automatic cleanup
|
|
68
|
-
useChannelEvent("
|
|
69
|
-
|
|
69
|
+
// Subscribe to host events with automatic cleanup
|
|
70
|
+
useChannelEvent("update-title", (title) => {
|
|
71
|
+
document.title = title;
|
|
70
72
|
});
|
|
71
73
|
|
|
74
|
+
// Send client events to the host
|
|
72
75
|
return <button onClick={() => send("counter", count + 1)}>Count: {count}</button>;
|
|
73
76
|
}
|
|
74
77
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ import { EventMap, SendArgs, SchemaMap, InferSchemaMap, TypedChannel, Validation
|
|
|
17
17
|
*
|
|
18
18
|
* const { ChannelProvider, useChannel, useChannelEvent, useSend } =
|
|
19
19
|
* createChannelHooks({
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* host: { title: z.string() },
|
|
21
|
+
* client: { counter: z.number() },
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* function App() {
|
|
@@ -45,14 +45,21 @@ export type { ChannelClientOptions } from '../ipc/client.ts';
|
|
|
45
45
|
*
|
|
46
46
|
* @example
|
|
47
47
|
* ```tsx
|
|
48
|
-
* <ChannelProvider schemas={
|
|
48
|
+
* <ChannelProvider schemas={{ host: hostSchemas, client: clientSchemas }}>
|
|
49
49
|
* <App />
|
|
50
50
|
* </ChannelProvider>
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
|
-
export interface ChannelProviderProps<
|
|
54
|
-
/**
|
|
55
|
-
|
|
53
|
+
export interface ChannelProviderProps<H extends SchemaMap, C extends SchemaMap> {
|
|
54
|
+
/**
|
|
55
|
+
* Directional schemas for the channel.
|
|
56
|
+
* - `host`: events the host sends to the client (validated on receive).
|
|
57
|
+
* - `client`: events the client sends to the host (type-checked on send).
|
|
58
|
+
*/
|
|
59
|
+
schemas: {
|
|
60
|
+
host: H;
|
|
61
|
+
client: C;
|
|
62
|
+
};
|
|
56
63
|
/**
|
|
57
64
|
* Called when an incoming payload fails schema validation.
|
|
58
65
|
* If not provided, failed payloads are silently dropped.
|
|
@@ -74,8 +81,8 @@ export interface ChannelProviderProps<S extends SchemaMap> {
|
|
|
74
81
|
* import { ChannelProvider } from "@nativewindow/react";
|
|
75
82
|
*
|
|
76
83
|
* const schemas = {
|
|
77
|
-
*
|
|
78
|
-
*
|
|
84
|
+
* host: { title: z.string() },
|
|
85
|
+
* client: { counter: z.number() },
|
|
79
86
|
* };
|
|
80
87
|
*
|
|
81
88
|
* function Root() {
|
|
@@ -87,67 +94,76 @@ export interface ChannelProviderProps<S extends SchemaMap> {
|
|
|
87
94
|
* }
|
|
88
95
|
* ```
|
|
89
96
|
*/
|
|
90
|
-
export declare function ChannelProvider<
|
|
97
|
+
export declare function ChannelProvider<H extends SchemaMap, C extends SchemaMap>(props: ChannelProviderProps<H, C>): ReactNode;
|
|
91
98
|
/**
|
|
92
99
|
* Access the typed IPC channel from context.
|
|
93
100
|
*
|
|
94
101
|
* Must be called inside a {@link ChannelProvider}. Throws if the
|
|
95
102
|
* provider is missing.
|
|
96
103
|
*
|
|
104
|
+
* @typeParam Send - Events this side can send (client events).
|
|
105
|
+
* @typeParam Receive - Events this side can receive (host events).
|
|
106
|
+
*
|
|
97
107
|
* @example
|
|
98
108
|
* ```tsx
|
|
99
109
|
* import { useChannel } from "@nativewindow/react";
|
|
100
110
|
*
|
|
101
|
-
* type
|
|
111
|
+
* type ClientEvents = { counter: number };
|
|
112
|
+
* type HostEvents = { title: string };
|
|
102
113
|
*
|
|
103
114
|
* function StatusBar() {
|
|
104
|
-
* const channel = useChannel<
|
|
115
|
+
* const channel = useChannel<ClientEvents, HostEvents>();
|
|
105
116
|
* channel.send("counter", 1);
|
|
106
117
|
* }
|
|
107
118
|
* ```
|
|
108
119
|
*/
|
|
109
|
-
export declare function useChannel<
|
|
120
|
+
export declare function useChannel<Send extends EventMap = EventMap, Receive extends EventMap = EventMap>(): TypedChannel<Send, Receive>;
|
|
110
121
|
/**
|
|
111
|
-
* Subscribe to a specific IPC event type with automatic cleanup.
|
|
122
|
+
* Subscribe to a specific incoming IPC event type with automatic cleanup.
|
|
112
123
|
*
|
|
113
124
|
* The handler is stored in a ref to avoid re-subscribing when the
|
|
114
125
|
* handler function identity changes between renders. The subscription
|
|
115
126
|
* itself only re-runs when `type` changes.
|
|
116
127
|
*
|
|
128
|
+
* @typeParam Receive - The event map for incoming (receivable) events.
|
|
129
|
+
* @typeParam K - The specific event key to subscribe to.
|
|
130
|
+
*
|
|
117
131
|
* @example
|
|
118
132
|
* ```tsx
|
|
119
133
|
* import { useChannelEvent } from "@nativewindow/react";
|
|
120
134
|
*
|
|
121
|
-
* type
|
|
135
|
+
* type HostEvents = { title: string };
|
|
122
136
|
*
|
|
123
137
|
* function TitleDisplay() {
|
|
124
|
-
* useChannelEvent<
|
|
138
|
+
* useChannelEvent<HostEvents, "title">("title", (title) => {
|
|
125
139
|
* document.title = title;
|
|
126
140
|
* });
|
|
127
141
|
* return null;
|
|
128
142
|
* }
|
|
129
143
|
* ```
|
|
130
144
|
*/
|
|
131
|
-
export declare function useChannelEvent<
|
|
145
|
+
export declare function useChannelEvent<Receive extends EventMap = EventMap, K extends keyof Receive & string = keyof Receive & string>(type: K, handler: (payload: Receive[K]) => void): void;
|
|
132
146
|
/**
|
|
133
147
|
* Returns a stable `send` function from the channel.
|
|
134
148
|
*
|
|
135
149
|
* A convenience wrapper around `useChannel().send`. The returned
|
|
136
150
|
* function has a stable identity (does not change between renders).
|
|
137
151
|
*
|
|
152
|
+
* @typeParam Send - The event map for outgoing (sendable) events.
|
|
153
|
+
*
|
|
138
154
|
* @example
|
|
139
155
|
* ```tsx
|
|
140
156
|
* import { useSend } from "@nativewindow/react";
|
|
141
157
|
*
|
|
142
|
-
* type
|
|
158
|
+
* type ClientEvents = { counter: number };
|
|
143
159
|
*
|
|
144
160
|
* function Counter() {
|
|
145
|
-
* const send = useSend<
|
|
161
|
+
* const send = useSend<ClientEvents>();
|
|
146
162
|
* return <button onClick={() => send("counter", 1)}>Increment</button>;
|
|
147
163
|
* }
|
|
148
164
|
* ```
|
|
149
165
|
*/
|
|
150
|
-
export declare function useSend<
|
|
166
|
+
export declare function useSend<Send extends EventMap = EventMap>(): <K extends keyof Send & string>(...args: SendArgs<Send, K>) => void;
|
|
151
167
|
/**
|
|
152
168
|
* Options for {@link createChannelHooks}.
|
|
153
169
|
*
|
|
@@ -169,11 +185,15 @@ export interface ChannelHooksOptions {
|
|
|
169
185
|
* The set of pre-typed React hooks and provider returned by
|
|
170
186
|
* {@link createChannelHooks}.
|
|
171
187
|
*
|
|
172
|
-
* All hooks are bound to the same internal context and typed
|
|
173
|
-
* so event names and payload types are
|
|
174
|
-
* requiring generic type parameters
|
|
188
|
+
* All hooks are bound to the same internal context and typed with
|
|
189
|
+
* separate Send/Receive maps, so event names and payload types are
|
|
190
|
+
* inferred automatically without requiring generic type parameters
|
|
191
|
+
* at the call site.
|
|
192
|
+
*
|
|
193
|
+
* @typeParam Send - Events the client sends to the host.
|
|
194
|
+
* @typeParam Receive - Events the client receives from the host.
|
|
175
195
|
*/
|
|
176
|
-
export interface TypedChannelHooks<
|
|
196
|
+
export interface TypedChannelHooks<Send extends EventMap, Receive extends EventMap> {
|
|
177
197
|
/**
|
|
178
198
|
* Context provider that creates the channel client once.
|
|
179
199
|
* Wrap your React app with this at the root.
|
|
@@ -182,11 +202,11 @@ export interface TypedChannelHooks<T extends EventMap> {
|
|
|
182
202
|
children: ReactNode;
|
|
183
203
|
}) => ReactNode;
|
|
184
204
|
/** Access the typed channel from context. Throws if outside the provider. */
|
|
185
|
-
useChannel: () => TypedChannel<
|
|
186
|
-
/** Subscribe to a typed event with automatic cleanup. */
|
|
187
|
-
useChannelEvent: <K extends keyof
|
|
188
|
-
/** Returns a stable typed `send` function. */
|
|
189
|
-
useSend: () => <K extends keyof
|
|
205
|
+
useChannel: () => TypedChannel<Send, Receive>;
|
|
206
|
+
/** Subscribe to a typed incoming (host) event with automatic cleanup. */
|
|
207
|
+
useChannelEvent: <K extends keyof Receive & string>(type: K, handler: (payload: Receive[K]) => void) => void;
|
|
208
|
+
/** Returns a stable typed `send` function for outgoing (client) events. */
|
|
209
|
+
useSend: () => <K extends keyof Send & string>(...args: SendArgs<Send, K>) => void;
|
|
190
210
|
}
|
|
191
211
|
/**
|
|
192
212
|
* Create a set of pre-typed React hooks for the IPC channel.
|
|
@@ -200,16 +220,16 @@ export interface TypedChannelHooks<T extends EventMap> {
|
|
|
200
220
|
* import { z } from "zod";
|
|
201
221
|
* import { createChannelHooks } from "@nativewindow/react";
|
|
202
222
|
*
|
|
203
|
-
* // Types are inferred
|
|
223
|
+
* // Types are inferred from directional schemas
|
|
204
224
|
* const { ChannelProvider, useChannel, useChannelEvent, useSend } =
|
|
205
225
|
* createChannelHooks({
|
|
206
|
-
*
|
|
207
|
-
*
|
|
226
|
+
* host: { title: z.string() },
|
|
227
|
+
* client: { counter: z.number() },
|
|
208
228
|
* });
|
|
209
229
|
*
|
|
210
230
|
* function App() {
|
|
211
|
-
* const send = useSend(); // fully typed
|
|
212
|
-
* useChannelEvent("title", (t) => { // t: string
|
|
231
|
+
* const send = useSend(); // fully typed (client events)
|
|
232
|
+
* useChannelEvent("title", (t) => { // t: string (host events)
|
|
213
233
|
* document.title = t;
|
|
214
234
|
* });
|
|
215
235
|
* return <button onClick={() => send("counter", 1)}>+1</button>;
|
|
@@ -224,4 +244,7 @@ export interface TypedChannelHooks<T extends EventMap> {
|
|
|
224
244
|
* }
|
|
225
245
|
* ```
|
|
226
246
|
*/
|
|
227
|
-
export declare function createChannelHooks<
|
|
247
|
+
export declare function createChannelHooks<H extends SchemaMap, C extends SchemaMap>(schemas: {
|
|
248
|
+
host: H;
|
|
249
|
+
client: C;
|
|
250
|
+
}, options?: ChannelHooksOptions): TypedChannelHooks<InferSchemaMap<C>, InferSchemaMap<H>>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nativewindow/react",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "React bindings for native-window IPC (
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "React bindings for native-window IPC (beta)",
|
|
5
5
|
"homepage": "https://nativewindow.fcannizzaro.com",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/nativewindow/webview/issues"
|