tab-bridge 0.1.1 → 0.2.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.
@@ -1,5 +1,5 @@
1
- import { createTabSync } from '../chunk-42VOZR6E.js';
2
- import { createContext, useRef, useEffect, useCallback, useSyncExternalStore, useContext, useState } from 'react';
1
+ import { createTabSync } from '../chunk-4JDWAUYM.js';
2
+ import { createContext, useRef, useEffect, useCallback, useSyncExternalStore, useContext, useMemo, useState } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
5
5
  var TabSyncContext = createContext(null);
@@ -125,14 +125,14 @@ function useTabSyncSelector(selector, isEqual) {
125
125
  initializedRef.current = true;
126
126
  }
127
127
  const subscribe = useCallback(
128
- (onStoreChange) => instance.onChange(() => {
129
- const next = selectorRef.current(instance.getAll());
130
- const equal = isEqualRef.current ?? Object.is;
131
- if (!equal(resultRef.current, next)) {
128
+ (onStoreChange) => instance.select(
129
+ (state) => selectorRef.current(state),
130
+ (next) => {
132
131
  resultRef.current = next;
133
132
  onStoreChange();
134
- }
135
- }),
133
+ },
134
+ { isEqual: isEqualRef.current }
135
+ ),
136
136
  [instance]
137
137
  );
138
138
  const getSnapshot = useCallback(() => resultRef.current, []);
@@ -163,5 +163,75 @@ function useIsLeader() {
163
163
  const getServerSnapshot = useCallback(() => SERVER_SNAPSHOT, []);
164
164
  return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
165
165
  }
166
+ var SERVER_SNAPSHOT2 = [];
167
+ function useTabs() {
168
+ const instance = useContext(TabSyncContext);
169
+ if (!instance) {
170
+ throw new Error("useTabs must be used within a <TabSyncProvider>");
171
+ }
172
+ const tabsRef = useRef(instance.getTabs());
173
+ const subscribe = useCallback(
174
+ (onStoreChange) => instance.onTabChange((tabs) => {
175
+ tabsRef.current = tabs;
176
+ onStoreChange();
177
+ }),
178
+ [instance]
179
+ );
180
+ const getSnapshot = useCallback(() => tabsRef.current, []);
181
+ const getServerSnapshot = useCallback(() => SERVER_SNAPSHOT2, []);
182
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
183
+ }
184
+ function useLeaderInfo() {
185
+ const instance = useContext(TabSyncContext);
186
+ if (!instance) {
187
+ throw new Error("useLeaderInfo must be used within a <TabSyncProvider>");
188
+ }
189
+ const leaderRef = useRef(instance.getLeader());
190
+ const subscribe = useCallback(
191
+ (onStoreChange) => {
192
+ const unsubs = [];
193
+ unsubs.push(
194
+ instance.onTabChange(() => {
195
+ const next = instance.getLeader();
196
+ if (next?.id !== leaderRef.current?.id) {
197
+ leaderRef.current = next;
198
+ onStoreChange();
199
+ }
200
+ })
201
+ );
202
+ unsubs.push(
203
+ instance.onLeader(() => {
204
+ leaderRef.current = instance.getLeader();
205
+ onStoreChange();
206
+ return () => {
207
+ leaderRef.current = instance.getLeader();
208
+ onStoreChange();
209
+ };
210
+ })
211
+ );
212
+ return () => {
213
+ for (const u of unsubs) u();
214
+ };
215
+ },
216
+ [instance]
217
+ );
218
+ const getSnapshot = useCallback(() => leaderRef.current, []);
219
+ const getServerSnapshot = useCallback(() => null, []);
220
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
221
+ }
222
+ function useTabSyncActions() {
223
+ const instance = useContext(TabSyncContext);
224
+ if (!instance) {
225
+ throw new Error("useTabSyncActions must be used within a <TabSyncProvider>");
226
+ }
227
+ return useMemo(
228
+ () => ({
229
+ set: instance.set.bind(instance),
230
+ patch: instance.patch.bind(instance),
231
+ transaction: instance.transaction.bind(instance)
232
+ }),
233
+ [instance]
234
+ );
235
+ }
166
236
 
167
- export { TabSyncContext, TabSyncProvider, useIsLeader, useTabSync, useTabSyncSelector, useTabSyncValue };
237
+ export { TabSyncContext, TabSyncProvider, useIsLeader, useLeaderInfo, useTabSync, useTabSyncActions, useTabSyncSelector, useTabSyncValue, useTabs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tab-bridge",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Zero-dependency TypeScript library for real-time state synchronization across browser tabs, with leader election and cross-tab RPC",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -62,11 +62,11 @@
62
62
  "license": "MIT",
63
63
  "repository": {
64
64
  "type": "git",
65
- "url": "git+https://github.com/serbi2012/tab-sync.git"
65
+ "url": "git+https://github.com/serbi2012/tab-bridge.git"
66
66
  },
67
- "homepage": "https://github.com/serbi2012/tab-sync#readme",
67
+ "homepage": "https://github.com/serbi2012/tab-bridge#readme",
68
68
  "bugs": {
69
- "url": "https://github.com/serbi2012/tab-sync/issues"
69
+ "url": "https://github.com/serbi2012/tab-bridge/issues"
70
70
  },
71
71
  "sideEffects": false,
72
72
  "peerDependencies": {
@@ -80,6 +80,7 @@
80
80
  "devDependencies": {
81
81
  "@types/react": "^19.2.14",
82
82
  "@types/react-dom": "^19.2.3",
83
+ "@vitest/coverage-v8": "^2.1.9",
83
84
  "jsdom": "^25.0.1",
84
85
  "react": "^19.2.4",
85
86
  "react-dom": "^19.2.4",