use-everywhere 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/llms.txt +113 -0
  2. package/package.json +15 -5
package/llms.txt ADDED
@@ -0,0 +1,113 @@
1
+ # use-everywhere
2
+
3
+ > React hooks for state, messages, presence and leader election that exist in
4
+ > every tab, window and worker on an origin. `useSharedState` is `useState` whose
5
+ > value lives in every tab; writes converge in milliseconds and a tab opened
6
+ > later hydrates to the current value rather than the initial one. There is no
7
+ > Provider and no server. This package re-exports the whole of
8
+ > `@use-everywhere/core`, so it is the only install a React app needs. React >=
9
+ > 18. Ships ESM and CommonJS.
10
+
11
+ ## Install
12
+
13
+ npm install use-everywhere
14
+
15
+ `react >= 18` is the only peer dependency.
16
+
17
+ ## Minimal working example
18
+
19
+ ```tsx
20
+ import { useSharedState } from 'use-everywhere';
21
+
22
+ export function Counter() {
23
+ // Same signature as useState. The value exists in every tab on the origin.
24
+ const [count, setCount] = useSharedState('count', 0);
25
+
26
+ return <button onClick={() => setCount((n) => n + 1)}>{count}</button>;
27
+ }
28
+ ```
29
+
30
+ Open it in two tabs. Clicking in one updates both.
31
+
32
+ ## The three mistakes to avoid
33
+
34
+ **1. Calling `defineChannel` or `defineStore` inside a component.** They are
35
+ module-scope factories. Called in a render they build a new bus on every
36
+ render, and the page syncs nothing while looking completely correct. Install
37
+ `eslint-plugin-use-everywhere` — this is the mistake its `define-at-module-scope`
38
+ rule exists for.
39
+
40
+ ```tsx
41
+ // WRONG — a new channel per render
42
+ function Cart() {
43
+ const shop = defineChannel<ShopEvents>('shop');
44
+ }
45
+
46
+ // RIGHT — once, at module level
47
+ const shop = defineChannel<ShopEvents>('shop');
48
+ function Cart() {
49
+ const post = shop.useSend();
50
+ }
51
+ ```
52
+
53
+ **2. Expecting a Provider.** There isn't one, and there is nothing to wrap. A
54
+ BroadcastChannel is already global to the origin, so identity is the name string
55
+ and the hooks read module-level singletons keyed by it. Just call them.
56
+
57
+ **3. Putting a value in shared state that structured clone cannot carry.** The
58
+ wire is the structured clone algorithm, so functions, class instances, DOM nodes
59
+ and symbols do not survive. Dates, Maps, Sets and typed arrays do. The
60
+ `structured-clone-safe` lint rule catches the rest.
61
+
62
+ ## API
63
+
64
+ | Export | Kind | What it answers |
65
+ | --- | --- | --- |
66
+ | `useSharedState` | hook | "What is the current value?" — `useState` across every tab |
67
+ | `useSharedReducer` | hook | The same, dispatch-shaped |
68
+ | `useSharedStore` | hook | Subscribe to a slice of a store with a selector |
69
+ | `useChannel` | hook | The typed event channel for a name |
70
+ | `useMessage` | hook | Run a handler when another tab posts an event |
71
+ | `useSend` | hook | A stable, typed `post` for a channel |
72
+ | `useAsk` | hook | Request/response across tabs |
73
+ | `useAnswer` | hook | Serve the other half of `useAsk` |
74
+ | `usePeers` | hook | A live list of open tabs, windows and workers |
75
+ | `useClientId` | hook | This tab's stable id on a bus |
76
+ | `usePresenceMetadata` | hook | Attach and read per-peer metadata |
77
+ | `useLeader` | hook | Elect exactly one tab to own a job |
78
+ | `useIsLeader` | hook | Whether this tab currently holds the lease |
79
+ | `useLeaderEffect` | hook | Run an effect only in the leader tab |
80
+ | `useOpenedWindow` | hook | The cross-origin window lifecycle as render state |
81
+ | `useHydrated` | hook | Whether the first cross-tab sync has landed (SSR) |
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 |
84
+ | `createNamespace` | factory | Prefix every bus name, for micro-frontends |
85
+ | `Inspector` | component | Devtools panel; import from `use-everywhere/devtools` |
86
+
87
+ `useSharedState` and the presence hooks are the two most people need. Everything
88
+ in `@use-everywhere/core` is re-exported from here too — see that package's
89
+ `llms.txt` for the framework-free engines.
90
+
91
+ ## Gotchas
92
+
93
+ - **Shared state never crosses origins.** Two origins are two trust domains. For
94
+ that, open a window explicitly with `useOpenedWindow`, which is typed,
95
+ per-message and validated by origin.
96
+ - **Last-writer-wins, per key.** Per-key `[counter, clientId]` clocks give a
97
+ deterministic tie-break, not a merge. Two tabs editing the same key
98
+ concurrently means one of them loses — use `useSharedReducer` when you need the
99
+ operations to compose instead.
100
+ - **The name is the identity.** `useSharedState('count', 0)` in two different
101
+ components is one value. Namespace with `createNamespace` if that is not what
102
+ you want.
103
+ - **SSR is safe.** Hooks render initial values on the server and converge after
104
+ hydration; nothing throws where `BroadcastChannel` is absent.
105
+
106
+ ## Docs
107
+
108
+ - Full documentation: https://rxova.org/packages/use-everywhere/
109
+ - Agent-facing index: https://rxova.org/packages/use-everywhere/llms.txt
110
+ - Every page as raw markdown: add `.md` to any docs URL
111
+ - Hooks reference: https://rxova.org/packages/use-everywhere/hooks/overview.md
112
+ - Error codes: https://rxova.org/packages/use-everywhere/errors.md
113
+ - Source: https://github.com/rxova/use-everywhere
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-everywhere",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
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>",
@@ -9,17 +9,26 @@
9
9
  "url": "git+https://github.com/rxova/use-everywhere.git",
10
10
  "directory": "packages/react"
11
11
  },
12
- "homepage": "https://github.com/rxova/use-everywhere#readme",
12
+ "homepage": "https://rxova.org/packages/use-everywhere/",
13
13
  "bugs": "https://github.com/rxova/use-everywhere/issues",
14
14
  "keywords": [
15
15
  "react",
16
16
  "hooks",
17
+ "react-hooks",
17
18
  "broadcastchannel",
19
+ "broadcast-channel",
18
20
  "cross-tab",
21
+ "multi-tab",
22
+ "tabs",
23
+ "tab-sync",
24
+ "sync",
19
25
  "shared-state",
26
+ "state-management",
20
27
  "postmessage",
21
28
  "cross-origin",
22
- "presence"
29
+ "cross-window",
30
+ "presence",
31
+ "leader-election"
23
32
  ],
24
33
  "publishConfig": {
25
34
  "access": "public"
@@ -75,7 +84,8 @@
75
84
  }
76
85
  },
77
86
  "files": [
78
- "dist"
87
+ "dist",
88
+ "llms.txt"
79
89
  ],
80
90
  "size-limit": [
81
91
  {
@@ -152,7 +162,7 @@
152
162
  }
153
163
  ],
154
164
  "dependencies": {
155
- "@use-everywhere/core": "0.11.0"
165
+ "@use-everywhere/core": "0.11.1"
156
166
  },
157
167
  "peerDependencies": {
158
168
  "react": ">=18",