use-everywhere 0.12.0 → 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/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.useMessage('cart-updated', (payload) => setItems(payload.items));
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)`, `useMessage(channel, type,
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: `useOpenedWindow`
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, useOpenedWindow } from 'use-everywhere';
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 = useOpenedWindow<ToPayment, FromPayment, Receipt>(() =>
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
  }),
@@ -43,7 +43,7 @@ function warnOnInitialMismatch(storeName, key, initial) {
43
43
  if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
44
44
  devWarn(
45
45
  "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 defineStore, or a shared constant.`
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 createStoreHooks, or a shared constant.`
47
47
  );
48
48
  }
49
49
  }
@@ -127,7 +127,7 @@ function configureStore(name, scope, options) {
127
127
  if (process.env.NODE_ENV !== "production") {
128
128
  devWarn(
129
129
  "UE2002",
130
- `defineStore('${name}') ran after that store was already created, with different options. The live store keeps the configuration it was built with. Move defineStore to module scope, before any component reads the store.`
130
+ `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
131
  );
132
132
  }
133
133
  return;
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getSharedStore,
4
4
  usePeers
5
- } from "../chunk-R7PBPLF7.js";
5
+ } from "../chunk-YPQ6PLD5.js";
6
6
 
7
7
  // src/devtools/inspector.tsx
8
8
  import { useState as useState2 } from "react";
package/dist/index.cjs CHANGED
@@ -37,9 +37,9 @@ __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
- defineStore: () => defineStore,
43
43
  enableDebug: () => import_core4.enableDebug,
44
44
  getBusNames: () => import_core4.getBusNames,
45
45
  getLeader: () => getLeader,
@@ -65,14 +65,14 @@ __export(src_exports, {
65
65
  useIsLeader: () => useIsLeader,
66
66
  useLeader: () => useLeader,
67
67
  useLeaderEffect: () => useLeaderEffect,
68
- useMessage: () => useMessage,
69
- useOpenedWindow: () => useOpenedWindow,
68
+ useOnMessage: () => useOnMessage,
70
69
  usePeers: () => usePeers,
71
70
  usePresenceMetadata: () => usePresenceMetadata,
72
71
  useSend: () => useSend,
73
72
  useSharedReducer: () => useSharedReducer,
73
+ useSharedSelector: () => useSharedSelector,
74
74
  useSharedState: () => useSharedState,
75
- useSharedStore: () => useSharedStore,
75
+ useWindowResult: () => useWindowResult,
76
76
  webStorageAdapter: () => import_core4.webStorageAdapter
77
77
  });
78
78
  module.exports = __toCommonJS(src_exports);
@@ -112,7 +112,7 @@ function warnOnInitialMismatch(storeName, key, initial) {
112
112
  if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
113
113
  devWarn(
114
114
  "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 defineStore, or a shared constant.`
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 createStoreHooks, or a shared constant.`
116
116
  );
117
117
  }
118
118
  }
@@ -199,7 +199,7 @@ function configureStore(name, scope, options) {
199
199
  if (process.env.NODE_ENV !== "production") {
200
200
  devWarn(
201
201
  "UE2002",
202
- `defineStore('${name}') ran after that store was already created, with different options. The live store keeps the configuration it was built with. Move defineStore to module scope, before any component reads the store.`
202
+ `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
203
  );
204
204
  }
205
205
  return;
@@ -325,7 +325,7 @@ function useSharedReducer(reducer, initial, options) {
325
325
 
326
326
  // src/use-shared-selector.ts
327
327
  var import_react3 = require("react");
328
- function useSharedStore(selector, options) {
328
+ function useSharedSelector(selector, options) {
329
329
  const store = getStore(options?.store ?? import_core.DEFAULT_NAME, options?.scope ?? "everywhere");
330
330
  const equal = options?.equal ?? Object.is;
331
331
  const selectorRef = (0, import_react3.useRef)(selector);
@@ -359,12 +359,12 @@ function shallowEqual(a, b) {
359
359
  return keys.every((key) => Object.is(left[key], right[key]));
360
360
  }
361
361
 
362
- // src/use-message.ts
362
+ // src/use-on-message.ts
363
363
  var import_react4 = require("react");
364
364
  function useChannel(name) {
365
365
  return getChannel(name);
366
366
  }
367
- function useMessage(channel, type, handler, options) {
367
+ function useOnMessage(channel, type, handler, options) {
368
368
  const handlerRef = (0, import_react4.useRef)(handler);
369
369
  (0, import_react4.useEffect)(() => {
370
370
  handlerRef.current = handler;
@@ -398,16 +398,16 @@ function useAsk(channel) {
398
398
  function defineChannel(name, options) {
399
399
  if (options) configureChannel(name, options);
400
400
  const useBoundSend = () => useSend(useChannel(name));
401
- const useBoundMessage = (type, handler) => useMessage(useChannel(name), type, handler);
401
+ const useBoundMessage = (type, handler) => useOnMessage(useChannel(name), type, handler);
402
402
  return {
403
403
  get: () => getChannel(name),
404
404
  useSend: useBoundSend,
405
- useMessage: useBoundMessage
405
+ useOnMessage: useBoundMessage
406
406
  };
407
407
  }
408
408
 
409
- // src/define-store.ts
410
- function defineStore(name, options = {}) {
409
+ // src/create-store-hooks.ts
410
+ function createStoreHooks(name, options = {}) {
411
411
  const scope = options.scope ?? "everywhere";
412
412
  if (options.persist) {
413
413
  configureStore(name, scope, {
@@ -422,7 +422,7 @@ function defineStore(name, options = {}) {
422
422
  });
423
423
  }
424
424
  return {
425
- get: () => getStore(name, scope),
425
+ store: () => getStore(name, scope),
426
426
  useSharedState: (key, initial) => useSharedState(key, initial, { store: name, scope })
427
427
  };
428
428
  }
@@ -512,11 +512,11 @@ function createNamespace(namespace) {
512
512
  const { busName } = core;
513
513
  return {
514
514
  ...core,
515
- defineStore: (name, options) => defineStore(busName(name), options),
515
+ createStoreHooks: (name, options) => createStoreHooks(busName(name), options),
516
516
  defineChannel: (name, options) => defineChannel(busName(name), options),
517
517
  getSharedStore: (name, scope) => getSharedStore(busName(name), scope),
518
518
  useSharedState: (key, initial, options) => useSharedState(key, initial, { ...options, store: busName(options?.store) }),
519
- useSharedStore: (selector, options) => useSharedStore(selector, { ...options, store: busName(options?.store) }),
519
+ useSharedSelector: (selector, options) => useSharedSelector(selector, { ...options, store: busName(options?.store) }),
520
520
  usePeers: (options) => usePeers({ ...options, name: busName(options?.name) }),
521
521
  usePresenceMetadata: (metadata, options) => usePresenceMetadata(metadata, { ...options, name: busName(options?.name) }),
522
522
  useHydrated: (options) => useHydrated({ ...options, store: busName(options?.store) }),
@@ -527,7 +527,7 @@ function createNamespace(namespace) {
527
527
  };
528
528
  }
529
529
 
530
- // src/use-opened-window.ts
530
+ // src/use-window-result.ts
531
531
  var import_react8 = require("react");
532
532
  var import_core3 = require("@use-everywhere/core");
533
533
  var IDLE = Object.freeze({
@@ -535,7 +535,7 @@ var IDLE = Object.freeze({
535
535
  result: void 0,
536
536
  error: void 0
537
537
  });
538
- function useOpenedWindow(factory) {
538
+ function useWindowResult(factory) {
539
539
  const [state, setState] = (0, import_react8.useState)(IDLE);
540
540
  const current = (0, import_react8.useRef)(null);
541
541
  const factoryRef = (0, import_react8.useRef)(factory);
@@ -604,9 +604,9 @@ var import_core4 = require("@use-everywhere/core");
604
604
  createPresence,
605
605
  createSharedReducer,
606
606
  createSharedStore,
607
+ createStoreHooks,
607
608
  defaultTransport,
608
609
  defineChannel,
609
- defineStore,
610
610
  enableDebug,
611
611
  getBusNames,
612
612
  getLeader,
@@ -632,13 +632,13 @@ var import_core4 = require("@use-everywhere/core");
632
632
  useIsLeader,
633
633
  useLeader,
634
634
  useLeaderEffect,
635
- useMessage,
636
- useOpenedWindow,
635
+ useOnMessage,
637
636
  usePeers,
638
637
  usePresenceMetadata,
639
638
  useSend,
640
639
  useSharedReducer,
640
+ useSharedSelector,
641
641
  useSharedState,
642
- useSharedStore,
642
+ useWindowResult,
643
643
  webStorageAdapter
644
644
  });
package/dist/index.d.cts CHANGED
@@ -91,7 +91,7 @@ interface UseSharedSelectorOptions extends UseSharedStateOptions {
91
91
  * anything in it.
92
92
  *
93
93
  * ```tsx
94
- * const total = useSharedStore<Cart, number>(
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 useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
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 UseMessageOptions {
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 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;
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,14 @@ 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
- * `useMessage`: the handler is kept fresh without resubscribing.
176
+ * `useOnMessage`: the handler is kept fresh without resubscribing.
177
177
  */
178
- useMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
178
+ useOnMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
179
179
  }
180
180
 
181
181
  /**
182
182
  * Bind a channel name and message map once, at module level, and get fully
183
- * typed hooks back. Sugar over useChannel/useMessage/useSend — the same
183
+ * typed hooks back. Sugar over useChannel/useOnMessage/useSend — the same
184
184
  * page-wide channel singleton is shared, so mixing bound and standalone
185
185
  * hooks for one name is safe.
186
186
  *
@@ -189,7 +189,7 @@ interface ChannelHooks<M extends MessageMap> {
189
189
  */
190
190
  declare function defineChannel<M extends MessageMap>(name: string, options?: ChannelOptions<M>): ChannelHooks<M>;
191
191
 
192
- interface DefineStoreOptions {
192
+ interface CreateStoreHooksOptions {
193
193
  /** Restore this store from disk on first use, and write it back as it changes. */
194
194
  persist?: PersistAdapter;
195
195
  /** Persist only these keys. Default: every key that has been written. */
@@ -212,7 +212,7 @@ interface DefineStoreOptions {
212
212
  /** A store bound to a name and a shape: typed hooks with no per-call generics. */
213
213
  interface StoreHooks<S extends Record<string, unknown>> {
214
214
  /** The underlying store instance (the same one the hooks use) — for non-React code. */
215
- get: () => AnyStore;
215
+ store: () => AnyStore;
216
216
  useSharedState: <K extends keyof S & string>(key: K, initial: S[K]) => [S[K], (next: S[K] | ((prev: S[K]) => S[K])) => void];
217
217
  }
218
218
 
@@ -222,7 +222,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
222
222
  * Like defineChannel, this does not construct anything: it registers the
223
223
  * options the registry will use when the store is first needed, so importing
224
224
  * the module has no side effect. The store stays a singleton per name, so
225
- * `defineStore('settings', { persist })` and a bare
225
+ * `createStoreHooks('settings', { persist })` and a bare
226
226
  * `useSharedState('theme', 'dark', { store: 'settings' })` elsewhere resolve to
227
227
  * the same store, and both get persistence.
228
228
  *
@@ -230,7 +230,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
230
230
  * so intended usage is automatic; if it does run late it throws rather than
231
231
  * quietly handing back a store with no persistence.
232
232
  */
233
- declare function defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: DefineStoreOptions): StoreHooks<S>;
233
+ declare function createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
234
234
 
235
235
  interface UsePeersOptions {
236
236
  /** Bus name. Default 'use-everywhere'. */
@@ -337,11 +337,11 @@ declare function useLeaderEffect(effect: () => void | (() => void), options?: Us
337
337
  * which namespace it lives in.
338
338
  */
339
339
  interface ReactNamespace extends Namespace {
340
- defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: DefineStoreOptions): StoreHooks<S>;
340
+ createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
341
341
  defineChannel<M extends MessageMap>(name?: string, options?: ChannelOptions<M>): ChannelHooks<M>;
342
342
  getSharedStore(name?: string, scope?: UseSharedStateOptions['scope']): AnyStore;
343
343
  useSharedState<T>(key: string, initial: T, options?: UseSharedStateOptions): [T, (next: T | ((prev: T) => T)) => void];
344
- useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
344
+ useSharedSelector<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
345
345
  usePeers(options?: UsePeersOptions): readonly Peer[];
346
346
  usePresenceMetadata(metadata: unknown, options?: UsePeersOptions): void;
347
347
  useHydrated(options?: UseSharedStateOptions): boolean;
@@ -364,7 +364,7 @@ interface ReactNamespace extends Namespace {
364
364
  * const [items, setItems] = checkout.useSharedState('items', []);
365
365
  * ```
366
366
  *
367
- * Call it **at module scope**, like `defineStore` and `defineChannel`. It
367
+ * Call it **at module scope**, like `createStoreHooks` and `defineChannel`. It
368
368
  * builds a small object of bound functions, and rebuilding that on every render
369
369
  * would hand React a new `useSharedState` identity each time — harmless for the
370
370
  * hooks themselves, which key off the bus name, but pointless work and a
@@ -418,7 +418,7 @@ interface OpenedWindowControls<Out extends MessageMap, In extends MessageMap, R>
418
418
  post: OpenedWindow<Out, In, R>['post'];
419
419
  close: () => void;
420
420
  }
421
- type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = OpenedWindowState<R> & OpenedWindowControls<Out, In, R>;
421
+ type UseWindowResult<Out extends MessageMap, In extends MessageMap, R> = OpenedWindowState<R> & OpenedWindowControls<Out, In, R>;
422
422
 
423
423
  /**
424
424
  * Drive an openWindow() flow from a component: the factory is called on
@@ -429,6 +429,6 @@ type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = OpenedW
429
429
  * because a route changed would lose the user's in-flight transaction. Call
430
430
  * close() if the component owns the window's lifetime.
431
431
  */
432
- declare function useOpenedWindow<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseOpenedWindow<Out, In, R>;
432
+ declare function useWindowResult<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseWindowResult<Out, In, R>;
433
433
 
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 };
434
+ export { type AnyStore, type ChannelHooks, type CreateStoreHooksOptions, type OpenedWindowControls, type OpenedWindowState, type OpenedWindowStatus, type ReactNamespace, type ShareScope, type StoreHooks, type UseLeaderOptions, type UseOnMessageOptions, type UsePeersOptions, type UseSharedReducerOptions, type UseSharedSelectorOptions, type UseSharedStateOptions, type UseWindowResult, createNamespace, createStoreHooks, defineChannel, getLeader, getSharedStore, shallowEqual, useAnswer, useAsk, useChannel, useClientId, useHydrated, useIsLeader, useLeader, useLeaderEffect, useOnMessage, usePeers, usePresenceMetadata, useSend, useSharedReducer, useSharedSelector, useSharedState, useWindowResult };
package/dist/index.d.ts CHANGED
@@ -91,7 +91,7 @@ interface UseSharedSelectorOptions extends UseSharedStateOptions {
91
91
  * anything in it.
92
92
  *
93
93
  * ```tsx
94
- * const total = useSharedStore<Cart, number>(
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 useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
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 UseMessageOptions {
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 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;
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,14 @@ 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
- * `useMessage`: the handler is kept fresh without resubscribing.
176
+ * `useOnMessage`: the handler is kept fresh without resubscribing.
177
177
  */
178
- useMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
178
+ useOnMessage: <K extends keyof M & string>(type: K, handler: (payload: M[K], meta: MessageMeta) => void) => void;
179
179
  }
180
180
 
181
181
  /**
182
182
  * Bind a channel name and message map once, at module level, and get fully
183
- * typed hooks back. Sugar over useChannel/useMessage/useSend — the same
183
+ * typed hooks back. Sugar over useChannel/useOnMessage/useSend — the same
184
184
  * page-wide channel singleton is shared, so mixing bound and standalone
185
185
  * hooks for one name is safe.
186
186
  *
@@ -189,7 +189,7 @@ interface ChannelHooks<M extends MessageMap> {
189
189
  */
190
190
  declare function defineChannel<M extends MessageMap>(name: string, options?: ChannelOptions<M>): ChannelHooks<M>;
191
191
 
192
- interface DefineStoreOptions {
192
+ interface CreateStoreHooksOptions {
193
193
  /** Restore this store from disk on first use, and write it back as it changes. */
194
194
  persist?: PersistAdapter;
195
195
  /** Persist only these keys. Default: every key that has been written. */
@@ -212,7 +212,7 @@ interface DefineStoreOptions {
212
212
  /** A store bound to a name and a shape: typed hooks with no per-call generics. */
213
213
  interface StoreHooks<S extends Record<string, unknown>> {
214
214
  /** The underlying store instance (the same one the hooks use) — for non-React code. */
215
- get: () => AnyStore;
215
+ store: () => AnyStore;
216
216
  useSharedState: <K extends keyof S & string>(key: K, initial: S[K]) => [S[K], (next: S[K] | ((prev: S[K]) => S[K])) => void];
217
217
  }
218
218
 
@@ -222,7 +222,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
222
222
  * Like defineChannel, this does not construct anything: it registers the
223
223
  * options the registry will use when the store is first needed, so importing
224
224
  * the module has no side effect. The store stays a singleton per name, so
225
- * `defineStore('settings', { persist })` and a bare
225
+ * `createStoreHooks('settings', { persist })` and a bare
226
226
  * `useSharedState('theme', 'dark', { store: 'settings' })` elsewhere resolve to
227
227
  * the same store, and both get persistence.
228
228
  *
@@ -230,7 +230,7 @@ interface StoreHooks<S extends Record<string, unknown>> {
230
230
  * so intended usage is automatic; if it does run late it throws rather than
231
231
  * quietly handing back a store with no persistence.
232
232
  */
233
- declare function defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: DefineStoreOptions): StoreHooks<S>;
233
+ declare function createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
234
234
 
235
235
  interface UsePeersOptions {
236
236
  /** Bus name. Default 'use-everywhere'. */
@@ -337,11 +337,11 @@ declare function useLeaderEffect(effect: () => void | (() => void), options?: Us
337
337
  * which namespace it lives in.
338
338
  */
339
339
  interface ReactNamespace extends Namespace {
340
- defineStore<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: DefineStoreOptions): StoreHooks<S>;
340
+ createStoreHooks<S extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: CreateStoreHooksOptions): StoreHooks<S>;
341
341
  defineChannel<M extends MessageMap>(name?: string, options?: ChannelOptions<M>): ChannelHooks<M>;
342
342
  getSharedStore(name?: string, scope?: UseSharedStateOptions['scope']): AnyStore;
343
343
  useSharedState<T>(key: string, initial: T, options?: UseSharedStateOptions): [T, (next: T | ((prev: T) => T)) => void];
344
- useSharedStore<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
344
+ useSharedSelector<S extends Record<string, unknown>, T>(selector: (state: S) => T, options?: UseSharedSelectorOptions): T;
345
345
  usePeers(options?: UsePeersOptions): readonly Peer[];
346
346
  usePresenceMetadata(metadata: unknown, options?: UsePeersOptions): void;
347
347
  useHydrated(options?: UseSharedStateOptions): boolean;
@@ -364,7 +364,7 @@ interface ReactNamespace extends Namespace {
364
364
  * const [items, setItems] = checkout.useSharedState('items', []);
365
365
  * ```
366
366
  *
367
- * Call it **at module scope**, like `defineStore` and `defineChannel`. It
367
+ * Call it **at module scope**, like `createStoreHooks` and `defineChannel`. It
368
368
  * builds a small object of bound functions, and rebuilding that on every render
369
369
  * would hand React a new `useSharedState` identity each time — harmless for the
370
370
  * hooks themselves, which key off the bus name, but pointless work and a
@@ -418,7 +418,7 @@ interface OpenedWindowControls<Out extends MessageMap, In extends MessageMap, R>
418
418
  post: OpenedWindow<Out, In, R>['post'];
419
419
  close: () => void;
420
420
  }
421
- type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = OpenedWindowState<R> & OpenedWindowControls<Out, In, R>;
421
+ type UseWindowResult<Out extends MessageMap, In extends MessageMap, R> = OpenedWindowState<R> & OpenedWindowControls<Out, In, R>;
422
422
 
423
423
  /**
424
424
  * Drive an openWindow() flow from a component: the factory is called on
@@ -429,6 +429,6 @@ type UseOpenedWindow<Out extends MessageMap, In extends MessageMap, R> = OpenedW
429
429
  * because a route changed would lose the user's in-flight transaction. Call
430
430
  * close() if the component owns the window's lifetime.
431
431
  */
432
- declare function useOpenedWindow<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseOpenedWindow<Out, In, R>;
432
+ declare function useWindowResult<Out extends MessageMap, In extends MessageMap, R = unknown>(factory: () => OpenedWindow<Out, In, R>): UseWindowResult<Out, In, R>;
433
433
 
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 };
434
+ export { type AnyStore, type ChannelHooks, type CreateStoreHooksOptions, type OpenedWindowControls, type OpenedWindowState, type OpenedWindowStatus, type ReactNamespace, type ShareScope, type StoreHooks, type UseLeaderOptions, type UseOnMessageOptions, type UsePeersOptions, type UseSharedReducerOptions, type UseSharedSelectorOptions, type UseSharedStateOptions, type UseWindowResult, createNamespace, createStoreHooks, defineChannel, getLeader, getSharedStore, shallowEqual, useAnswer, useAsk, useChannel, useClientId, useHydrated, useIsLeader, useLeader, useLeaderEffect, useOnMessage, usePeers, usePresenceMetadata, useSend, useSharedReducer, useSharedSelector, useSharedState, useWindowResult };
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  usePeers,
13
13
  usePresenceMetadata,
14
14
  warnOnInitialMismatch
15
- } from "./chunk-R7PBPLF7.js";
15
+ } from "./chunk-YPQ6PLD5.js";
16
16
 
17
17
  // src/use-shared-state.ts
18
18
  import { useCallback, useSyncExternalStore } from "react";
@@ -55,7 +55,7 @@ function useSharedReducer(reducer, initial, options) {
55
55
 
56
56
  // src/use-shared-selector.ts
57
57
  import { useCallback as useCallback3, useRef, useSyncExternalStore as useSyncExternalStore3 } from "react";
58
- function useSharedStore(selector, options) {
58
+ function useSharedSelector(selector, options) {
59
59
  const store = getStore(options?.store ?? DEFAULT_NAME, options?.scope ?? "everywhere");
60
60
  const equal = options?.equal ?? Object.is;
61
61
  const selectorRef = useRef(selector);
@@ -89,12 +89,12 @@ function shallowEqual(a, b) {
89
89
  return keys.every((key) => Object.is(left[key], right[key]));
90
90
  }
91
91
 
92
- // src/use-message.ts
92
+ // src/use-on-message.ts
93
93
  import { useEffect, useRef as useRef2 } from "react";
94
94
  function useChannel(name) {
95
95
  return getChannel(name);
96
96
  }
97
- function useMessage(channel, type, handler, options) {
97
+ function useOnMessage(channel, type, handler, options) {
98
98
  const handlerRef = useRef2(handler);
99
99
  useEffect(() => {
100
100
  handlerRef.current = handler;
@@ -128,16 +128,16 @@ function useAsk(channel) {
128
128
  function defineChannel(name, options) {
129
129
  if (options) configureChannel(name, options);
130
130
  const useBoundSend = () => useSend(useChannel(name));
131
- const useBoundMessage = (type, handler) => useMessage(useChannel(name), type, handler);
131
+ const useBoundMessage = (type, handler) => useOnMessage(useChannel(name), type, handler);
132
132
  return {
133
133
  get: () => getChannel(name),
134
134
  useSend: useBoundSend,
135
- useMessage: useBoundMessage
135
+ useOnMessage: useBoundMessage
136
136
  };
137
137
  }
138
138
 
139
- // src/define-store.ts
140
- function defineStore(name, options = {}) {
139
+ // src/create-store-hooks.ts
140
+ function createStoreHooks(name, options = {}) {
141
141
  const scope = options.scope ?? "everywhere";
142
142
  if (options.persist) {
143
143
  configureStore(name, scope, {
@@ -152,7 +152,7 @@ function defineStore(name, options = {}) {
152
152
  });
153
153
  }
154
154
  return {
155
- get: () => getStore(name, scope),
155
+ store: () => getStore(name, scope),
156
156
  useSharedState: (key, initial) => useSharedState(key, initial, { store: name, scope })
157
157
  };
158
158
  }
@@ -214,11 +214,11 @@ function createNamespace(namespace) {
214
214
  const { busName } = core;
215
215
  return {
216
216
  ...core,
217
- defineStore: (name, options) => defineStore(busName(name), options),
217
+ createStoreHooks: (name, options) => createStoreHooks(busName(name), options),
218
218
  defineChannel: (name, options) => defineChannel(busName(name), options),
219
219
  getSharedStore: (name, scope) => getSharedStore(busName(name), scope),
220
220
  useSharedState: (key, initial, options) => useSharedState(key, initial, { ...options, store: busName(options?.store) }),
221
- useSharedStore: (selector, options) => useSharedStore(selector, { ...options, store: busName(options?.store) }),
221
+ useSharedSelector: (selector, options) => useSharedSelector(selector, { ...options, store: busName(options?.store) }),
222
222
  usePeers: (options) => usePeers({ ...options, name: busName(options?.name) }),
223
223
  usePresenceMetadata: (metadata, options) => usePresenceMetadata(metadata, { ...options, name: busName(options?.name) }),
224
224
  useHydrated: (options) => useHydrated({ ...options, store: busName(options?.store) }),
@@ -229,7 +229,7 @@ function createNamespace(namespace) {
229
229
  };
230
230
  }
231
231
 
232
- // src/use-opened-window.ts
232
+ // src/use-window-result.ts
233
233
  import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef4, useState as useState2 } from "react";
234
234
  import { WindowClosedError } from "@use-everywhere/core";
235
235
  var IDLE = Object.freeze({
@@ -237,7 +237,7 @@ var IDLE = Object.freeze({
237
237
  result: void 0,
238
238
  error: void 0
239
239
  });
240
- function useOpenedWindow(factory) {
240
+ function useWindowResult(factory) {
241
241
  const [state, setState] = useState2(IDLE);
242
242
  const current = useRef4(null);
243
243
  const factoryRef = useRef4(factory);
@@ -336,9 +336,9 @@ export {
336
336
  createPresence,
337
337
  createSharedReducer,
338
338
  createSharedStore,
339
+ createStoreHooks,
339
340
  defaultTransport,
340
341
  defineChannel,
341
- defineStore,
342
342
  enableDebug,
343
343
  getBusNames,
344
344
  getLeader,
@@ -364,13 +364,13 @@ export {
364
364
  useIsLeader,
365
365
  useLeader,
366
366
  useLeaderEffect,
367
- useMessage,
368
- useOpenedWindow,
367
+ useOnMessage,
369
368
  usePeers,
370
369
  usePresenceMetadata,
371
370
  useSend,
372
371
  useSharedReducer,
372
+ useSharedSelector,
373
373
  useSharedState,
374
- useSharedStore,
374
+ useWindowResult,
375
375
  webStorageAdapter
376
376
  };
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 `defineStore` inside a component.** They are
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
- | `useSharedStore` | hook | Subscribe to a slice of a store with a selector |
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
- | `useMessage` | hook | Run a handler when another tab posts an event |
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
- | `useOpenedWindow` | hook | The cross-origin window lifecycle as render state |
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
- | `defineStore` | factory | The same for a store, and where persistence is enabled |
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 `useOpenedWindow`, which is typed,
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.12.0",
3
+ "version": "1.0.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": "useSharedStore (selector)",
112
+ "name": "useSharedSelector",
113
113
  "path": "dist/index.js",
114
- "import": "{ useSharedStore, shallowEqual }",
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 + useMessage + useSend",
124
+ "name": "useChannel + useOnMessage + useSend",
125
125
  "path": "dist/index.js",
126
- "import": "{ useChannel, useMessage, useSend }",
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": "useOpenedWindow + openWindow",
136
+ "name": "useWindowResult + openWindow",
137
137
  "path": "dist/index.js",
138
- "import": "{ useOpenedWindow, openWindow }",
138
+ "import": "{ useWindowResult, openWindow }",
139
139
  "limit": "1.47 kB"
140
140
  },
141
141
  {
@@ -145,9 +145,9 @@
145
145
  "limit": "3.65 kB"
146
146
  },
147
147
  {
148
- "name": "defineStore (persisted)",
148
+ "name": "createStoreHooks (persisted)",
149
149
  "path": "dist/index.js",
150
- "import": "{ defineStore, localStorageAdapter }",
150
+ "import": "{ createStoreHooks, localStorageAdapter }",
151
151
  "limit": "4.67 kB"
152
152
  },
153
153
  {
@@ -170,7 +170,7 @@
170
170
  }
171
171
  ],
172
172
  "dependencies": {
173
- "@use-everywhere/core": "0.11.2"
173
+ "@use-everywhere/core": "1.0.0"
174
174
  },
175
175
  "peerDependencies": {
176
176
  "react": ">=18",
@@ -187,7 +187,7 @@
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.10",
190
+ "@vitest/coverage-v8": "^4.1.11",
191
191
  "happy-dom": "^20.11.15",
192
192
  "publint": "^0.3.24",
193
193
  "react": "^19.2.8",
@@ -195,7 +195,7 @@
195
195
  "size-limit": "^13.0.3",
196
196
  "tsup": "^8.5.1",
197
197
  "typescript": "^6.0.3",
198
- "vitest": "^4.1.10"
198
+ "vitest": "^4.1.11"
199
199
  },
200
200
  "typesVersions": {
201
201
  "*": {