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.
- package/README.md +74 -11
- package/dist/{chunk-42VOZR6E.js → chunk-4JDWAUYM.js} +216 -93
- package/dist/{chunk-BQCNBNBT.cjs → chunk-TGEXRVAL.cjs} +219 -92
- package/dist/index.cjs +41 -25
- package/dist/index.d.cts +110 -5
- package/dist/index.d.ts +110 -5
- package/dist/index.js +2 -2
- package/dist/{types-BtK4ixKz.d.cts → instance-5LIItazN.d.cts} +58 -80
- package/dist/{types-BtK4ixKz.d.ts → instance-5LIItazN.d.ts} +58 -80
- package/dist/react/index.cjs +82 -9
- package/dist/react/index.d.cts +47 -2
- package/dist/react/index.d.ts +47 -2
- package/dist/react/index.js +79 -9
- package/package.json +5 -4
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createTabSync } from '../chunk-
|
|
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.
|
|
129
|
-
|
|
130
|
-
|
|
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.
|
|
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-
|
|
65
|
+
"url": "git+https://github.com/serbi2012/tab-bridge.git"
|
|
66
66
|
},
|
|
67
|
-
"homepage": "https://github.com/serbi2012/tab-
|
|
67
|
+
"homepage": "https://github.com/serbi2012/tab-bridge#readme",
|
|
68
68
|
"bugs": {
|
|
69
|
-
"url": "https://github.com/serbi2012/tab-
|
|
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",
|