@nativewindow/react 0.1.1 → 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.
Files changed (2) hide show
  1. package/dist/index.d.ts +57 -34
  2. package/package.json +1 -1
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
- * counter: z.number(),
21
- * title: z.string(),
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={schemas}>
48
+ * <ChannelProvider schemas={{ host: hostSchemas, client: clientSchemas }}>
49
49
  * <App />
50
50
  * </ChannelProvider>
51
51
  * ```
52
52
  */
53
- export interface ChannelProviderProps<S extends SchemaMap> {
54
- /** Schemas for each event. Provides both TypeScript types and runtime validation. */
55
- schemas: S;
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
- * counter: z.number(),
78
- * title: z.string(),
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<S extends SchemaMap>(props: ChannelProviderProps<S>): ReactNode;
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 Events = { counter: number; title: string };
111
+ * type ClientEvents = { counter: number };
112
+ * type HostEvents = { title: string };
102
113
  *
103
114
  * function StatusBar() {
104
- * const channel = useChannel<Events>();
115
+ * const channel = useChannel<ClientEvents, HostEvents>();
105
116
  * channel.send("counter", 1);
106
117
  * }
107
118
  * ```
108
119
  */
109
- export declare function useChannel<T extends EventMap = EventMap>(): TypedChannel<T>;
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 Events = { title: string };
135
+ * type HostEvents = { title: string };
122
136
  *
123
137
  * function TitleDisplay() {
124
- * useChannelEvent<Events, "title">("title", (title) => {
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<T extends EventMap = EventMap, K extends keyof T & string = keyof T & string>(type: K, handler: (payload: T[K]) => void): void;
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 Events = { counter: number; title: string };
158
+ * type ClientEvents = { counter: number };
143
159
  *
144
160
  * function Counter() {
145
- * const send = useSend<Events>();
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<T extends EventMap = EventMap>(): <K extends keyof T & string>(...args: SendArgs<T, K>) => void;
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 to `T`,
173
- * so event names and payload types are inferred automatically without
174
- * requiring generic type parameters at the call site.
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<T extends EventMap> {
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<T>;
186
- /** Subscribe to a typed event with automatic cleanup. */
187
- useChannelEvent: <K extends keyof T & string>(type: K, handler: (payload: T[K]) => void) => void;
188
- /** Returns a stable typed `send` function. */
189
- useSend: () => <K extends keyof T & string>(...args: SendArgs<T, K>) => void;
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: { counter: number; title: string }
223
+ * // Types are inferred from directional schemas
204
224
  * const { ChannelProvider, useChannel, useChannelEvent, useSend } =
205
225
  * createChannelHooks({
206
- * counter: z.number(),
207
- * title: z.string(),
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<S extends SchemaMap>(schemas: S, options?: ChannelHooksOptions): TypedChannelHooks<InferSchemaMap<S>>;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@nativewindow/react",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "description": "React bindings for native-window IPC (alpha)",
5
5
  "homepage": "https://nativewindow.fcannizzaro.com",
6
6
  "bugs": {