use-everywhere 0.11.2 → 0.13.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 +5 -5
- package/dist/{chunk-R7PBPLF7.js → chunk-HZ5EI66W.js} +9 -2
- package/dist/devtools/index.js +1 -1
- package/dist/index.cjs +65 -14
- package/dist/index.d.cts +46 -15
- package/dist/index.d.ts +46 -15
- package/dist/index.js +56 -14
- package/llms.txt +6 -6
- package/package.json +16 -16
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ function CartBadge() {
|
|
|
57
57
|
const send = shop.useSend();
|
|
58
58
|
|
|
59
59
|
// Fires when any OTHER tab posts 'cart-updated'.
|
|
60
|
-
shop.
|
|
60
|
+
shop.useOnMessage('cart-updated', (payload) => setItems(payload.items));
|
|
61
61
|
|
|
62
62
|
const addToCart = () => {
|
|
63
63
|
setItems(items + 1); // this tab
|
|
@@ -68,7 +68,7 @@ function CartBadge() {
|
|
|
68
68
|
}
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
The standalone hooks — `useChannel(name)`, `
|
|
71
|
+
The standalone hooks — `useChannel(name)`, `useOnMessage(channel, type,
|
|
72
72
|
handler)`, `useSend(channel)` — are the same machinery without the
|
|
73
73
|
module-level binding, for one-off use.
|
|
74
74
|
|
|
@@ -84,20 +84,20 @@ function DuplicateTabWarning() {
|
|
|
84
84
|
}
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
## Cross-origin windows: `
|
|
87
|
+
## Cross-origin windows: `useWindowResult`
|
|
88
88
|
|
|
89
89
|
Open a window on another domain, exchange typed messages, and await its
|
|
90
90
|
result — the whole lifecycle folded into render state.
|
|
91
91
|
|
|
92
92
|
```tsx
|
|
93
|
-
import { openWindow,
|
|
93
|
+
import { openWindow, useWindowResult } from 'use-everywhere';
|
|
94
94
|
|
|
95
95
|
type ToPayment = { order: { orderId: string; amount: string } };
|
|
96
96
|
type FromPayment = { progress: { step: string } };
|
|
97
97
|
type Receipt = { receiptId: string; last4: string };
|
|
98
98
|
|
|
99
99
|
function PayButton() {
|
|
100
|
-
const pay =
|
|
100
|
+
const pay = useWindowResult<ToPayment, FromPayment, Receipt>(() =>
|
|
101
101
|
openWindow('https://pay.example.com/checkout', {
|
|
102
102
|
peerOrigin: 'https://pay.example.com', // required — '*' throws
|
|
103
103
|
}),
|
|
@@ -30,6 +30,12 @@ function devWarn(code, message) {
|
|
|
30
30
|
warned.add(line);
|
|
31
31
|
console.warn(line);
|
|
32
32
|
}
|
|
33
|
+
function warnRenamed(from, to) {
|
|
34
|
+
devWarn(
|
|
35
|
+
"UE2005",
|
|
36
|
+
`\`${from}\` was renamed to \`${to}\` and is removed in 1.0. Run \`npx use-everywhere-codemod rename-1.0 src/\` to update, or rename it by hand \u2014 nothing else changes.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
33
39
|
var seenInitials = /* @__PURE__ */ new Map();
|
|
34
40
|
function warnOnInitialMismatch(storeName, key, initial) {
|
|
35
41
|
if (!inDev) return;
|
|
@@ -43,7 +49,7 @@ function warnOnInitialMismatch(storeName, key, initial) {
|
|
|
43
49
|
if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
|
|
44
50
|
devWarn(
|
|
45
51
|
"UE2001",
|
|
46
|
-
`useSharedState('${key}') was called with different initial values (${String(first)} and ${String(initial)}). The first registration wins, so the second is ignored. Define the default once \u2014
|
|
52
|
+
`useSharedState('${key}') was called with different initial values (${String(first)} and ${String(initial)}). The first registration wins, so the second is ignored. Define the default once \u2014 createStoreHooks, or a shared constant.`
|
|
47
53
|
);
|
|
48
54
|
}
|
|
49
55
|
}
|
|
@@ -127,7 +133,7 @@ function configureStore(name, scope, options) {
|
|
|
127
133
|
if (process.env.NODE_ENV !== "production") {
|
|
128
134
|
devWarn(
|
|
129
135
|
"UE2002",
|
|
130
|
-
`
|
|
136
|
+
`createStoreHooks('${name}') ran after that store was already created, with different options. The live store keeps the configuration it was built with. Move createStoreHooks to module scope, before any component reads the store.`
|
|
131
137
|
);
|
|
132
138
|
}
|
|
133
139
|
return;
|
|
@@ -244,6 +250,7 @@ function usePresenceMetadata(metadata, options) {
|
|
|
244
250
|
}
|
|
245
251
|
|
|
246
252
|
export {
|
|
253
|
+
warnRenamed,
|
|
247
254
|
warnOnInitialMismatch,
|
|
248
255
|
DEFAULT_NAME,
|
|
249
256
|
getSharedStore,
|
package/dist/devtools/index.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ __export(src_exports, {
|
|
|
37
37
|
createPresence: () => import_core4.createPresence,
|
|
38
38
|
createSharedReducer: () => import_core4.createSharedReducer,
|
|
39
39
|
createSharedStore: () => import_core4.createSharedStore,
|
|
40
|
+
createStoreHooks: () => createStoreHooks,
|
|
40
41
|
defaultTransport: () => import_core4.defaultTransport,
|
|
41
42
|
defineChannel: () => defineChannel,
|
|
42
43
|
defineStore: () => defineStore,
|
|
@@ -66,13 +67,16 @@ __export(src_exports, {
|
|
|
66
67
|
useLeader: () => useLeader,
|
|
67
68
|
useLeaderEffect: () => useLeaderEffect,
|
|
68
69
|
useMessage: () => useMessage,
|
|
70
|
+
useOnMessage: () => useOnMessage,
|
|
69
71
|
useOpenedWindow: () => useOpenedWindow,
|
|
70
72
|
usePeers: () => usePeers,
|
|
71
73
|
usePresenceMetadata: () => usePresenceMetadata,
|
|
72
74
|
useSend: () => useSend,
|
|
73
75
|
useSharedReducer: () => useSharedReducer,
|
|
76
|
+
useSharedSelector: () => useSharedSelector,
|
|
74
77
|
useSharedState: () => useSharedState,
|
|
75
78
|
useSharedStore: () => useSharedStore,
|
|
79
|
+
useWindowResult: () => useWindowResult,
|
|
76
80
|
webStorageAdapter: () => import_core4.webStorageAdapter
|
|
77
81
|
});
|
|
78
82
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -99,6 +103,12 @@ function devWarn(code, message) {
|
|
|
99
103
|
warned.add(line);
|
|
100
104
|
console.warn(line);
|
|
101
105
|
}
|
|
106
|
+
function warnRenamed(from, to) {
|
|
107
|
+
devWarn(
|
|
108
|
+
"UE2005",
|
|
109
|
+
`\`${from}\` was renamed to \`${to}\` and is removed in 1.0. Run \`npx use-everywhere-codemod rename-1.0 src/\` to update, or rename it by hand \u2014 nothing else changes.`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
102
112
|
var seenInitials = /* @__PURE__ */ new Map();
|
|
103
113
|
function warnOnInitialMismatch(storeName, key, initial) {
|
|
104
114
|
if (!inDev) return;
|
|
@@ -112,7 +122,7 @@ function warnOnInitialMismatch(storeName, key, initial) {
|
|
|
112
122
|
if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
|
|
113
123
|
devWarn(
|
|
114
124
|
"UE2001",
|
|
115
|
-
`useSharedState('${key}') was called with different initial values (${String(first)} and ${String(initial)}). The first registration wins, so the second is ignored. Define the default once \u2014
|
|
125
|
+
`useSharedState('${key}') was called with different initial values (${String(first)} and ${String(initial)}). The first registration wins, so the second is ignored. Define the default once \u2014 createStoreHooks, or a shared constant.`
|
|
116
126
|
);
|
|
117
127
|
}
|
|
118
128
|
}
|
|
@@ -199,7 +209,7 @@ function configureStore(name, scope, options) {
|
|
|
199
209
|
if (process.env.NODE_ENV !== "production") {
|
|
200
210
|
devWarn(
|
|
201
211
|
"UE2002",
|
|
202
|
-
`
|
|
212
|
+
`createStoreHooks('${name}') ran after that store was already created, with different options. The live store keeps the configuration it was built with. Move createStoreHooks to module scope, before any component reads the store.`
|
|
203
213
|
);
|
|
204
214
|
}
|
|
205
215
|
return;
|
|
@@ -325,7 +335,7 @@ function useSharedReducer(reducer, initial, options) {
|
|
|
325
335
|
|
|
326
336
|
// src/use-shared-selector.ts
|
|
327
337
|
var import_react3 = require("react");
|
|
328
|
-
function
|
|
338
|
+
function useSharedSelector(selector, options) {
|
|
329
339
|
const store = getStore(options?.store ?? import_core.DEFAULT_NAME, options?.scope ?? "everywhere");
|
|
330
340
|
const equal = options?.equal ?? Object.is;
|
|
331
341
|
const selectorRef = (0, import_react3.useRef)(selector);
|
|
@@ -359,12 +369,12 @@ function shallowEqual(a, b) {
|
|
|
359
369
|
return keys.every((key) => Object.is(left[key], right[key]));
|
|
360
370
|
}
|
|
361
371
|
|
|
362
|
-
// src/use-message.ts
|
|
372
|
+
// src/use-on-message.ts
|
|
363
373
|
var import_react4 = require("react");
|
|
364
374
|
function useChannel(name) {
|
|
365
375
|
return getChannel(name);
|
|
366
376
|
}
|
|
367
|
-
function
|
|
377
|
+
function useOnMessage(channel, type, handler, options) {
|
|
368
378
|
const handlerRef = (0, import_react4.useRef)(handler);
|
|
369
379
|
(0, import_react4.useEffect)(() => {
|
|
370
380
|
handlerRef.current = handler;
|
|
@@ -398,16 +408,21 @@ function useAsk(channel) {
|
|
|
398
408
|
function defineChannel(name, options) {
|
|
399
409
|
if (options) configureChannel(name, options);
|
|
400
410
|
const useBoundSend = () => useSend(useChannel(name));
|
|
401
|
-
const useBoundMessage = (type, handler) =>
|
|
411
|
+
const useBoundMessage = (type, handler) => useOnMessage(useChannel(name), type, handler);
|
|
402
412
|
return {
|
|
403
413
|
get: () => getChannel(name),
|
|
404
414
|
useSend: useBoundSend,
|
|
405
|
-
|
|
415
|
+
useOnMessage: useBoundMessage,
|
|
416
|
+
// Removed in 1.0 along with the standalone renames; see deprecated.ts.
|
|
417
|
+
useMessage: (type, handler) => {
|
|
418
|
+
warnRenamed("ChannelHooks.useMessage", "ChannelHooks.useOnMessage");
|
|
419
|
+
return useBoundMessage(type, handler);
|
|
420
|
+
}
|
|
406
421
|
};
|
|
407
422
|
}
|
|
408
423
|
|
|
409
|
-
// src/
|
|
410
|
-
function
|
|
424
|
+
// src/create-store-hooks.ts
|
|
425
|
+
function createStoreHooks(name, options = {}) {
|
|
411
426
|
const scope = options.scope ?? "everywhere";
|
|
412
427
|
if (options.persist) {
|
|
413
428
|
configureStore(name, scope, {
|
|
@@ -422,7 +437,12 @@ function defineStore(name, options = {}) {
|
|
|
422
437
|
});
|
|
423
438
|
}
|
|
424
439
|
return {
|
|
425
|
-
|
|
440
|
+
store: () => getStore(name, scope),
|
|
441
|
+
// Removed in 1.0 along with the standalone renames; see deprecated.ts.
|
|
442
|
+
get: () => {
|
|
443
|
+
warnRenamed("StoreHooks.get()", "StoreHooks.store()");
|
|
444
|
+
return getStore(name, scope);
|
|
445
|
+
},
|
|
426
446
|
useSharedState: (key, initial) => useSharedState(key, initial, { store: name, scope })
|
|
427
447
|
};
|
|
428
448
|
}
|
|
@@ -512,11 +532,20 @@ function createNamespace(namespace) {
|
|
|
512
532
|
const { busName } = core;
|
|
513
533
|
return {
|
|
514
534
|
...core,
|
|
515
|
-
|
|
535
|
+
createStoreHooks: (name, options) => createStoreHooks(busName(name), options),
|
|
516
536
|
defineChannel: (name, options) => defineChannel(busName(name), options),
|
|
517
537
|
getSharedStore: (name, scope) => getSharedStore(busName(name), scope),
|
|
518
538
|
useSharedState: (key, initial, options) => useSharedState(key, initial, { ...options, store: busName(options?.store) }),
|
|
519
|
-
|
|
539
|
+
useSharedSelector: (selector, options) => useSharedSelector(selector, { ...options, store: busName(options?.store) }),
|
|
540
|
+
// Removed in 1.0 along with the standalone renames; see deprecated.ts.
|
|
541
|
+
defineStore: (name, options) => {
|
|
542
|
+
warnRenamed("Namespace.defineStore", "Namespace.createStoreHooks");
|
|
543
|
+
return createStoreHooks(busName(name), options);
|
|
544
|
+
},
|
|
545
|
+
useSharedStore: (selector, options) => {
|
|
546
|
+
warnRenamed("Namespace.useSharedStore", "Namespace.useSharedSelector");
|
|
547
|
+
return useSharedSelector(selector, { ...options, store: busName(options?.store) });
|
|
548
|
+
},
|
|
520
549
|
usePeers: (options) => usePeers({ ...options, name: busName(options?.name) }),
|
|
521
550
|
usePresenceMetadata: (metadata, options) => usePresenceMetadata(metadata, { ...options, name: busName(options?.name) }),
|
|
522
551
|
useHydrated: (options) => useHydrated({ ...options, store: busName(options?.store) }),
|
|
@@ -527,7 +556,7 @@ function createNamespace(namespace) {
|
|
|
527
556
|
};
|
|
528
557
|
}
|
|
529
558
|
|
|
530
|
-
// src/use-
|
|
559
|
+
// src/use-window-result.ts
|
|
531
560
|
var import_react8 = require("react");
|
|
532
561
|
var import_core3 = require("@use-everywhere/core");
|
|
533
562
|
var IDLE = Object.freeze({
|
|
@@ -535,7 +564,7 @@ var IDLE = Object.freeze({
|
|
|
535
564
|
result: void 0,
|
|
536
565
|
error: void 0
|
|
537
566
|
});
|
|
538
|
-
function
|
|
567
|
+
function useWindowResult(factory) {
|
|
539
568
|
const [state, setState] = (0, import_react8.useState)(IDLE);
|
|
540
569
|
const current = (0, import_react8.useRef)(null);
|
|
541
570
|
const factoryRef = (0, import_react8.useRef)(factory);
|
|
@@ -584,6 +613,24 @@ function useOpenedWindow(factory) {
|
|
|
584
613
|
return { ...state, open, post, close };
|
|
585
614
|
}
|
|
586
615
|
|
|
616
|
+
// src/deprecated.ts
|
|
617
|
+
function useMessage(channel, type, handler, options) {
|
|
618
|
+
warnRenamed("useMessage", "useOnMessage");
|
|
619
|
+
useOnMessage(channel, type, handler, options);
|
|
620
|
+
}
|
|
621
|
+
function useOpenedWindow(factory) {
|
|
622
|
+
warnRenamed("useOpenedWindow", "useWindowResult");
|
|
623
|
+
return useWindowResult(factory);
|
|
624
|
+
}
|
|
625
|
+
function useSharedStore(selector, options) {
|
|
626
|
+
warnRenamed("useSharedStore", "useSharedSelector");
|
|
627
|
+
return useSharedSelector(selector, options);
|
|
628
|
+
}
|
|
629
|
+
function defineStore(name, options = {}) {
|
|
630
|
+
warnRenamed("defineStore", "createStoreHooks");
|
|
631
|
+
return createStoreHooks(name, options);
|
|
632
|
+
}
|
|
633
|
+
|
|
587
634
|
// src/index.ts
|
|
588
635
|
var import_core4 = require("@use-everywhere/core");
|
|
589
636
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -604,6 +651,7 @@ var import_core4 = require("@use-everywhere/core");
|
|
|
604
651
|
createPresence,
|
|
605
652
|
createSharedReducer,
|
|
606
653
|
createSharedStore,
|
|
654
|
+
createStoreHooks,
|
|
607
655
|
defaultTransport,
|
|
608
656
|
defineChannel,
|
|
609
657
|
defineStore,
|
|
@@ -633,12 +681,15 @@ var import_core4 = require("@use-everywhere/core");
|
|
|
633
681
|
useLeader,
|
|
634
682
|
useLeaderEffect,
|
|
635
683
|
useMessage,
|
|
684
|
+
useOnMessage,
|
|
636
685
|
useOpenedWindow,
|
|
637
686
|
usePeers,
|
|
638
687
|
usePresenceMetadata,
|
|
639
688
|
useSend,
|
|
640
689
|
useSharedReducer,
|
|
690
|
+
useSharedSelector,
|
|
641
691
|
useSharedState,
|
|
642
692
|
useSharedStore,
|
|
693
|
+
useWindowResult,
|
|
643
694
|
webStorageAdapter
|
|
644
695
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SharedStore, LeaderOptions, Leader, MessageMap, ReplyMap, Channel, MessageMeta, ChannelOptions, PersistAdapter, RestoreError, Peer, LeaderSnapshot, Namespace, OpenedWindow, WindowClosedError } from '@use-everywhere/core';
|
|
2
|
-
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, MessageEventLike, MessageMap, MessageMeta, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, SharedWorkerTransport, SharedWorkerTransportOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isSharedWorkerAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
2
|
+
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, LockManagerLike, MessageEventLike, MessageMap, MessageMeta, MessagePortLike, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, SharedWorkerLike, SharedWorkerTransport, SharedWorkerTransportOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isSharedWorkerAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* How far a shared value travels:
|
|
@@ -91,7 +91,7 @@ interface UseSharedSelectorOptions extends UseSharedStateOptions {
|
|
|
91
91
|
* anything in it.
|
|
92
92
|
*
|
|
93
93
|
* ```tsx
|
|
94
|
-
* const total =
|
|
94
|
+
* const total = useSharedSelector<Cart, number>(
|
|
95
95
|
* (cart) => cart.items.length + cart.saved.length,
|
|
96
96
|
* );
|
|
97
97
|
* ```
|
|
@@ -111,7 +111,7 @@ interface UseSharedSelectorOptions extends UseSharedStateOptions {
|
|
|
111
111
|
* selector runs against `{}`, and its result is what the server-rendered markup
|
|
112
112
|
* shows.
|
|
113
113
|
*/
|
|
114
|
-
declare function
|
|
114
|
+
declare function useSharedSelector<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
115
115
|
/** Shallow equality over an object or array, for selectors that build one. */
|
|
116
116
|
declare function shallowEqual(a: unknown, b: unknown): boolean;
|
|
117
117
|
|
|
@@ -130,7 +130,7 @@ declare function getLeader(name: string, options?: LeaderOptions): Leader;
|
|
|
130
130
|
|
|
131
131
|
/** Get the page-wide typed channel for `name` (one instance per name). */
|
|
132
132
|
declare function useChannel<M extends MessageMap, R extends ReplyMap<M> = Record<never, never>>(name: string): Channel<M, R>;
|
|
133
|
-
interface
|
|
133
|
+
interface UseOnMessageOptions {
|
|
134
134
|
/**
|
|
135
135
|
* Subscribe at all. Default true.
|
|
136
136
|
*
|
|
@@ -146,7 +146,7 @@ interface UseMessageOptions {
|
|
|
146
146
|
* Subscribe to one message type. The handler is kept fresh without
|
|
147
147
|
* resubscribing, so it may close over render state.
|
|
148
148
|
*/
|
|
149
|
-
declare function
|
|
149
|
+
declare function useOnMessage<M extends MessageMap, R extends ReplyMap<M>, K extends keyof M & string>(channel: Channel<M, R>, type: K, handler: (payload: M[K], meta: MessageMeta) => void, options?: UseOnMessageOptions): void;
|
|
150
150
|
/**
|
|
151
151
|
* Answer `ask`s of one type for as long as this component is mounted.
|
|
152
152
|
*
|
|
@@ -173,14 +173,16 @@ interface ChannelHooks<M extends MessageMap> {
|
|
|
173
173
|
useSend: () => Channel<M>['post'];
|
|
174
174
|
/**
|
|
175
175
|
* Subscribe to one message type. Same contract as the standalone
|
|
176
|
-
* `
|
|
176
|
+
* `useOnMessage`: the handler is kept fresh without resubscribing.
|
|
177
177
|
*/
|
|
178
|
+
useOnMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
|
|
179
|
+
/** @deprecated Renamed to `useOnMessage`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
178
180
|
useMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
/**
|
|
182
184
|
* Bind a channel name and message map once, at module level, and get fully
|
|
183
|
-
* typed hooks back. Sugar over useChannel/
|
|
185
|
+
* typed hooks back. Sugar over useChannel/useOnMessage/useSend — the same
|
|
184
186
|
* page-wide channel singleton is shared, so mixing bound and standalone
|
|
185
187
|
* hooks for one name is safe.
|
|
186
188
|
*
|
|
@@ -189,7 +191,7 @@ interface ChannelHooks<M extends MessageMap> {
|
|
|
189
191
|
*/
|
|
190
192
|
declare function defineChannel<M extends MessageMap>(name: string, options?: ChannelOptions<M>): ChannelHooks<M>;
|
|
191
193
|
|
|
192
|
-
interface
|
|
194
|
+
interface CreateStoreHooksOptions {
|
|
193
195
|
/** Restore this store from disk on first use, and write it back as it changes. */
|
|
194
196
|
persist?: PersistAdapter;
|
|
195
197
|
/** Persist only these keys. Default: every key that has been written. */
|
|
@@ -212,6 +214,8 @@ interface DefineStoreOptions {
|
|
|
212
214
|
/** A store bound to a name and a shape: typed hooks with no per-call generics. */
|
|
213
215
|
interface StoreHooks<S extends Record<string, unknown>> {
|
|
214
216
|
/** The underlying store instance (the same one the hooks use) — for non-React code. */
|
|
217
|
+
store: () => AnyStore;
|
|
218
|
+
/** @deprecated Renamed to `store`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
215
219
|
get: () => AnyStore;
|
|
216
220
|
useSharedState: <K extends keyof S & string>(key: K, initial: S[K]) => [S[K], (next: S[K] | ((prev: S[K]) => S[K])) => void];
|
|
217
221
|
}
|
|
@@ -222,7 +226,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
|
|
|
222
226
|
* Like defineChannel, this does not construct anything: it registers the
|
|
223
227
|
* options the registry will use when the store is first needed, so importing
|
|
224
228
|
* the module has no side effect. The store stays a singleton per name, so
|
|
225
|
-
* `
|
|
229
|
+
* `createStoreHooks('settings', { persist })` and a bare
|
|
226
230
|
* `useSharedState('theme', 'dark', { store: 'settings' })` elsewhere resolve to
|
|
227
231
|
* the same store, and both get persistence.
|
|
228
232
|
*
|
|
@@ -230,7 +234,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
|
|
|
230
234
|
* so intended usage is automatic; if it does run late it throws rather than
|
|
231
235
|
* quietly handing back a store with no persistence.
|
|
232
236
|
*/
|
|
233
|
-
declare function
|
|
237
|
+
declare function createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
|
|
234
238
|
|
|
235
239
|
interface UsePeersOptions {
|
|
236
240
|
/** Bus name. Default 'use-everywhere'. */
|
|
@@ -337,10 +341,14 @@ declare function useLeaderEffect(effect: () => void | (() => void), options?: Us
|
|
|
337
341
|
* which namespace it lives in.
|
|
338
342
|
*/
|
|
339
343
|
interface ReactNamespace extends Namespace {
|
|
340
|
-
|
|
344
|
+
createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
|
|
341
345
|
defineChannel<M extends MessageMap>(name?: string, options?: ChannelOptions<M>): ChannelHooks<M>;
|
|
342
346
|
getSharedStore(name?: string, scope?: UseSharedStateOptions['scope']): AnyStore;
|
|
343
347
|
useSharedState<T>(key: string, initial: T, options?: UseSharedStateOptions): [T, (next: T | ((prev: T) => T)) => void];
|
|
348
|
+
useSharedSelector<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
349
|
+
/** @deprecated Renamed to `createStoreHooks`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
350
|
+
defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
|
|
351
|
+
/** @deprecated Renamed to `useSharedSelector`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
344
352
|
useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
345
353
|
usePeers(options?: UsePeersOptions): readonly Peer[];
|
|
346
354
|
usePresenceMetadata(metadata: unknown, options?: UsePeersOptions): void;
|
|
@@ -364,7 +372,7 @@ interface ReactNamespace extends Namespace {
|
|
|
364
372
|
* const [items, setItems] = checkout.useSharedState('items', []);
|
|
365
373
|
* ```
|
|
366
374
|
*
|
|
367
|
-
* Call it **at module scope**, like `
|
|
375
|
+
* Call it **at module scope**, like `createStoreHooks` and `defineChannel`. It
|
|
368
376
|
* builds a small object of bound functions, and rebuilding that on every render
|
|
369
377
|
* would hand React a new `useSharedState` identity each time — harmless for the
|
|
370
378
|
* hooks themselves, which key off the bus name, but pointless work and a
|
|
@@ -418,7 +426,7 @@ interface OpenedWindowControls<Out extends MessageMap, In extends MessageMap, R>
|
|
|
418
426
|
post: OpenedWindow<Out, In, R>['post'];
|
|
419
427
|
close: () => void;
|
|
420
428
|
}
|
|
421
|
-
type
|
|
429
|
+
type UseWindowResult<Out extends MessageMap, In extends MessageMap, R> = OpenedWindowState<R> & OpenedWindowControls<Out, In, R>;
|
|
422
430
|
|
|
423
431
|
/**
|
|
424
432
|
* Drive an openWindow() flow from a component: the factory is called on
|
|
@@ -429,6 +437,29 @@ type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = OpenedW
|
|
|
429
437
|
* because a route changed would lose the user's in-flight transaction. Call
|
|
430
438
|
* close() if the component owns the window's lifetime.
|
|
431
439
|
*/
|
|
432
|
-
declare function
|
|
440
|
+
declare function useWindowResult<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseWindowResult<Out, In, R>;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @deprecated Renamed to `useOnMessage`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
444
|
+
*/
|
|
445
|
+
declare function useMessage<M extends MessageMap, R extends ReplyMap<M>, K extends keyof M & string>(channel: Channel<M, R>, type: K, handler: (payload: M[K], meta: MessageMeta) => void, options?: UseMessageOptions): void;
|
|
446
|
+
/**
|
|
447
|
+
* @deprecated Renamed to `useWindowResult`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
448
|
+
*/
|
|
449
|
+
declare function useOpenedWindow<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseWindowResult<Out, In, R>;
|
|
450
|
+
/**
|
|
451
|
+
* @deprecated Renamed to `useSharedSelector`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
452
|
+
*/
|
|
453
|
+
declare function useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
454
|
+
/**
|
|
455
|
+
* @deprecated Renamed to `createStoreHooks`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
456
|
+
*/
|
|
457
|
+
declare function defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: DefineStoreOptions): StoreHooks<S>;
|
|
458
|
+
/** @deprecated Renamed to `UseOnMessageOptions`. Removed in 1.0. */
|
|
459
|
+
type UseMessageOptions = UseOnMessageOptions;
|
|
460
|
+
/** @deprecated Renamed to `CreateStoreHooksOptions`. Removed in 1.0. */
|
|
461
|
+
type DefineStoreOptions = CreateStoreHooksOptions;
|
|
462
|
+
/** @deprecated Renamed to `UseWindowResult`. Removed in 1.0. */
|
|
463
|
+
type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = UseWindowResult<Out, In, R>;
|
|
433
464
|
|
|
434
|
-
export { type AnyStore, type ChannelHooks, type DefineStoreOptions, type OpenedWindowControls, type OpenedWindowState, type OpenedWindowStatus, type ReactNamespace, type ShareScope, type StoreHooks, type UseLeaderOptions, type UseMessageOptions, type UseOpenedWindow, type UsePeersOptions, type UseSharedReducerOptions, type UseSharedSelectorOptions, type UseSharedStateOptions, createNamespace, defineChannel, defineStore, getLeader, getSharedStore, shallowEqual, useAnswer, useAsk, useChannel, useClientId, useHydrated, useIsLeader, useLeader, useLeaderEffect, useMessage, useOpenedWindow, usePeers, usePresenceMetadata, useSend, useSharedReducer, useSharedState, useSharedStore };
|
|
465
|
+
export { type AnyStore, type ChannelHooks, type CreateStoreHooksOptions, type DefineStoreOptions, type OpenedWindowControls, type OpenedWindowState, type OpenedWindowStatus, type ReactNamespace, type ShareScope, type StoreHooks, type UseLeaderOptions, type UseMessageOptions, type UseOnMessageOptions, type UseOpenedWindow, type UsePeersOptions, type UseSharedReducerOptions, type UseSharedSelectorOptions, type UseSharedStateOptions, type UseWindowResult, createNamespace, createStoreHooks, defineChannel, defineStore, getLeader, getSharedStore, shallowEqual, useAnswer, useAsk, useChannel, useClientId, useHydrated, useIsLeader, useLeader, useLeaderEffect, useMessage, useOnMessage, useOpenedWindow, usePeers, usePresenceMetadata, useSend, useSharedReducer, useSharedSelector, useSharedState, useSharedStore, useWindowResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SharedStore, LeaderOptions, Leader, MessageMap, ReplyMap, Channel, MessageMeta, ChannelOptions, PersistAdapter, RestoreError, Peer, LeaderSnapshot, Namespace, OpenedWindow, WindowClosedError } from '@use-everywhere/core';
|
|
2
|
-
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, MessageEventLike, MessageMap, MessageMeta, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, SharedWorkerTransport, SharedWorkerTransportOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isSharedWorkerAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
2
|
+
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, LockManagerLike, MessageEventLike, MessageMap, MessageMeta, MessagePortLike, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, SharedWorkerLike, SharedWorkerTransport, SharedWorkerTransportOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isSharedWorkerAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* How far a shared value travels:
|
|
@@ -91,7 +91,7 @@ interface UseSharedSelectorOptions extends UseSharedStateOptions {
|
|
|
91
91
|
* anything in it.
|
|
92
92
|
*
|
|
93
93
|
* ```tsx
|
|
94
|
-
* const total =
|
|
94
|
+
* const total = useSharedSelector<Cart, number>(
|
|
95
95
|
* (cart) => cart.items.length + cart.saved.length,
|
|
96
96
|
* );
|
|
97
97
|
* ```
|
|
@@ -111,7 +111,7 @@ interface UseSharedSelectorOptions extends UseSharedStateOptions {
|
|
|
111
111
|
* selector runs against `{}`, and its result is what the server-rendered markup
|
|
112
112
|
* shows.
|
|
113
113
|
*/
|
|
114
|
-
declare function
|
|
114
|
+
declare function useSharedSelector<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
115
115
|
/** Shallow equality over an object or array, for selectors that build one. */
|
|
116
116
|
declare function shallowEqual(a: unknown, b: unknown): boolean;
|
|
117
117
|
|
|
@@ -130,7 +130,7 @@ declare function getLeader(name: string, options?: LeaderOptions): Leader;
|
|
|
130
130
|
|
|
131
131
|
/** Get the page-wide typed channel for `name` (one instance per name). */
|
|
132
132
|
declare function useChannel<M extends MessageMap, R extends ReplyMap<M> = Record<never, never>>(name: string): Channel<M, R>;
|
|
133
|
-
interface
|
|
133
|
+
interface UseOnMessageOptions {
|
|
134
134
|
/**
|
|
135
135
|
* Subscribe at all. Default true.
|
|
136
136
|
*
|
|
@@ -146,7 +146,7 @@ interface UseMessageOptions {
|
|
|
146
146
|
* Subscribe to one message type. The handler is kept fresh without
|
|
147
147
|
* resubscribing, so it may close over render state.
|
|
148
148
|
*/
|
|
149
|
-
declare function
|
|
149
|
+
declare function useOnMessage<M extends MessageMap, R extends ReplyMap<M>, K extends keyof M & string>(channel: Channel<M, R>, type: K, handler: (payload: M[K], meta: MessageMeta) => void, options?: UseOnMessageOptions): void;
|
|
150
150
|
/**
|
|
151
151
|
* Answer `ask`s of one type for as long as this component is mounted.
|
|
152
152
|
*
|
|
@@ -173,14 +173,16 @@ interface ChannelHooks<M extends MessageMap> {
|
|
|
173
173
|
useSend: () => Channel<M>['post'];
|
|
174
174
|
/**
|
|
175
175
|
* Subscribe to one message type. Same contract as the standalone
|
|
176
|
-
* `
|
|
176
|
+
* `useOnMessage`: the handler is kept fresh without resubscribing.
|
|
177
177
|
*/
|
|
178
|
+
useOnMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
|
|
179
|
+
/** @deprecated Renamed to `useOnMessage`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
178
180
|
useMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
/**
|
|
182
184
|
* Bind a channel name and message map once, at module level, and get fully
|
|
183
|
-
* typed hooks back. Sugar over useChannel/
|
|
185
|
+
* typed hooks back. Sugar over useChannel/useOnMessage/useSend — the same
|
|
184
186
|
* page-wide channel singleton is shared, so mixing bound and standalone
|
|
185
187
|
* hooks for one name is safe.
|
|
186
188
|
*
|
|
@@ -189,7 +191,7 @@ interface ChannelHooks<M extends MessageMap> {
|
|
|
189
191
|
*/
|
|
190
192
|
declare function defineChannel<M extends MessageMap>(name: string, options?: ChannelOptions<M>): ChannelHooks<M>;
|
|
191
193
|
|
|
192
|
-
interface
|
|
194
|
+
interface CreateStoreHooksOptions {
|
|
193
195
|
/** Restore this store from disk on first use, and write it back as it changes. */
|
|
194
196
|
persist?: PersistAdapter;
|
|
195
197
|
/** Persist only these keys. Default: every key that has been written. */
|
|
@@ -212,6 +214,8 @@ interface DefineStoreOptions {
|
|
|
212
214
|
/** A store bound to a name and a shape: typed hooks with no per-call generics. */
|
|
213
215
|
interface StoreHooks<S extends Record<string, unknown>> {
|
|
214
216
|
/** The underlying store instance (the same one the hooks use) — for non-React code. */
|
|
217
|
+
store: () => AnyStore;
|
|
218
|
+
/** @deprecated Renamed to `store`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
215
219
|
get: () => AnyStore;
|
|
216
220
|
useSharedState: <K extends keyof S & string>(key: K, initial: S[K]) => [S[K], (next: S[K] | ((prev: S[K]) => S[K])) => void];
|
|
217
221
|
}
|
|
@@ -222,7 +226,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
|
|
|
222
226
|
* Like defineChannel, this does not construct anything: it registers the
|
|
223
227
|
* options the registry will use when the store is first needed, so importing
|
|
224
228
|
* the module has no side effect. The store stays a singleton per name, so
|
|
225
|
-
* `
|
|
229
|
+
* `createStoreHooks('settings', { persist })` and a bare
|
|
226
230
|
* `useSharedState('theme', 'dark', { store: 'settings' })` elsewhere resolve to
|
|
227
231
|
* the same store, and both get persistence.
|
|
228
232
|
*
|
|
@@ -230,7 +234,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
|
|
|
230
234
|
* so intended usage is automatic; if it does run late it throws rather than
|
|
231
235
|
* quietly handing back a store with no persistence.
|
|
232
236
|
*/
|
|
233
|
-
declare function
|
|
237
|
+
declare function createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
|
|
234
238
|
|
|
235
239
|
interface UsePeersOptions {
|
|
236
240
|
/** Bus name. Default 'use-everywhere'. */
|
|
@@ -337,10 +341,14 @@ declare function useLeaderEffect(effect: () => void | (() => void), options?: Us
|
|
|
337
341
|
* which namespace it lives in.
|
|
338
342
|
*/
|
|
339
343
|
interface ReactNamespace extends Namespace {
|
|
340
|
-
|
|
344
|
+
createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
|
|
341
345
|
defineChannel<M extends MessageMap>(name?: string, options?: ChannelOptions<M>): ChannelHooks<M>;
|
|
342
346
|
getSharedStore(name?: string, scope?: UseSharedStateOptions['scope']): AnyStore;
|
|
343
347
|
useSharedState<T>(key: string, initial: T, options?: UseSharedStateOptions): [T, (next: T | ((prev: T) => T)) => void];
|
|
348
|
+
useSharedSelector<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
349
|
+
/** @deprecated Renamed to `createStoreHooks`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
350
|
+
defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
|
|
351
|
+
/** @deprecated Renamed to `useSharedSelector`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`. */
|
|
344
352
|
useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
345
353
|
usePeers(options?: UsePeersOptions): readonly Peer[];
|
|
346
354
|
usePresenceMetadata(metadata: unknown, options?: UsePeersOptions): void;
|
|
@@ -364,7 +372,7 @@ interface ReactNamespace extends Namespace {
|
|
|
364
372
|
* const [items, setItems] = checkout.useSharedState('items', []);
|
|
365
373
|
* ```
|
|
366
374
|
*
|
|
367
|
-
* Call it **at module scope**, like `
|
|
375
|
+
* Call it **at module scope**, like `createStoreHooks` and `defineChannel`. It
|
|
368
376
|
* builds a small object of bound functions, and rebuilding that on every render
|
|
369
377
|
* would hand React a new `useSharedState` identity each time — harmless for the
|
|
370
378
|
* hooks themselves, which key off the bus name, but pointless work and a
|
|
@@ -418,7 +426,7 @@ interface OpenedWindowControls<Out extends MessageMap, In extends MessageMap, R>
|
|
|
418
426
|
post: OpenedWindow<Out, In, R>['post'];
|
|
419
427
|
close: () => void;
|
|
420
428
|
}
|
|
421
|
-
type
|
|
429
|
+
type UseWindowResult<Out extends MessageMap, In extends MessageMap, R> = OpenedWindowState<R> & OpenedWindowControls<Out, In, R>;
|
|
422
430
|
|
|
423
431
|
/**
|
|
424
432
|
* Drive an openWindow() flow from a component: the factory is called on
|
|
@@ -429,6 +437,29 @@ type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = OpenedW
|
|
|
429
437
|
* because a route changed would lose the user's in-flight transaction. Call
|
|
430
438
|
* close() if the component owns the window's lifetime.
|
|
431
439
|
*/
|
|
432
|
-
declare function
|
|
440
|
+
declare function useWindowResult<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseWindowResult<Out, In, R>;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @deprecated Renamed to `useOnMessage`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
444
|
+
*/
|
|
445
|
+
declare function useMessage<M extends MessageMap, R extends ReplyMap<M>, K extends keyof M & string>(channel: Channel<M, R>, type: K, handler: (payload: M[K], meta: MessageMeta) => void, options?: UseMessageOptions): void;
|
|
446
|
+
/**
|
|
447
|
+
* @deprecated Renamed to `useWindowResult`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
448
|
+
*/
|
|
449
|
+
declare function useOpenedWindow<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseWindowResult<Out, In, R>;
|
|
450
|
+
/**
|
|
451
|
+
* @deprecated Renamed to `useSharedSelector`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
452
|
+
*/
|
|
453
|
+
declare function useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
|
|
454
|
+
/**
|
|
455
|
+
* @deprecated Renamed to `createStoreHooks`. Removed in 1.0 — `npx use-everywhere-codemod rename-1.0 src/`.
|
|
456
|
+
*/
|
|
457
|
+
declare function defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: DefineStoreOptions): StoreHooks<S>;
|
|
458
|
+
/** @deprecated Renamed to `UseOnMessageOptions`. Removed in 1.0. */
|
|
459
|
+
type UseMessageOptions = UseOnMessageOptions;
|
|
460
|
+
/** @deprecated Renamed to `CreateStoreHooksOptions`. Removed in 1.0. */
|
|
461
|
+
type DefineStoreOptions = CreateStoreHooksOptions;
|
|
462
|
+
/** @deprecated Renamed to `UseWindowResult`. Removed in 1.0. */
|
|
463
|
+
type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = UseWindowResult<Out, In, R>;
|
|
433
464
|
|
|
434
|
-
export { type AnyStore, type ChannelHooks, type DefineStoreOptions, type OpenedWindowControls, type OpenedWindowState, type OpenedWindowStatus, type ReactNamespace, type ShareScope, type StoreHooks, type UseLeaderOptions, type UseMessageOptions, type UseOpenedWindow, type UsePeersOptions, type UseSharedReducerOptions, type UseSharedSelectorOptions, type UseSharedStateOptions, createNamespace, defineChannel, defineStore, getLeader, getSharedStore, shallowEqual, useAnswer, useAsk, useChannel, useClientId, useHydrated, useIsLeader, useLeader, useLeaderEffect, useMessage, useOpenedWindow, usePeers, usePresenceMetadata, useSend, useSharedReducer, useSharedState, useSharedStore };
|
|
465
|
+
export { type AnyStore, type ChannelHooks, type CreateStoreHooksOptions, type DefineStoreOptions, type OpenedWindowControls, type OpenedWindowState, type OpenedWindowStatus, type ReactNamespace, type ShareScope, type StoreHooks, type UseLeaderOptions, type UseMessageOptions, type UseOnMessageOptions, type UseOpenedWindow, type UsePeersOptions, type UseSharedReducerOptions, type UseSharedSelectorOptions, type UseSharedStateOptions, type UseWindowResult, createNamespace, createStoreHooks, defineChannel, defineStore, getLeader, getSharedStore, shallowEqual, useAnswer, useAsk, useChannel, useClientId, useHydrated, useIsLeader, useLeader, useLeaderEffect, useMessage, useOnMessage, useOpenedWindow, usePeers, usePresenceMetadata, useSend, useSharedReducer, useSharedSelector, useSharedState, useSharedStore, useWindowResult };
|
package/dist/index.js
CHANGED
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
useClientId,
|
|
12
12
|
usePeers,
|
|
13
13
|
usePresenceMetadata,
|
|
14
|
-
warnOnInitialMismatch
|
|
15
|
-
|
|
14
|
+
warnOnInitialMismatch,
|
|
15
|
+
warnRenamed
|
|
16
|
+
} from "./chunk-HZ5EI66W.js";
|
|
16
17
|
|
|
17
18
|
// src/use-shared-state.ts
|
|
18
19
|
import { useCallback, useSyncExternalStore } from "react";
|
|
@@ -55,7 +56,7 @@ function useSharedReducer(reducer, initial, options) {
|
|
|
55
56
|
|
|
56
57
|
// src/use-shared-selector.ts
|
|
57
58
|
import { useCallback as useCallback3, useRef, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
58
|
-
function
|
|
59
|
+
function useSharedSelector(selector, options) {
|
|
59
60
|
const store = getStore(options?.store ?? DEFAULT_NAME, options?.scope ?? "everywhere");
|
|
60
61
|
const equal = options?.equal ?? Object.is;
|
|
61
62
|
const selectorRef = useRef(selector);
|
|
@@ -89,12 +90,12 @@ function shallowEqual(a, b) {
|
|
|
89
90
|
return keys.every((key) => Object.is(left[key], right[key]));
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
// src/use-message.ts
|
|
93
|
+
// src/use-on-message.ts
|
|
93
94
|
import { useEffect, useRef as useRef2 } from "react";
|
|
94
95
|
function useChannel(name) {
|
|
95
96
|
return getChannel(name);
|
|
96
97
|
}
|
|
97
|
-
function
|
|
98
|
+
function useOnMessage(channel, type, handler, options) {
|
|
98
99
|
const handlerRef = useRef2(handler);
|
|
99
100
|
useEffect(() => {
|
|
100
101
|
handlerRef.current = handler;
|
|
@@ -128,16 +129,21 @@ function useAsk(channel) {
|
|
|
128
129
|
function defineChannel(name, options) {
|
|
129
130
|
if (options) configureChannel(name, options);
|
|
130
131
|
const useBoundSend = () => useSend(useChannel(name));
|
|
131
|
-
const useBoundMessage = (type, handler) =>
|
|
132
|
+
const useBoundMessage = (type, handler) => useOnMessage(useChannel(name), type, handler);
|
|
132
133
|
return {
|
|
133
134
|
get: () => getChannel(name),
|
|
134
135
|
useSend: useBoundSend,
|
|
135
|
-
|
|
136
|
+
useOnMessage: useBoundMessage,
|
|
137
|
+
// Removed in 1.0 along with the standalone renames; see deprecated.ts.
|
|
138
|
+
useMessage: (type, handler) => {
|
|
139
|
+
warnRenamed("ChannelHooks.useMessage", "ChannelHooks.useOnMessage");
|
|
140
|
+
return useBoundMessage(type, handler);
|
|
141
|
+
}
|
|
136
142
|
};
|
|
137
143
|
}
|
|
138
144
|
|
|
139
|
-
// src/
|
|
140
|
-
function
|
|
145
|
+
// src/create-store-hooks.ts
|
|
146
|
+
function createStoreHooks(name, options = {}) {
|
|
141
147
|
const scope = options.scope ?? "everywhere";
|
|
142
148
|
if (options.persist) {
|
|
143
149
|
configureStore(name, scope, {
|
|
@@ -152,7 +158,12 @@ function defineStore(name, options = {}) {
|
|
|
152
158
|
});
|
|
153
159
|
}
|
|
154
160
|
return {
|
|
155
|
-
|
|
161
|
+
store: () => getStore(name, scope),
|
|
162
|
+
// Removed in 1.0 along with the standalone renames; see deprecated.ts.
|
|
163
|
+
get: () => {
|
|
164
|
+
warnRenamed("StoreHooks.get()", "StoreHooks.store()");
|
|
165
|
+
return getStore(name, scope);
|
|
166
|
+
},
|
|
156
167
|
useSharedState: (key, initial) => useSharedState(key, initial, { store: name, scope })
|
|
157
168
|
};
|
|
158
169
|
}
|
|
@@ -214,11 +225,20 @@ function createNamespace(namespace) {
|
|
|
214
225
|
const { busName } = core;
|
|
215
226
|
return {
|
|
216
227
|
...core,
|
|
217
|
-
|
|
228
|
+
createStoreHooks: (name, options) => createStoreHooks(busName(name), options),
|
|
218
229
|
defineChannel: (name, options) => defineChannel(busName(name), options),
|
|
219
230
|
getSharedStore: (name, scope) => getSharedStore(busName(name), scope),
|
|
220
231
|
useSharedState: (key, initial, options) => useSharedState(key, initial, { ...options, store: busName(options?.store) }),
|
|
221
|
-
|
|
232
|
+
useSharedSelector: (selector, options) => useSharedSelector(selector, { ...options, store: busName(options?.store) }),
|
|
233
|
+
// Removed in 1.0 along with the standalone renames; see deprecated.ts.
|
|
234
|
+
defineStore: (name, options) => {
|
|
235
|
+
warnRenamed("Namespace.defineStore", "Namespace.createStoreHooks");
|
|
236
|
+
return createStoreHooks(busName(name), options);
|
|
237
|
+
},
|
|
238
|
+
useSharedStore: (selector, options) => {
|
|
239
|
+
warnRenamed("Namespace.useSharedStore", "Namespace.useSharedSelector");
|
|
240
|
+
return useSharedSelector(selector, { ...options, store: busName(options?.store) });
|
|
241
|
+
},
|
|
222
242
|
usePeers: (options) => usePeers({ ...options, name: busName(options?.name) }),
|
|
223
243
|
usePresenceMetadata: (metadata, options) => usePresenceMetadata(metadata, { ...options, name: busName(options?.name) }),
|
|
224
244
|
useHydrated: (options) => useHydrated({ ...options, store: busName(options?.store) }),
|
|
@@ -229,7 +249,7 @@ function createNamespace(namespace) {
|
|
|
229
249
|
};
|
|
230
250
|
}
|
|
231
251
|
|
|
232
|
-
// src/use-
|
|
252
|
+
// src/use-window-result.ts
|
|
233
253
|
import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef4, useState as useState2 } from "react";
|
|
234
254
|
import { WindowClosedError } from "@use-everywhere/core";
|
|
235
255
|
var IDLE = Object.freeze({
|
|
@@ -237,7 +257,7 @@ var IDLE = Object.freeze({
|
|
|
237
257
|
result: void 0,
|
|
238
258
|
error: void 0
|
|
239
259
|
});
|
|
240
|
-
function
|
|
260
|
+
function useWindowResult(factory) {
|
|
241
261
|
const [state, setState] = useState2(IDLE);
|
|
242
262
|
const current = useRef4(null);
|
|
243
263
|
const factoryRef = useRef4(factory);
|
|
@@ -286,6 +306,24 @@ function useOpenedWindow(factory) {
|
|
|
286
306
|
return { ...state, open, post, close };
|
|
287
307
|
}
|
|
288
308
|
|
|
309
|
+
// src/deprecated.ts
|
|
310
|
+
function useMessage(channel, type, handler, options) {
|
|
311
|
+
warnRenamed("useMessage", "useOnMessage");
|
|
312
|
+
useOnMessage(channel, type, handler, options);
|
|
313
|
+
}
|
|
314
|
+
function useOpenedWindow(factory) {
|
|
315
|
+
warnRenamed("useOpenedWindow", "useWindowResult");
|
|
316
|
+
return useWindowResult(factory);
|
|
317
|
+
}
|
|
318
|
+
function useSharedStore(selector, options) {
|
|
319
|
+
warnRenamed("useSharedStore", "useSharedSelector");
|
|
320
|
+
return useSharedSelector(selector, options);
|
|
321
|
+
}
|
|
322
|
+
function defineStore(name, options = {}) {
|
|
323
|
+
warnRenamed("defineStore", "createStoreHooks");
|
|
324
|
+
return createStoreHooks(name, options);
|
|
325
|
+
}
|
|
326
|
+
|
|
289
327
|
// src/index.ts
|
|
290
328
|
import {
|
|
291
329
|
createChannel,
|
|
@@ -336,6 +374,7 @@ export {
|
|
|
336
374
|
createPresence,
|
|
337
375
|
createSharedReducer,
|
|
338
376
|
createSharedStore,
|
|
377
|
+
createStoreHooks,
|
|
339
378
|
defaultTransport,
|
|
340
379
|
defineChannel,
|
|
341
380
|
defineStore,
|
|
@@ -365,12 +404,15 @@ export {
|
|
|
365
404
|
useLeader,
|
|
366
405
|
useLeaderEffect,
|
|
367
406
|
useMessage,
|
|
407
|
+
useOnMessage,
|
|
368
408
|
useOpenedWindow,
|
|
369
409
|
usePeers,
|
|
370
410
|
usePresenceMetadata,
|
|
371
411
|
useSend,
|
|
372
412
|
useSharedReducer,
|
|
413
|
+
useSharedSelector,
|
|
373
414
|
useSharedState,
|
|
374
415
|
useSharedStore,
|
|
416
|
+
useWindowResult,
|
|
375
417
|
webStorageAdapter
|
|
376
418
|
};
|
package/llms.txt
CHANGED
|
@@ -31,7 +31,7 @@ Open it in two tabs. Clicking in one updates both.
|
|
|
31
31
|
|
|
32
32
|
## The three mistakes to avoid
|
|
33
33
|
|
|
34
|
-
**1. Calling `defineChannel` or `
|
|
34
|
+
**1. Calling `defineChannel` or `createStoreHooks` inside a component.** They are
|
|
35
35
|
module-scope factories. Called in a render they build a new bus on every
|
|
36
36
|
render, and the page syncs nothing while looking completely correct. Install
|
|
37
37
|
`eslint-plugin-use-everywhere` — this is the mistake its `define-at-module-scope`
|
|
@@ -65,9 +65,9 @@ and symbols do not survive. Dates, Maps, Sets and typed arrays do. The
|
|
|
65
65
|
| --- | --- | --- |
|
|
66
66
|
| `useSharedState` | hook | "What is the current value?" — `useState` across every tab |
|
|
67
67
|
| `useSharedReducer` | hook | The same, dispatch-shaped |
|
|
68
|
-
| `
|
|
68
|
+
| `useSharedSelector` | hook | Subscribe to a slice of a store with a selector |
|
|
69
69
|
| `useChannel` | hook | The typed event channel for a name |
|
|
70
|
-
| `
|
|
70
|
+
| `useOnMessage` | hook | Run a handler when another tab posts an event |
|
|
71
71
|
| `useSend` | hook | A stable, typed `post` for a channel |
|
|
72
72
|
| `useAsk` | hook | Request/response across tabs |
|
|
73
73
|
| `useAnswer` | hook | Serve the other half of `useAsk` |
|
|
@@ -77,10 +77,10 @@ and symbols do not survive. Dates, Maps, Sets and typed arrays do. The
|
|
|
77
77
|
| `useLeader` | hook | Elect exactly one tab to own a job |
|
|
78
78
|
| `useIsLeader` | hook | Whether this tab currently holds the lease |
|
|
79
79
|
| `useLeaderEffect` | hook | Run an effect only in the leader tab |
|
|
80
|
-
| `
|
|
80
|
+
| `useWindowResult` | hook | The cross-origin window lifecycle as render state |
|
|
81
81
|
| `useHydrated` | hook | Whether the first cross-tab sync has landed (SSR) |
|
|
82
82
|
| `defineChannel` | factory | Bind a channel name + message map once, at module scope |
|
|
83
|
-
| `
|
|
83
|
+
| `createStoreHooks` | factory | The same for a store, and where persistence is enabled |
|
|
84
84
|
| `createNamespace` | factory | Prefix every bus name, for micro-frontends |
|
|
85
85
|
| `Inspector` | component | Devtools panel; import from `use-everywhere/devtools` |
|
|
86
86
|
|
|
@@ -91,7 +91,7 @@ in `@use-everywhere/core` is re-exported from here too — see that package's
|
|
|
91
91
|
## Gotchas
|
|
92
92
|
|
|
93
93
|
- **Shared state never crosses origins.** Two origins are two trust domains. For
|
|
94
|
-
that, open a window explicitly with `
|
|
94
|
+
that, open a window explicitly with `useWindowResult`, which is typed,
|
|
95
95
|
per-message and validated by origin.
|
|
96
96
|
- **Last-writer-wins, per key.** Per-key `[counter, clientId]` clocks give a
|
|
97
97
|
deterministic tie-break, not a merge. Two tabs editing the same key
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-everywhere",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "React hooks for state and messages shared across tabs, windows, and workers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jonatan Kruszewski <jonakrusze@gmail.com>",
|
|
@@ -109,9 +109,9 @@
|
|
|
109
109
|
"limit": "4.24 kB"
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
|
-
"name": "
|
|
112
|
+
"name": "useSharedSelector",
|
|
113
113
|
"path": "dist/index.js",
|
|
114
|
-
"import": "{
|
|
114
|
+
"import": "{ useSharedSelector, shallowEqual }",
|
|
115
115
|
"limit": "4.40 kB"
|
|
116
116
|
},
|
|
117
117
|
{
|
|
@@ -121,9 +121,9 @@
|
|
|
121
121
|
"limit": "4.21 kB"
|
|
122
122
|
},
|
|
123
123
|
{
|
|
124
|
-
"name": "useChannel +
|
|
124
|
+
"name": "useChannel + useOnMessage + useSend",
|
|
125
125
|
"path": "dist/index.js",
|
|
126
|
-
"import": "{ useChannel,
|
|
126
|
+
"import": "{ useChannel, useOnMessage, useSend }",
|
|
127
127
|
"limit": "3.07 kB"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
@@ -133,9 +133,9 @@
|
|
|
133
133
|
"limit": "2.77 kB"
|
|
134
134
|
},
|
|
135
135
|
{
|
|
136
|
-
"name": "
|
|
136
|
+
"name": "useWindowResult + openWindow",
|
|
137
137
|
"path": "dist/index.js",
|
|
138
|
-
"import": "{
|
|
138
|
+
"import": "{ useWindowResult, openWindow }",
|
|
139
139
|
"limit": "1.47 kB"
|
|
140
140
|
},
|
|
141
141
|
{
|
|
@@ -145,10 +145,10 @@
|
|
|
145
145
|
"limit": "3.65 kB"
|
|
146
146
|
},
|
|
147
147
|
{
|
|
148
|
-
"name": "
|
|
148
|
+
"name": "createStoreHooks (persisted)",
|
|
149
149
|
"path": "dist/index.js",
|
|
150
|
-
"import": "{
|
|
151
|
-
"limit": "
|
|
150
|
+
"import": "{ createStoreHooks, localStorageAdapter }",
|
|
151
|
+
"limit": "6 kB"
|
|
152
152
|
},
|
|
153
153
|
{
|
|
154
154
|
"name": "Inspector (devtools subpath)",
|
|
@@ -183,19 +183,19 @@
|
|
|
183
183
|
},
|
|
184
184
|
"devDependencies": {
|
|
185
185
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
186
|
-
"@size-limit/preset-small-lib": "^13.0.
|
|
186
|
+
"@size-limit/preset-small-lib": "^13.0.3",
|
|
187
187
|
"@testing-library/react": "^16.3.2",
|
|
188
188
|
"@types/react": "^19.2.17",
|
|
189
189
|
"@types/react-dom": "^19.2.3",
|
|
190
|
-
"@vitest/coverage-v8": "^4.1.
|
|
191
|
-
"happy-dom": "^20.11.
|
|
192
|
-
"publint": "^0.3.
|
|
190
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
191
|
+
"happy-dom": "^20.11.15",
|
|
192
|
+
"publint": "^0.3.24",
|
|
193
193
|
"react": "^19.2.8",
|
|
194
194
|
"react-dom": "^19.2.8",
|
|
195
|
-
"size-limit": "^13.0.
|
|
195
|
+
"size-limit": "^13.0.3",
|
|
196
196
|
"tsup": "^8.5.1",
|
|
197
197
|
"typescript": "^6.0.3",
|
|
198
|
-
"vitest": "^4.1.
|
|
198
|
+
"vitest": "^4.1.11"
|
|
199
199
|
},
|
|
200
200
|
"typesVersions": {
|
|
201
201
|
"*": {
|