use-everywhere 0.2.0 → 0.4.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/dist/index.js CHANGED
@@ -1,52 +1,17 @@
1
- // src/use-shared-state.ts
2
- import { useCallback, useSyncExternalStore } from "react";
3
-
4
- // src/registry.ts
1
+ 'use client';
5
2
  import {
6
- createChannel,
7
- createPresence,
8
- createSharedStore,
9
- NoopTransport
10
- } from "@use-everywhere/core";
11
- var DEFAULT_NAME = "use-everywhere";
12
- var stores = /* @__PURE__ */ new Map();
13
- var presences = /* @__PURE__ */ new Map();
14
- var channels = /* @__PURE__ */ new Map();
15
- var scopeOptions = {
16
- everywhere: {},
17
- tabs: { accept: (meta) => meta.kind !== "worker" },
18
- tab: { transport: () => new NoopTransport() }
19
- };
20
- function getSharedStore(name = DEFAULT_NAME, scope = "everywhere") {
21
- return getStore(name, scope);
22
- }
23
- function getStore(name, scope = "everywhere") {
24
- const key = `${scope}\0${name}`;
25
- let store = stores.get(key);
26
- if (!store) {
27
- store = createSharedStore(name, {}, scopeOptions[scope]);
28
- stores.set(key, store);
29
- }
30
- return store;
31
- }
32
- function getPresence(name) {
33
- let presence = presences.get(name);
34
- if (!presence) {
35
- presence = createPresence(name);
36
- presences.set(name, presence);
37
- }
38
- return presence;
39
- }
40
- function getChannel(name) {
41
- let channel = channels.get(name);
42
- if (!channel) {
43
- channel = createChannel(name);
44
- channels.set(name, channel);
45
- }
46
- return channel;
47
- }
3
+ DEFAULT_NAME,
4
+ configureStore,
5
+ getChannel,
6
+ getLeader,
7
+ getSharedStore,
8
+ getStore,
9
+ useClientId,
10
+ usePeers
11
+ } from "./chunk-PNFJW7QK.js";
48
12
 
49
13
  // src/use-shared-state.ts
14
+ import { useCallback, useSyncExternalStore } from "react";
50
15
  function useSharedState(key, initial, options) {
51
16
  const store = getStore(options?.store ?? DEFAULT_NAME, options?.scope ?? "everywhere");
52
17
  store.registerKey(key, initial);
@@ -92,30 +57,64 @@ function defineChannel(name) {
92
57
  };
93
58
  }
94
59
 
95
- // src/use-peers.ts
96
- import { useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
97
- var NO_PEERS = Object.freeze([]);
98
- function usePeers(options) {
99
- const presence = getPresence(options?.name ?? DEFAULT_NAME);
60
+ // src/define-store.ts
61
+ function defineStore(name, options = {}) {
62
+ const scope = options.scope ?? "everywhere";
63
+ if (options.persist) {
64
+ configureStore(name, scope, {
65
+ persist: {
66
+ adapter: options.persist,
67
+ ...options.persistKeys ? { keys: options.persistKeys } : {},
68
+ ...options.persistDebounceMs === void 0 ? {} : { debounceMs: options.persistDebounceMs }
69
+ }
70
+ });
71
+ }
72
+ return {
73
+ get: () => getStore(name, scope),
74
+ useSharedState: (key, initial) => useSharedState(key, initial, { store: name, scope })
75
+ };
76
+ }
77
+
78
+ // src/use-leader.ts
79
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
80
+ var NO_LEADER = Object.freeze({ leaderId: null, isLeader: false });
81
+ function useLeader(options) {
82
+ const leader = getLeader(options?.name ?? DEFAULT_NAME, options);
83
+ const eligible = options?.eligible;
84
+ useEffect2(() => {
85
+ if (eligible === void 0) return;
86
+ leader.setEligible(eligible);
87
+ }, [leader, eligible]);
100
88
  return useSyncExternalStore2(
101
- useCallback2((onChange) => presence.subscribe(onChange), [presence]),
102
- () => presence.getPeers(),
103
- () => NO_PEERS
89
+ useCallback2((onChange) => leader.subscribe(onChange), [leader]),
90
+ () => leader.getSnapshot(),
91
+ () => NO_LEADER
104
92
  );
105
93
  }
106
- function useClientId(options) {
107
- return getPresence(options?.name ?? DEFAULT_NAME).clientId;
94
+ function useIsLeader(options) {
95
+ return useLeader(options).isLeader;
96
+ }
97
+ function useLeaderEffect(effect, options) {
98
+ const { isLeader } = useLeader(options);
99
+ const effectRef = useRef2(effect);
100
+ useEffect2(() => {
101
+ effectRef.current = effect;
102
+ });
103
+ useEffect2(() => {
104
+ if (!isLeader) return;
105
+ return effectRef.current();
106
+ }, [isLeader]);
108
107
  }
109
108
 
110
109
  // src/use-opened-window.ts
111
- import { useCallback as useCallback3, useRef as useRef2, useState } from "react";
110
+ import { useCallback as useCallback3, useRef as useRef3, useState } from "react";
112
111
  import { WindowClosedError } from "@use-everywhere/core";
113
112
  function useOpenedWindow(factory) {
114
113
  const [status, setStatus] = useState("idle");
115
114
  const [result, setResult] = useState(void 0);
116
115
  const [error, setError] = useState(void 0);
117
- const current = useRef2(null);
118
- const factoryRef = useRef2(factory);
116
+ const current = useRef3(null);
117
+ const factoryRef = useRef3(factory);
119
118
  factoryRef.current = factory;
120
119
  const open = useCallback3(() => {
121
120
  current.current?.close();
@@ -165,9 +164,14 @@ export * from "@use-everywhere/core";
165
164
  export {
166
165
  DEFAULT_NAME,
167
166
  defineChannel,
167
+ defineStore,
168
+ getLeader,
168
169
  getSharedStore,
169
170
  useChannel,
170
171
  useClientId,
172
+ useIsLeader,
173
+ useLeader,
174
+ useLeaderEffect,
171
175
  useMessage,
172
176
  useOpenedWindow,
173
177
  usePeers,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-everywhere",
3
- "version": "0.2.0",
3
+ "version": "0.4.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>",
@@ -26,12 +26,29 @@
26
26
  },
27
27
  "type": "module",
28
28
  "sideEffects": false,
29
- "main": "./dist/index.js",
29
+ "main": "./dist/index.cjs",
30
+ "module": "./dist/index.js",
30
31
  "types": "./dist/index.d.ts",
31
32
  "exports": {
32
33
  ".": {
33
- "types": "./dist/index.d.ts",
34
- "import": "./dist/index.js"
34
+ "import": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ },
38
+ "require": {
39
+ "types": "./dist/index.d.cts",
40
+ "default": "./dist/index.cjs"
41
+ }
42
+ },
43
+ "./devtools": {
44
+ "import": {
45
+ "types": "./dist/devtools/index.d.ts",
46
+ "default": "./dist/devtools/index.js"
47
+ },
48
+ "require": {
49
+ "types": "./dist/devtools/index.d.cts",
50
+ "default": "./dist/devtools/index.cjs"
51
+ }
35
52
  }
36
53
  },
37
54
  "files": [
@@ -42,13 +59,13 @@
42
59
  "name": "everything (import *)",
43
60
  "path": "dist/index.js",
44
61
  "import": "*",
45
- "limit": "4.2 kB"
62
+ "limit": "5.4 kB"
46
63
  },
47
64
  {
48
65
  "name": "useSharedState",
49
66
  "path": "dist/index.js",
50
67
  "import": "{ useSharedState }",
51
- "limit": "1.5 kB"
68
+ "limit": "1.8 kB"
52
69
  },
53
70
  {
54
71
  "name": "useChannel + useMessage + useSend",
@@ -67,28 +84,53 @@
67
84
  "path": "dist/index.js",
68
85
  "import": "{ useOpenedWindow, openWindow }",
69
86
  "limit": "1.4 kB"
87
+ },
88
+ {
89
+ "name": "useLeader + useLeaderEffect",
90
+ "path": "dist/index.js",
91
+ "import": "{ useLeader, useLeaderEffect }",
92
+ "limit": "1.8 kB"
93
+ },
94
+ {
95
+ "name": "defineStore (persisted)",
96
+ "path": "dist/index.js",
97
+ "import": "{ defineStore, localStorageAdapter }",
98
+ "limit": "2.3 kB"
99
+ },
100
+ {
101
+ "name": "Inspector (devtools subpath)",
102
+ "path": "dist/devtools/index.js",
103
+ "import": "{ Inspector }",
104
+ "limit": "5 kB"
70
105
  }
71
106
  ],
72
107
  "dependencies": {
73
- "@use-everywhere/core": "0.2.0"
108
+ "@use-everywhere/core": "0.4.0"
74
109
  },
75
110
  "peerDependencies": {
76
111
  "react": ">=18"
77
112
  },
78
113
  "devDependencies": {
79
- "@size-limit/preset-small-lib": "^12.1.0",
80
- "@testing-library/react": "^16.3.0",
81
- "@types/react": "^19.1.8",
114
+ "@size-limit/preset-small-lib": "^13.0.1",
115
+ "@testing-library/react": "^16.3.2",
116
+ "@types/react": "^19.2.17",
82
117
  "@types/react-dom": "^19.2.3",
83
118
  "@vitest/coverage-v8": "^4.1.10",
84
- "happy-dom": "^20.10.6",
85
- "react": "^19.1.0",
86
- "react-dom": "^19.1.0",
87
- "size-limit": "^12.1.0",
88
- "tsup": "^8.5.0",
89
- "typescript": "^5.8.3",
119
+ "happy-dom": "^20.11.1",
120
+ "react": "^19.2.8",
121
+ "react-dom": "^19.2.8",
122
+ "size-limit": "^13.0.1",
123
+ "tsup": "^8.5.1",
124
+ "typescript": "^6.0.3",
90
125
  "vitest": "^4.1.10"
91
126
  },
127
+ "typesVersions": {
128
+ "*": {
129
+ "devtools": [
130
+ "./dist/devtools/index.d.ts"
131
+ ]
132
+ }
133
+ },
92
134
  "scripts": {
93
135
  "build": "tsup",
94
136
  "test": "vitest run --coverage",