use-everywhere 0.8.0 → 0.10.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 +2 -2
- package/dist/{chunk-75TICQ7E.js → chunk-R7PBPLF7.js} +19 -8
- package/dist/devtools/index.cjs +304 -84
- package/dist/devtools/index.d.cts +13 -2
- package/dist/devtools/index.d.ts +13 -2
- package/dist/devtools/index.js +305 -87
- package/dist/index.cjs +23 -8
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -2
- package/dist/shared-worker.cjs +31 -0
- package/dist/shared-worker.d.cts +2 -0
- package/dist/shared-worker.d.ts +2 -0
- package/dist/shared-worker.js +7 -0
- package/package.json +33 -5
package/README.md
CHANGED
|
@@ -142,13 +142,13 @@ per-connection nonce, and source window.
|
|
|
142
142
|
- Values must survive structured clone (no functions, DOM nodes); state lives
|
|
143
143
|
as long as at least one context holds it — nothing is persisted.
|
|
144
144
|
- Testing is first-class: inject a `MemoryHub` transport to simulate many tabs
|
|
145
|
-
in one test. See the [testing guide](https://rxova.
|
|
145
|
+
in one test. See the [testing guide](https://rxova.org/packages/use-everywhere/guides/testing).
|
|
146
146
|
|
|
147
147
|
This package re-exports the full framework-agnostic surface of
|
|
148
148
|
[`@use-everywhere/core`](https://www.npmjs.com/package/@use-everywhere/core),
|
|
149
149
|
so you never need to install core directly.
|
|
150
150
|
|
|
151
|
-
📖 **[Documentation](https://rxova.
|
|
151
|
+
📖 **[Documentation](https://rxova.org/packages/use-everywhere/)** — mental
|
|
152
152
|
model, how sync works, security model, recipes, and generated API reference.
|
|
153
153
|
Source and demo app: [github.com/rxova/use-everywhere](https://github.com/rxova/use-everywhere)
|
|
154
154
|
|
|
@@ -18,10 +18,17 @@ try {
|
|
|
18
18
|
} catch {
|
|
19
19
|
}
|
|
20
20
|
var warned = /* @__PURE__ */ new Set();
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
var DOCS = "https://rxova.org/packages/use-everywhere/errors";
|
|
22
|
+
function diagnostic(code, message) {
|
|
23
|
+
return `[use-everywhere] ${code}: ${message}
|
|
24
|
+
\u2192 ${DOCS}/#${code.toLowerCase()}`;
|
|
25
|
+
}
|
|
26
|
+
function devWarn(code, message) {
|
|
27
|
+
if (!inDev) return;
|
|
28
|
+
const line = diagnostic(code, message);
|
|
29
|
+
if (warned.has(line)) return;
|
|
30
|
+
warned.add(line);
|
|
31
|
+
console.warn(line);
|
|
25
32
|
}
|
|
26
33
|
var seenInitials = /* @__PURE__ */ new Map();
|
|
27
34
|
function warnOnInitialMismatch(storeName, key, initial) {
|
|
@@ -35,7 +42,8 @@ function warnOnInitialMismatch(storeName, key, initial) {
|
|
|
35
42
|
const comparable = (v) => v === null || typeof v !== "object";
|
|
36
43
|
if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
|
|
37
44
|
devWarn(
|
|
38
|
-
|
|
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.`
|
|
39
47
|
);
|
|
40
48
|
}
|
|
41
49
|
}
|
|
@@ -118,7 +126,8 @@ function configureStore(name, scope, options) {
|
|
|
118
126
|
if (configSignature(storeConfig.get(key)) === configSignature(options)) return;
|
|
119
127
|
if (process.env.NODE_ENV !== "production") {
|
|
120
128
|
devWarn(
|
|
121
|
-
|
|
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.`
|
|
122
131
|
);
|
|
123
132
|
}
|
|
124
133
|
return;
|
|
@@ -162,7 +171,8 @@ function warnOnLeaderOptionConflict(name, options) {
|
|
|
162
171
|
if (requested !== void 0 && requested !== first?.[key]) {
|
|
163
172
|
if (process.env.NODE_ENV !== "production") {
|
|
164
173
|
devWarn(
|
|
165
|
-
|
|
174
|
+
"UE2003",
|
|
175
|
+
`leader "${name}": ${key} ignored \u2014 the first useLeader/getLeader call fixes the election timings for this tab.`
|
|
166
176
|
);
|
|
167
177
|
}
|
|
168
178
|
}
|
|
@@ -176,7 +186,8 @@ function configureChannel(name, options) {
|
|
|
176
186
|
if (before.join() === after.join()) return;
|
|
177
187
|
if (process.env.NODE_ENV !== "production") {
|
|
178
188
|
devWarn(
|
|
179
|
-
|
|
189
|
+
"UE2004",
|
|
190
|
+
`defineChannel('${name}') ran after that channel was already created, with different options. The live channel keeps the configuration it was built with. Move defineChannel to module scope, before any component sends or receives on it.`
|
|
180
191
|
);
|
|
181
192
|
}
|
|
182
193
|
return;
|
package/dist/devtools/index.cjs
CHANGED
|
@@ -26,6 +26,11 @@ __export(devtools_exports, {
|
|
|
26
26
|
module.exports = __toCommonJS(devtools_exports);
|
|
27
27
|
|
|
28
28
|
// src/devtools/inspector.tsx
|
|
29
|
+
var import_react3 = require("react");
|
|
30
|
+
var import_react_dom = require("react-dom");
|
|
31
|
+
var import_core3 = require("@use-everywhere/core");
|
|
32
|
+
|
|
33
|
+
// src/devtools/panel.tsx
|
|
29
34
|
var import_react2 = require("react");
|
|
30
35
|
var import_core2 = require("@use-everywhere/core");
|
|
31
36
|
|
|
@@ -113,85 +118,34 @@ function usePeers(options) {
|
|
|
113
118
|
);
|
|
114
119
|
}
|
|
115
120
|
|
|
116
|
-
// src/devtools/
|
|
117
|
-
var STYLES = `
|
|
118
|
-
.ue-ins {
|
|
119
|
-
position: fixed;
|
|
120
|
-
z-index: 2147483000;
|
|
121
|
-
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
122
|
-
color: #e6edf3;
|
|
123
|
-
background: #0d1117;
|
|
124
|
-
border: 1px solid #30363d;
|
|
125
|
-
border-radius: 8px;
|
|
126
|
-
box-shadow: 0 8px 32px rgb(0 0 0 / 0.4);
|
|
127
|
-
max-width: min(420px, calc(100vw - 24px));
|
|
128
|
-
overflow: hidden;
|
|
129
|
-
}
|
|
130
|
-
.ue-ins--bottom-right { bottom: 12px; right: 12px; }
|
|
131
|
-
.ue-ins--bottom-left { bottom: 12px; left: 12px; }
|
|
132
|
-
.ue-ins--top-right { top: 12px; right: 12px; }
|
|
133
|
-
.ue-ins--top-left { top: 12px; left: 12px; }
|
|
134
|
-
|
|
135
|
-
.ue-ins__bar {
|
|
136
|
-
display: flex;
|
|
137
|
-
align-items: center;
|
|
138
|
-
gap: 8px;
|
|
139
|
-
width: 100%;
|
|
140
|
-
padding: 7px 10px;
|
|
141
|
-
background: #161b22;
|
|
142
|
-
border: 0;
|
|
143
|
-
color: inherit;
|
|
144
|
-
font: inherit;
|
|
145
|
-
cursor: pointer;
|
|
146
|
-
text-align: left;
|
|
147
|
-
}
|
|
148
|
-
.ue-ins__dot { width: 7px; height: 7px; border-radius: 50%; background: #3fb950; flex: none; }
|
|
149
|
-
.ue-ins__title { font-weight: 600; }
|
|
150
|
-
.ue-ins__muted { color: #8b949e; }
|
|
151
|
-
.ue-ins__crown { margin-left: auto; color: #d29922; }
|
|
152
|
-
|
|
153
|
-
.ue-ins__body { max-height: 60vh; overflow-y: auto; }
|
|
154
|
-
.ue-ins__section { border-top: 1px solid #21262d; padding: 8px 10px; }
|
|
155
|
-
.ue-ins__h {
|
|
156
|
-
color: #8b949e;
|
|
157
|
-
text-transform: uppercase;
|
|
158
|
-
letter-spacing: 0.06em;
|
|
159
|
-
font-size: 10px;
|
|
160
|
-
margin-bottom: 5px;
|
|
161
|
-
}
|
|
162
|
-
.ue-ins__row { display: flex; gap: 8px; padding: 1px 0; }
|
|
163
|
-
.ue-ins__k { color: #79c0ff; flex: none; }
|
|
164
|
-
.ue-ins__v { color: #e6edf3; overflow-wrap: anywhere; }
|
|
165
|
-
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
166
|
-
.ue-ins__empty { color: #6e7681; }
|
|
167
|
-
|
|
168
|
-
.ue-ins__log { display: flex; flex-direction: column-reverse; max-height: 190px; overflow-y: auto; }
|
|
169
|
-
.ue-ins__wire { display: flex; gap: 7px; padding: 1px 0; white-space: nowrap; }
|
|
170
|
-
.ue-ins__dir { flex: none; width: 9px; }
|
|
171
|
-
.ue-ins__dir--out { color: #d29922; }
|
|
172
|
-
.ue-ins__dir--in { color: #3fb950; }
|
|
173
|
-
.ue-ins__scope { color: #e6edf3; }
|
|
174
|
-
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
175
|
-
`;
|
|
176
|
-
|
|
177
|
-
// src/devtools/inspector.tsx
|
|
121
|
+
// src/devtools/panel.tsx
|
|
178
122
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
179
123
|
var short = (id) => id.slice(0, 6);
|
|
180
124
|
function wireLabel(wire) {
|
|
181
125
|
return `${wire.scope}/${wire.type}`;
|
|
182
126
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
limit
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
127
|
+
var SCOPES = ["all", "state", "leader", "presence", "channel"];
|
|
128
|
+
function Panel({
|
|
129
|
+
name,
|
|
130
|
+
limit,
|
|
131
|
+
leaseMs,
|
|
132
|
+
position,
|
|
133
|
+
defaultOpen
|
|
134
|
+
}) {
|
|
190
135
|
const [open, setOpen] = (0, import_react2.useState)(defaultOpen);
|
|
191
136
|
const [wires, setWires] = (0, import_react2.useState)([]);
|
|
192
137
|
const [crown, setCrown] = (0, import_react2.useState)(null);
|
|
138
|
+
const [paused, setPaused] = (0, import_react2.useState)(false);
|
|
139
|
+
const [filter, setFilter] = (0, import_react2.useState)("");
|
|
140
|
+
const [scopeView, setScopeView] = (0, import_react2.useState)("all");
|
|
141
|
+
const [editing, setEditing] = (0, import_react2.useState)(null);
|
|
142
|
+
const [frames, setFrames] = (0, import_react2.useState)([]);
|
|
193
143
|
const nextId = (0, import_react2.useRef)(0);
|
|
194
144
|
const crownAt = (0, import_react2.useRef)(0);
|
|
145
|
+
const pausedRef = (0, import_react2.useRef)(false);
|
|
146
|
+
(0, import_react2.useEffect)(() => {
|
|
147
|
+
pausedRef.current = paused;
|
|
148
|
+
}, [paused]);
|
|
195
149
|
const peers = usePeers({ name });
|
|
196
150
|
const store = getSharedStore(name);
|
|
197
151
|
const subscribe = (0, import_react2.useCallback)((onChange) => store.subscribe(onChange), [store]);
|
|
@@ -217,19 +171,22 @@ function Inspector({
|
|
|
217
171
|
crownAt.current = Date.now();
|
|
218
172
|
}
|
|
219
173
|
}
|
|
174
|
+
if (pausedRef.current) return;
|
|
175
|
+
const id = nextId.current++;
|
|
176
|
+
const label = wireLabel(wire);
|
|
220
177
|
setWires(
|
|
221
178
|
(prev) => [
|
|
222
179
|
...prev.slice(-(limit - 1)),
|
|
223
|
-
{
|
|
224
|
-
id: nextId.current++,
|
|
225
|
-
direction,
|
|
226
|
-
label: wireLabel(wire),
|
|
227
|
-
from: short(wire.clientId)
|
|
228
|
-
}
|
|
180
|
+
{ id, direction, scope: wire.scope, label, from: short(wire.clientId) }
|
|
229
181
|
].slice(-limit)
|
|
230
182
|
);
|
|
183
|
+
if (wire.scope === "state") {
|
|
184
|
+
setFrames(
|
|
185
|
+
(prev) => [...prev, { wireId: id, label, snapshot: { ...store.getSnapshot() } }].slice(-limit)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
231
188
|
});
|
|
232
|
-
}, [name, limit]);
|
|
189
|
+
}, [name, limit, store]);
|
|
233
190
|
(0, import_react2.useEffect)(() => {
|
|
234
191
|
const timer = setInterval(
|
|
235
192
|
() => {
|
|
@@ -238,17 +195,43 @@ function Inspector({
|
|
|
238
195
|
crownAt.current = 0;
|
|
239
196
|
}
|
|
240
197
|
},
|
|
241
|
-
// Quarter of the lease, so a vacated crown clears well within it. The
|
|
242
|
-
// floor is low enough that a short lease still works rather than being
|
|
243
|
-
// silently rounded up to something coarser than the lease itself.
|
|
244
198
|
Math.max(50, Math.floor(leaseMs / 4))
|
|
245
199
|
);
|
|
246
200
|
return () => clearInterval(timer);
|
|
247
201
|
}, [leaseMs]);
|
|
248
202
|
const selfId = store.clientId;
|
|
249
203
|
const entries = Object.entries(versions);
|
|
204
|
+
const needle = filter.trim().toLowerCase();
|
|
205
|
+
const shown = wires.filter((wire) => {
|
|
206
|
+
if (scopeView !== "all" && wire.scope !== scopeView) return false;
|
|
207
|
+
if (!needle) return true;
|
|
208
|
+
return wire.label.toLowerCase().includes(needle) || wire.from.toLowerCase().includes(needle);
|
|
209
|
+
});
|
|
210
|
+
const commit = (key, draft) => {
|
|
211
|
+
let value;
|
|
212
|
+
try {
|
|
213
|
+
value = JSON.parse(draft);
|
|
214
|
+
} catch {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
store.set(key, value);
|
|
218
|
+
setEditing(null);
|
|
219
|
+
};
|
|
220
|
+
const draftIsValid = (draft) => {
|
|
221
|
+
try {
|
|
222
|
+
JSON.parse(draft);
|
|
223
|
+
return true;
|
|
224
|
+
} catch {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
const restore = (frame) => {
|
|
229
|
+
for (const [key, value] of Object.entries(frame.snapshot)) {
|
|
230
|
+
if (Object.is(store.getSnapshot()[key], value)) continue;
|
|
231
|
+
store.set(key, value);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
250
234
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `ue-ins ue-ins--${position}`, "data-testid": "ue-inspector", children: [
|
|
251
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: STYLES }),
|
|
252
235
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
253
236
|
"button",
|
|
254
237
|
{
|
|
@@ -294,7 +277,31 @@ function Inspector({
|
|
|
294
277
|
] }),
|
|
295
278
|
entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__empty", children: "no keys yet" }) : entries.map(([key, version]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__row", children: [
|
|
296
279
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__k", children: key }),
|
|
297
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
280
|
+
editing?.key === key ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
281
|
+
"input",
|
|
282
|
+
{
|
|
283
|
+
className: `ue-ins__edit${draftIsValid(editing.draft) ? "" : " ue-ins__v--invalid"}`,
|
|
284
|
+
value: editing.draft,
|
|
285
|
+
autoFocus: true,
|
|
286
|
+
"aria-label": `Value of ${key}`,
|
|
287
|
+
onChange: (event) => setEditing({ key, draft: event.target.value }),
|
|
288
|
+
onKeyDown: (event) => {
|
|
289
|
+
if (event.key === "Enter") commit(key, editing.draft);
|
|
290
|
+
if (event.key === "Escape") setEditing(null);
|
|
291
|
+
},
|
|
292
|
+
onBlur: () => setEditing(null),
|
|
293
|
+
"data-testid": `ue-edit-${key}`
|
|
294
|
+
}
|
|
295
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
296
|
+
"button",
|
|
297
|
+
{
|
|
298
|
+
type: "button",
|
|
299
|
+
className: "ue-ins__v ue-ins__v--editable",
|
|
300
|
+
onClick: () => setEditing({ key, draft: JSON.stringify(snapshot[key]) ?? "" }),
|
|
301
|
+
"data-testid": `ue-value-${key}`,
|
|
302
|
+
children: JSON.stringify(snapshot[key])
|
|
303
|
+
}
|
|
304
|
+
),
|
|
298
305
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ue-ins__ver", children: [
|
|
299
306
|
version[0],
|
|
300
307
|
"\xB7",
|
|
@@ -305,18 +312,231 @@ function Inspector({
|
|
|
305
312
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__section", children: [
|
|
306
313
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__h", children: [
|
|
307
314
|
"Wires (",
|
|
308
|
-
|
|
309
|
-
"
|
|
315
|
+
shown.length,
|
|
316
|
+
shown.length === wires.length ? "" : ` of ${wires.length}`,
|
|
317
|
+
")",
|
|
318
|
+
paused ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__paused", children: " \xB7 paused" }) : null
|
|
319
|
+
] }),
|
|
320
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__tools", children: [
|
|
321
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
322
|
+
"button",
|
|
323
|
+
{
|
|
324
|
+
type: "button",
|
|
325
|
+
className: "ue-ins__btn",
|
|
326
|
+
"aria-pressed": paused,
|
|
327
|
+
onClick: () => setPaused((value) => !value),
|
|
328
|
+
"data-testid": "ue-pause",
|
|
329
|
+
children: paused ? "resume" : "pause"
|
|
330
|
+
}
|
|
331
|
+
),
|
|
332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
333
|
+
"button",
|
|
334
|
+
{
|
|
335
|
+
type: "button",
|
|
336
|
+
className: "ue-ins__btn",
|
|
337
|
+
onClick: () => {
|
|
338
|
+
setWires([]);
|
|
339
|
+
setFrames([]);
|
|
340
|
+
},
|
|
341
|
+
"data-testid": "ue-clear",
|
|
342
|
+
children: "clear"
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
346
|
+
"input",
|
|
347
|
+
{
|
|
348
|
+
className: "ue-ins__filter",
|
|
349
|
+
value: filter,
|
|
350
|
+
placeholder: "filter",
|
|
351
|
+
"aria-label": "Filter wires",
|
|
352
|
+
onChange: (event) => setFilter(event.target.value),
|
|
353
|
+
"data-testid": "ue-filter"
|
|
354
|
+
}
|
|
355
|
+
)
|
|
310
356
|
] }),
|
|
311
|
-
|
|
357
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__tools", role: "group", "aria-label": "Scope", children: SCOPES.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
358
|
+
"button",
|
|
359
|
+
{
|
|
360
|
+
type: "button",
|
|
361
|
+
className: "ue-ins__btn",
|
|
362
|
+
"aria-pressed": scopeView === scope,
|
|
363
|
+
onClick: () => setScopeView(scope),
|
|
364
|
+
"data-testid": `ue-scope-${scope}`,
|
|
365
|
+
children: scope
|
|
366
|
+
},
|
|
367
|
+
scope
|
|
368
|
+
)) }),
|
|
369
|
+
shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__empty", "data-testid": "ue-wires", children: wires.length === 0 ? "nothing yet" : "no matches" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__log", "data-testid": "ue-wires", children: shown.map((wire) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__wire", children: [
|
|
312
370
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `ue-ins__dir ue-ins__dir--${wire.direction}`, children: wire.direction === "out" ? "\u2192" : "\u2190" }),
|
|
313
371
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__scope", children: wire.label }),
|
|
314
372
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__from", children: wire.from })
|
|
315
373
|
] }, wire.id)) })
|
|
374
|
+
] }),
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__section", children: [
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__h", children: [
|
|
377
|
+
"Timeline (",
|
|
378
|
+
frames.length,
|
|
379
|
+
")"
|
|
380
|
+
] }),
|
|
381
|
+
frames.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__empty", children: "no state on the wire yet" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__log", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__wire", children: [
|
|
382
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
383
|
+
"button",
|
|
384
|
+
{
|
|
385
|
+
type: "button",
|
|
386
|
+
className: "ue-ins__btn",
|
|
387
|
+
onClick: () => restore(frame),
|
|
388
|
+
"data-testid": `ue-restore-${String(frame.wireId)}`,
|
|
389
|
+
children: "restore"
|
|
390
|
+
}
|
|
391
|
+
),
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__scope", children: frame.label }),
|
|
393
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ue-ins__from", children: [
|
|
394
|
+
Object.keys(frame.snapshot).length,
|
|
395
|
+
" key",
|
|
396
|
+
Object.keys(frame.snapshot).length === 1 ? "" : "s"
|
|
397
|
+
] })
|
|
398
|
+
] }, frame.wireId)) })
|
|
316
399
|
] })
|
|
317
400
|
] }) : null
|
|
318
401
|
] });
|
|
319
402
|
}
|
|
403
|
+
|
|
404
|
+
// src/devtools/styles.ts
|
|
405
|
+
var STYLES = `
|
|
406
|
+
.ue-ins {
|
|
407
|
+
position: fixed;
|
|
408
|
+
z-index: 2147483000;
|
|
409
|
+
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
410
|
+
color: #e6edf3;
|
|
411
|
+
background: #0d1117;
|
|
412
|
+
border: 1px solid #30363d;
|
|
413
|
+
border-radius: 8px;
|
|
414
|
+
box-shadow: 0 8px 32px rgb(0 0 0 / 0.4);
|
|
415
|
+
max-width: min(420px, calc(100vw - 24px));
|
|
416
|
+
overflow: hidden;
|
|
417
|
+
}
|
|
418
|
+
.ue-ins--bottom-right { bottom: 12px; right: 12px; }
|
|
419
|
+
.ue-ins--bottom-left { bottom: 12px; left: 12px; }
|
|
420
|
+
.ue-ins--top-right { top: 12px; right: 12px; }
|
|
421
|
+
.ue-ins--top-left { top: 12px; left: 12px; }
|
|
422
|
+
|
|
423
|
+
.ue-ins__bar {
|
|
424
|
+
display: flex;
|
|
425
|
+
align-items: center;
|
|
426
|
+
gap: 8px;
|
|
427
|
+
width: 100%;
|
|
428
|
+
padding: 7px 10px;
|
|
429
|
+
background: #161b22;
|
|
430
|
+
border: 0;
|
|
431
|
+
color: inherit;
|
|
432
|
+
font: inherit;
|
|
433
|
+
cursor: pointer;
|
|
434
|
+
text-align: left;
|
|
435
|
+
}
|
|
436
|
+
.ue-ins__dot { width: 7px; height: 7px; border-radius: 50%; background: #3fb950; flex: none; }
|
|
437
|
+
.ue-ins__title { font-weight: 600; }
|
|
438
|
+
.ue-ins__muted { color: #8b949e; }
|
|
439
|
+
.ue-ins__crown { margin-left: auto; color: #d29922; }
|
|
440
|
+
|
|
441
|
+
.ue-ins__body { max-height: 60vh; overflow-y: auto; }
|
|
442
|
+
.ue-ins__section { border-top: 1px solid #21262d; padding: 8px 10px; }
|
|
443
|
+
.ue-ins__h {
|
|
444
|
+
color: #8b949e;
|
|
445
|
+
text-transform: uppercase;
|
|
446
|
+
letter-spacing: 0.06em;
|
|
447
|
+
font-size: 10px;
|
|
448
|
+
margin-bottom: 5px;
|
|
449
|
+
}
|
|
450
|
+
.ue-ins__row { display: flex; gap: 8px; padding: 1px 0; }
|
|
451
|
+
.ue-ins__k { color: #79c0ff; flex: none; }
|
|
452
|
+
.ue-ins__v { color: #e6edf3; overflow-wrap: anywhere; }
|
|
453
|
+
button.ue-ins__v {
|
|
454
|
+
background: none;
|
|
455
|
+
border: 0;
|
|
456
|
+
padding: 0;
|
|
457
|
+
font: inherit;
|
|
458
|
+
text-align: left;
|
|
459
|
+
}
|
|
460
|
+
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
461
|
+
.ue-ins__empty { color: #6e7681; }
|
|
462
|
+
|
|
463
|
+
.ue-ins__log { display: flex; flex-direction: column-reverse; max-height: 190px; overflow-y: auto; }
|
|
464
|
+
.ue-ins__wire { display: flex; gap: 7px; padding: 1px 0; white-space: nowrap; }
|
|
465
|
+
.ue-ins__dir { flex: none; width: 9px; }
|
|
466
|
+
.ue-ins__dir--out { color: #d29922; }
|
|
467
|
+
.ue-ins__dir--in { color: #3fb950; }
|
|
468
|
+
.ue-ins__scope { color: #e6edf3; }
|
|
469
|
+
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
470
|
+
|
|
471
|
+
.ue-ins__tools { display: flex; gap: 6px; align-items: center; margin-bottom: 5px; }
|
|
472
|
+
.ue-ins__btn {
|
|
473
|
+
background: #21262d;
|
|
474
|
+
border: 1px solid #30363d;
|
|
475
|
+
border-radius: 5px;
|
|
476
|
+
color: #c9d1d9;
|
|
477
|
+
font: inherit;
|
|
478
|
+
font-size: 10px;
|
|
479
|
+
padding: 1px 7px;
|
|
480
|
+
cursor: pointer;
|
|
481
|
+
}
|
|
482
|
+
.ue-ins__btn[aria-pressed='true'] { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
|
483
|
+
.ue-ins__filter {
|
|
484
|
+
flex: 1;
|
|
485
|
+
min-width: 0;
|
|
486
|
+
background: #0d1117;
|
|
487
|
+
border: 1px solid #30363d;
|
|
488
|
+
border-radius: 5px;
|
|
489
|
+
color: #c9d1d9;
|
|
490
|
+
font: inherit;
|
|
491
|
+
font-size: 10px;
|
|
492
|
+
padding: 1px 6px;
|
|
493
|
+
}
|
|
494
|
+
.ue-ins__edit {
|
|
495
|
+
flex: 1;
|
|
496
|
+
min-width: 0;
|
|
497
|
+
background: #0d1117;
|
|
498
|
+
border: 1px solid #1f6feb;
|
|
499
|
+
border-radius: 4px;
|
|
500
|
+
color: #e6edf3;
|
|
501
|
+
font: inherit;
|
|
502
|
+
padding: 0 4px;
|
|
503
|
+
}
|
|
504
|
+
.ue-ins__v--editable { cursor: text; text-decoration: underline dotted #30363d; }
|
|
505
|
+
.ue-ins__v--invalid { color: #f85149; }
|
|
506
|
+
.ue-ins__paused { color: #d29922; }
|
|
507
|
+
`;
|
|
508
|
+
|
|
509
|
+
// src/devtools/inspector.tsx
|
|
510
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
511
|
+
function Inspector({
|
|
512
|
+
name = import_core3.DEFAULT_NAME,
|
|
513
|
+
position = "bottom-right",
|
|
514
|
+
limit = 50,
|
|
515
|
+
defaultOpen = false,
|
|
516
|
+
leaseMs = 3e3
|
|
517
|
+
} = {}) {
|
|
518
|
+
const [root, setRoot] = (0, import_react3.useState)(null);
|
|
519
|
+
const attach = (host) => {
|
|
520
|
+
if (!host || root) return;
|
|
521
|
+
setRoot(host.shadowRoot ?? host.attachShadow({ mode: "open" }));
|
|
522
|
+
};
|
|
523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: attach, "data-testid": "ue-inspector-host", children: root ? (0, import_react_dom.createPortal)(
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: STYLES }),
|
|
526
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
527
|
+
Panel,
|
|
528
|
+
{
|
|
529
|
+
name,
|
|
530
|
+
position,
|
|
531
|
+
limit,
|
|
532
|
+
defaultOpen,
|
|
533
|
+
leaseMs
|
|
534
|
+
}
|
|
535
|
+
)
|
|
536
|
+
] }),
|
|
537
|
+
root
|
|
538
|
+
) : null });
|
|
539
|
+
}
|
|
320
540
|
// Annotate the CommonJS export names for ESM import in node:
|
|
321
541
|
0 && (module.exports = {
|
|
322
542
|
Inspector
|
|
@@ -18,8 +18,8 @@ interface InspectorProps {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* A floating panel showing what this tab is saying and hearing on the bus:
|
|
21
|
-
* peers, the leader, store keys with their version clocks,
|
|
22
|
-
*
|
|
21
|
+
* peers, the leader, store keys with their version clocks, a live wire log in
|
|
22
|
+
* both directions, and a timeline of the state each wire produced.
|
|
23
23
|
*
|
|
24
24
|
* It deliberately does **not** create a Leader. Under dynamic eligibility,
|
|
25
25
|
* mounting one with `eligible: false` would disable candidacy for the whole
|
|
@@ -29,6 +29,17 @@ interface InspectorProps {
|
|
|
29
29
|
*
|
|
30
30
|
* Presence is fine to use: the bus heartbeats regardless of whether anything
|
|
31
31
|
* created a Presence, so usePeers observes rather than perturbs.
|
|
32
|
+
*
|
|
33
|
+
* **The panel lives in a shadow root.** Its styles used to be a `<style>` tag
|
|
34
|
+
* in the page, which is only ever half true: `.ue-ins` could not leak out, but
|
|
35
|
+
* everything in the host document leaked *in* — a `* { box-sizing }` reset, an
|
|
36
|
+
* app-wide `button { text-transform: uppercase }`, a Tailwind preflight, any
|
|
37
|
+
* `!important`. A devtool that renders differently depending on whose app it is
|
|
38
|
+
* mounted in is a devtool you cannot trust when it looks wrong. Inside a shadow
|
|
39
|
+
* root, page CSS does not apply and the panel's own CSS cannot escape.
|
|
40
|
+
*
|
|
41
|
+
* A consequence worth knowing when testing an app that mounts it: the panel is
|
|
42
|
+
* **not** in `document`. Reach it through `host.shadowRoot`.
|
|
32
43
|
*/
|
|
33
44
|
declare function Inspector({ name, position, limit, defaultOpen, leaseMs, }?: InspectorProps): react.JSX.Element;
|
|
34
45
|
|
package/dist/devtools/index.d.ts
CHANGED
|
@@ -18,8 +18,8 @@ interface InspectorProps {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* A floating panel showing what this tab is saying and hearing on the bus:
|
|
21
|
-
* peers, the leader, store keys with their version clocks,
|
|
22
|
-
*
|
|
21
|
+
* peers, the leader, store keys with their version clocks, a live wire log in
|
|
22
|
+
* both directions, and a timeline of the state each wire produced.
|
|
23
23
|
*
|
|
24
24
|
* It deliberately does **not** create a Leader. Under dynamic eligibility,
|
|
25
25
|
* mounting one with `eligible: false` would disable candidacy for the whole
|
|
@@ -29,6 +29,17 @@ interface InspectorProps {
|
|
|
29
29
|
*
|
|
30
30
|
* Presence is fine to use: the bus heartbeats regardless of whether anything
|
|
31
31
|
* created a Presence, so usePeers observes rather than perturbs.
|
|
32
|
+
*
|
|
33
|
+
* **The panel lives in a shadow root.** Its styles used to be a `<style>` tag
|
|
34
|
+
* in the page, which is only ever half true: `.ue-ins` could not leak out, but
|
|
35
|
+
* everything in the host document leaked *in* — a `* { box-sizing }` reset, an
|
|
36
|
+
* app-wide `button { text-transform: uppercase }`, a Tailwind preflight, any
|
|
37
|
+
* `!important`. A devtool that renders differently depending on whose app it is
|
|
38
|
+
* mounted in is a devtool you cannot trust when it looks wrong. Inside a shadow
|
|
39
|
+
* root, page CSS does not apply and the panel's own CSS cannot escape.
|
|
40
|
+
*
|
|
41
|
+
* A consequence worth knowing when testing an app that mounts it: the panel is
|
|
42
|
+
* **not** in `document`. Reach it through `host.shadowRoot`.
|
|
32
43
|
*/
|
|
33
44
|
declare function Inspector({ name, position, limit, defaultOpen, leaseMs, }?: InspectorProps): react.JSX.Element;
|
|
34
45
|
|
package/dist/devtools/index.js
CHANGED
|
@@ -2,91 +2,43 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getSharedStore,
|
|
4
4
|
usePeers
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-R7PBPLF7.js";
|
|
6
6
|
|
|
7
7
|
// src/devtools/inspector.tsx
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
// src/devtools/styles.ts
|
|
12
|
-
var STYLES = `
|
|
13
|
-
.ue-ins {
|
|
14
|
-
position: fixed;
|
|
15
|
-
z-index: 2147483000;
|
|
16
|
-
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
17
|
-
color: #e6edf3;
|
|
18
|
-
background: #0d1117;
|
|
19
|
-
border: 1px solid #30363d;
|
|
20
|
-
border-radius: 8px;
|
|
21
|
-
box-shadow: 0 8px 32px rgb(0 0 0 / 0.4);
|
|
22
|
-
max-width: min(420px, calc(100vw - 24px));
|
|
23
|
-
overflow: hidden;
|
|
24
|
-
}
|
|
25
|
-
.ue-ins--bottom-right { bottom: 12px; right: 12px; }
|
|
26
|
-
.ue-ins--bottom-left { bottom: 12px; left: 12px; }
|
|
27
|
-
.ue-ins--top-right { top: 12px; right: 12px; }
|
|
28
|
-
.ue-ins--top-left { top: 12px; left: 12px; }
|
|
29
|
-
|
|
30
|
-
.ue-ins__bar {
|
|
31
|
-
display: flex;
|
|
32
|
-
align-items: center;
|
|
33
|
-
gap: 8px;
|
|
34
|
-
width: 100%;
|
|
35
|
-
padding: 7px 10px;
|
|
36
|
-
background: #161b22;
|
|
37
|
-
border: 0;
|
|
38
|
-
color: inherit;
|
|
39
|
-
font: inherit;
|
|
40
|
-
cursor: pointer;
|
|
41
|
-
text-align: left;
|
|
42
|
-
}
|
|
43
|
-
.ue-ins__dot { width: 7px; height: 7px; border-radius: 50%; background: #3fb950; flex: none; }
|
|
44
|
-
.ue-ins__title { font-weight: 600; }
|
|
45
|
-
.ue-ins__muted { color: #8b949e; }
|
|
46
|
-
.ue-ins__crown { margin-left: auto; color: #d29922; }
|
|
8
|
+
import { useState as useState2 } from "react";
|
|
9
|
+
import { createPortal } from "react-dom";
|
|
10
|
+
import { DEFAULT_NAME } from "@use-everywhere/core";
|
|
47
11
|
|
|
48
|
-
.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
color: #8b949e;
|
|
52
|
-
text-transform: uppercase;
|
|
53
|
-
letter-spacing: 0.06em;
|
|
54
|
-
font-size: 10px;
|
|
55
|
-
margin-bottom: 5px;
|
|
56
|
-
}
|
|
57
|
-
.ue-ins__row { display: flex; gap: 8px; padding: 1px 0; }
|
|
58
|
-
.ue-ins__k { color: #79c0ff; flex: none; }
|
|
59
|
-
.ue-ins__v { color: #e6edf3; overflow-wrap: anywhere; }
|
|
60
|
-
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
61
|
-
.ue-ins__empty { color: #6e7681; }
|
|
62
|
-
|
|
63
|
-
.ue-ins__log { display: flex; flex-direction: column-reverse; max-height: 190px; overflow-y: auto; }
|
|
64
|
-
.ue-ins__wire { display: flex; gap: 7px; padding: 1px 0; white-space: nowrap; }
|
|
65
|
-
.ue-ins__dir { flex: none; width: 9px; }
|
|
66
|
-
.ue-ins__dir--out { color: #d29922; }
|
|
67
|
-
.ue-ins__dir--in { color: #3fb950; }
|
|
68
|
-
.ue-ins__scope { color: #e6edf3; }
|
|
69
|
-
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
70
|
-
`;
|
|
71
|
-
|
|
72
|
-
// src/devtools/inspector.tsx
|
|
12
|
+
// src/devtools/panel.tsx
|
|
13
|
+
import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
14
|
+
import { observeBus } from "@use-everywhere/core";
|
|
73
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
74
16
|
var short = (id) => id.slice(0, 6);
|
|
75
17
|
function wireLabel(wire) {
|
|
76
18
|
return `${wire.scope}/${wire.type}`;
|
|
77
19
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
limit
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
20
|
+
var SCOPES = ["all", "state", "leader", "presence", "channel"];
|
|
21
|
+
function Panel({
|
|
22
|
+
name,
|
|
23
|
+
limit,
|
|
24
|
+
leaseMs,
|
|
25
|
+
position,
|
|
26
|
+
defaultOpen
|
|
27
|
+
}) {
|
|
85
28
|
const [open, setOpen] = useState(defaultOpen);
|
|
86
29
|
const [wires, setWires] = useState([]);
|
|
87
30
|
const [crown, setCrown] = useState(null);
|
|
31
|
+
const [paused, setPaused] = useState(false);
|
|
32
|
+
const [filter, setFilter] = useState("");
|
|
33
|
+
const [scopeView, setScopeView] = useState("all");
|
|
34
|
+
const [editing, setEditing] = useState(null);
|
|
35
|
+
const [frames, setFrames] = useState([]);
|
|
88
36
|
const nextId = useRef(0);
|
|
89
37
|
const crownAt = useRef(0);
|
|
38
|
+
const pausedRef = useRef(false);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
pausedRef.current = paused;
|
|
41
|
+
}, [paused]);
|
|
90
42
|
const peers = usePeers({ name });
|
|
91
43
|
const store = getSharedStore(name);
|
|
92
44
|
const subscribe = useCallback((onChange) => store.subscribe(onChange), [store]);
|
|
@@ -112,19 +64,22 @@ function Inspector({
|
|
|
112
64
|
crownAt.current = Date.now();
|
|
113
65
|
}
|
|
114
66
|
}
|
|
67
|
+
if (pausedRef.current) return;
|
|
68
|
+
const id = nextId.current++;
|
|
69
|
+
const label = wireLabel(wire);
|
|
115
70
|
setWires(
|
|
116
71
|
(prev) => [
|
|
117
72
|
...prev.slice(-(limit - 1)),
|
|
118
|
-
{
|
|
119
|
-
id: nextId.current++,
|
|
120
|
-
direction,
|
|
121
|
-
label: wireLabel(wire),
|
|
122
|
-
from: short(wire.clientId)
|
|
123
|
-
}
|
|
73
|
+
{ id, direction, scope: wire.scope, label, from: short(wire.clientId) }
|
|
124
74
|
].slice(-limit)
|
|
125
75
|
);
|
|
76
|
+
if (wire.scope === "state") {
|
|
77
|
+
setFrames(
|
|
78
|
+
(prev) => [...prev, { wireId: id, label, snapshot: { ...store.getSnapshot() } }].slice(-limit)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
126
81
|
});
|
|
127
|
-
}, [name, limit]);
|
|
82
|
+
}, [name, limit, store]);
|
|
128
83
|
useEffect(() => {
|
|
129
84
|
const timer = setInterval(
|
|
130
85
|
() => {
|
|
@@ -133,17 +88,43 @@ function Inspector({
|
|
|
133
88
|
crownAt.current = 0;
|
|
134
89
|
}
|
|
135
90
|
},
|
|
136
|
-
// Quarter of the lease, so a vacated crown clears well within it. The
|
|
137
|
-
// floor is low enough that a short lease still works rather than being
|
|
138
|
-
// silently rounded up to something coarser than the lease itself.
|
|
139
91
|
Math.max(50, Math.floor(leaseMs / 4))
|
|
140
92
|
);
|
|
141
93
|
return () => clearInterval(timer);
|
|
142
94
|
}, [leaseMs]);
|
|
143
95
|
const selfId = store.clientId;
|
|
144
96
|
const entries = Object.entries(versions);
|
|
97
|
+
const needle = filter.trim().toLowerCase();
|
|
98
|
+
const shown = wires.filter((wire) => {
|
|
99
|
+
if (scopeView !== "all" && wire.scope !== scopeView) return false;
|
|
100
|
+
if (!needle) return true;
|
|
101
|
+
return wire.label.toLowerCase().includes(needle) || wire.from.toLowerCase().includes(needle);
|
|
102
|
+
});
|
|
103
|
+
const commit = (key, draft) => {
|
|
104
|
+
let value;
|
|
105
|
+
try {
|
|
106
|
+
value = JSON.parse(draft);
|
|
107
|
+
} catch {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
store.set(key, value);
|
|
111
|
+
setEditing(null);
|
|
112
|
+
};
|
|
113
|
+
const draftIsValid = (draft) => {
|
|
114
|
+
try {
|
|
115
|
+
JSON.parse(draft);
|
|
116
|
+
return true;
|
|
117
|
+
} catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const restore = (frame) => {
|
|
122
|
+
for (const [key, value] of Object.entries(frame.snapshot)) {
|
|
123
|
+
if (Object.is(store.getSnapshot()[key], value)) continue;
|
|
124
|
+
store.set(key, value);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
145
127
|
return /* @__PURE__ */ jsxs("div", { className: `ue-ins ue-ins--${position}`, "data-testid": "ue-inspector", children: [
|
|
146
|
-
/* @__PURE__ */ jsx("style", { children: STYLES }),
|
|
147
128
|
/* @__PURE__ */ jsxs(
|
|
148
129
|
"button",
|
|
149
130
|
{
|
|
@@ -189,7 +170,31 @@ function Inspector({
|
|
|
189
170
|
] }),
|
|
190
171
|
entries.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ue-ins__empty", children: "no keys yet" }) : entries.map(([key, version]) => /* @__PURE__ */ jsxs("div", { className: "ue-ins__row", children: [
|
|
191
172
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__k", children: key }),
|
|
192
|
-
/* @__PURE__ */ jsx(
|
|
173
|
+
editing?.key === key ? /* @__PURE__ */ jsx(
|
|
174
|
+
"input",
|
|
175
|
+
{
|
|
176
|
+
className: `ue-ins__edit${draftIsValid(editing.draft) ? "" : " ue-ins__v--invalid"}`,
|
|
177
|
+
value: editing.draft,
|
|
178
|
+
autoFocus: true,
|
|
179
|
+
"aria-label": `Value of ${key}`,
|
|
180
|
+
onChange: (event) => setEditing({ key, draft: event.target.value }),
|
|
181
|
+
onKeyDown: (event) => {
|
|
182
|
+
if (event.key === "Enter") commit(key, editing.draft);
|
|
183
|
+
if (event.key === "Escape") setEditing(null);
|
|
184
|
+
},
|
|
185
|
+
onBlur: () => setEditing(null),
|
|
186
|
+
"data-testid": `ue-edit-${key}`
|
|
187
|
+
}
|
|
188
|
+
) : /* @__PURE__ */ jsx(
|
|
189
|
+
"button",
|
|
190
|
+
{
|
|
191
|
+
type: "button",
|
|
192
|
+
className: "ue-ins__v ue-ins__v--editable",
|
|
193
|
+
onClick: () => setEditing({ key, draft: JSON.stringify(snapshot[key]) ?? "" }),
|
|
194
|
+
"data-testid": `ue-value-${key}`,
|
|
195
|
+
children: JSON.stringify(snapshot[key])
|
|
196
|
+
}
|
|
197
|
+
),
|
|
193
198
|
/* @__PURE__ */ jsxs("span", { className: "ue-ins__ver", children: [
|
|
194
199
|
version[0],
|
|
195
200
|
"\xB7",
|
|
@@ -200,18 +205,231 @@ function Inspector({
|
|
|
200
205
|
/* @__PURE__ */ jsxs("div", { className: "ue-ins__section", children: [
|
|
201
206
|
/* @__PURE__ */ jsxs("div", { className: "ue-ins__h", children: [
|
|
202
207
|
"Wires (",
|
|
203
|
-
|
|
204
|
-
"
|
|
208
|
+
shown.length,
|
|
209
|
+
shown.length === wires.length ? "" : ` of ${wires.length}`,
|
|
210
|
+
")",
|
|
211
|
+
paused ? /* @__PURE__ */ jsx("span", { className: "ue-ins__paused", children: " \xB7 paused" }) : null
|
|
205
212
|
] }),
|
|
206
|
-
|
|
213
|
+
/* @__PURE__ */ jsxs("div", { className: "ue-ins__tools", children: [
|
|
214
|
+
/* @__PURE__ */ jsx(
|
|
215
|
+
"button",
|
|
216
|
+
{
|
|
217
|
+
type: "button",
|
|
218
|
+
className: "ue-ins__btn",
|
|
219
|
+
"aria-pressed": paused,
|
|
220
|
+
onClick: () => setPaused((value) => !value),
|
|
221
|
+
"data-testid": "ue-pause",
|
|
222
|
+
children: paused ? "resume" : "pause"
|
|
223
|
+
}
|
|
224
|
+
),
|
|
225
|
+
/* @__PURE__ */ jsx(
|
|
226
|
+
"button",
|
|
227
|
+
{
|
|
228
|
+
type: "button",
|
|
229
|
+
className: "ue-ins__btn",
|
|
230
|
+
onClick: () => {
|
|
231
|
+
setWires([]);
|
|
232
|
+
setFrames([]);
|
|
233
|
+
},
|
|
234
|
+
"data-testid": "ue-clear",
|
|
235
|
+
children: "clear"
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
/* @__PURE__ */ jsx(
|
|
239
|
+
"input",
|
|
240
|
+
{
|
|
241
|
+
className: "ue-ins__filter",
|
|
242
|
+
value: filter,
|
|
243
|
+
placeholder: "filter",
|
|
244
|
+
"aria-label": "Filter wires",
|
|
245
|
+
onChange: (event) => setFilter(event.target.value),
|
|
246
|
+
"data-testid": "ue-filter"
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
] }),
|
|
250
|
+
/* @__PURE__ */ jsx("div", { className: "ue-ins__tools", role: "group", "aria-label": "Scope", children: SCOPES.map((scope) => /* @__PURE__ */ jsx(
|
|
251
|
+
"button",
|
|
252
|
+
{
|
|
253
|
+
type: "button",
|
|
254
|
+
className: "ue-ins__btn",
|
|
255
|
+
"aria-pressed": scopeView === scope,
|
|
256
|
+
onClick: () => setScopeView(scope),
|
|
257
|
+
"data-testid": `ue-scope-${scope}`,
|
|
258
|
+
children: scope
|
|
259
|
+
},
|
|
260
|
+
scope
|
|
261
|
+
)) }),
|
|
262
|
+
shown.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ue-ins__empty", "data-testid": "ue-wires", children: wires.length === 0 ? "nothing yet" : "no matches" }) : /* @__PURE__ */ jsx("div", { className: "ue-ins__log", "data-testid": "ue-wires", children: shown.map((wire) => /* @__PURE__ */ jsxs("div", { className: "ue-ins__wire", children: [
|
|
207
263
|
/* @__PURE__ */ jsx("span", { className: `ue-ins__dir ue-ins__dir--${wire.direction}`, children: wire.direction === "out" ? "\u2192" : "\u2190" }),
|
|
208
264
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__scope", children: wire.label }),
|
|
209
265
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__from", children: wire.from })
|
|
210
266
|
] }, wire.id)) })
|
|
267
|
+
] }),
|
|
268
|
+
/* @__PURE__ */ jsxs("div", { className: "ue-ins__section", children: [
|
|
269
|
+
/* @__PURE__ */ jsxs("div", { className: "ue-ins__h", children: [
|
|
270
|
+
"Timeline (",
|
|
271
|
+
frames.length,
|
|
272
|
+
")"
|
|
273
|
+
] }),
|
|
274
|
+
frames.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ue-ins__empty", children: "no state on the wire yet" }) : /* @__PURE__ */ jsx("div", { className: "ue-ins__log", children: frames.map((frame) => /* @__PURE__ */ jsxs("div", { className: "ue-ins__wire", children: [
|
|
275
|
+
/* @__PURE__ */ jsx(
|
|
276
|
+
"button",
|
|
277
|
+
{
|
|
278
|
+
type: "button",
|
|
279
|
+
className: "ue-ins__btn",
|
|
280
|
+
onClick: () => restore(frame),
|
|
281
|
+
"data-testid": `ue-restore-${String(frame.wireId)}`,
|
|
282
|
+
children: "restore"
|
|
283
|
+
}
|
|
284
|
+
),
|
|
285
|
+
/* @__PURE__ */ jsx("span", { className: "ue-ins__scope", children: frame.label }),
|
|
286
|
+
/* @__PURE__ */ jsxs("span", { className: "ue-ins__from", children: [
|
|
287
|
+
Object.keys(frame.snapshot).length,
|
|
288
|
+
" key",
|
|
289
|
+
Object.keys(frame.snapshot).length === 1 ? "" : "s"
|
|
290
|
+
] })
|
|
291
|
+
] }, frame.wireId)) })
|
|
211
292
|
] })
|
|
212
293
|
] }) : null
|
|
213
294
|
] });
|
|
214
295
|
}
|
|
296
|
+
|
|
297
|
+
// src/devtools/styles.ts
|
|
298
|
+
var STYLES = `
|
|
299
|
+
.ue-ins {
|
|
300
|
+
position: fixed;
|
|
301
|
+
z-index: 2147483000;
|
|
302
|
+
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
303
|
+
color: #e6edf3;
|
|
304
|
+
background: #0d1117;
|
|
305
|
+
border: 1px solid #30363d;
|
|
306
|
+
border-radius: 8px;
|
|
307
|
+
box-shadow: 0 8px 32px rgb(0 0 0 / 0.4);
|
|
308
|
+
max-width: min(420px, calc(100vw - 24px));
|
|
309
|
+
overflow: hidden;
|
|
310
|
+
}
|
|
311
|
+
.ue-ins--bottom-right { bottom: 12px; right: 12px; }
|
|
312
|
+
.ue-ins--bottom-left { bottom: 12px; left: 12px; }
|
|
313
|
+
.ue-ins--top-right { top: 12px; right: 12px; }
|
|
314
|
+
.ue-ins--top-left { top: 12px; left: 12px; }
|
|
315
|
+
|
|
316
|
+
.ue-ins__bar {
|
|
317
|
+
display: flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
gap: 8px;
|
|
320
|
+
width: 100%;
|
|
321
|
+
padding: 7px 10px;
|
|
322
|
+
background: #161b22;
|
|
323
|
+
border: 0;
|
|
324
|
+
color: inherit;
|
|
325
|
+
font: inherit;
|
|
326
|
+
cursor: pointer;
|
|
327
|
+
text-align: left;
|
|
328
|
+
}
|
|
329
|
+
.ue-ins__dot { width: 7px; height: 7px; border-radius: 50%; background: #3fb950; flex: none; }
|
|
330
|
+
.ue-ins__title { font-weight: 600; }
|
|
331
|
+
.ue-ins__muted { color: #8b949e; }
|
|
332
|
+
.ue-ins__crown { margin-left: auto; color: #d29922; }
|
|
333
|
+
|
|
334
|
+
.ue-ins__body { max-height: 60vh; overflow-y: auto; }
|
|
335
|
+
.ue-ins__section { border-top: 1px solid #21262d; padding: 8px 10px; }
|
|
336
|
+
.ue-ins__h {
|
|
337
|
+
color: #8b949e;
|
|
338
|
+
text-transform: uppercase;
|
|
339
|
+
letter-spacing: 0.06em;
|
|
340
|
+
font-size: 10px;
|
|
341
|
+
margin-bottom: 5px;
|
|
342
|
+
}
|
|
343
|
+
.ue-ins__row { display: flex; gap: 8px; padding: 1px 0; }
|
|
344
|
+
.ue-ins__k { color: #79c0ff; flex: none; }
|
|
345
|
+
.ue-ins__v { color: #e6edf3; overflow-wrap: anywhere; }
|
|
346
|
+
button.ue-ins__v {
|
|
347
|
+
background: none;
|
|
348
|
+
border: 0;
|
|
349
|
+
padding: 0;
|
|
350
|
+
font: inherit;
|
|
351
|
+
text-align: left;
|
|
352
|
+
}
|
|
353
|
+
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
354
|
+
.ue-ins__empty { color: #6e7681; }
|
|
355
|
+
|
|
356
|
+
.ue-ins__log { display: flex; flex-direction: column-reverse; max-height: 190px; overflow-y: auto; }
|
|
357
|
+
.ue-ins__wire { display: flex; gap: 7px; padding: 1px 0; white-space: nowrap; }
|
|
358
|
+
.ue-ins__dir { flex: none; width: 9px; }
|
|
359
|
+
.ue-ins__dir--out { color: #d29922; }
|
|
360
|
+
.ue-ins__dir--in { color: #3fb950; }
|
|
361
|
+
.ue-ins__scope { color: #e6edf3; }
|
|
362
|
+
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
363
|
+
|
|
364
|
+
.ue-ins__tools { display: flex; gap: 6px; align-items: center; margin-bottom: 5px; }
|
|
365
|
+
.ue-ins__btn {
|
|
366
|
+
background: #21262d;
|
|
367
|
+
border: 1px solid #30363d;
|
|
368
|
+
border-radius: 5px;
|
|
369
|
+
color: #c9d1d9;
|
|
370
|
+
font: inherit;
|
|
371
|
+
font-size: 10px;
|
|
372
|
+
padding: 1px 7px;
|
|
373
|
+
cursor: pointer;
|
|
374
|
+
}
|
|
375
|
+
.ue-ins__btn[aria-pressed='true'] { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
|
376
|
+
.ue-ins__filter {
|
|
377
|
+
flex: 1;
|
|
378
|
+
min-width: 0;
|
|
379
|
+
background: #0d1117;
|
|
380
|
+
border: 1px solid #30363d;
|
|
381
|
+
border-radius: 5px;
|
|
382
|
+
color: #c9d1d9;
|
|
383
|
+
font: inherit;
|
|
384
|
+
font-size: 10px;
|
|
385
|
+
padding: 1px 6px;
|
|
386
|
+
}
|
|
387
|
+
.ue-ins__edit {
|
|
388
|
+
flex: 1;
|
|
389
|
+
min-width: 0;
|
|
390
|
+
background: #0d1117;
|
|
391
|
+
border: 1px solid #1f6feb;
|
|
392
|
+
border-radius: 4px;
|
|
393
|
+
color: #e6edf3;
|
|
394
|
+
font: inherit;
|
|
395
|
+
padding: 0 4px;
|
|
396
|
+
}
|
|
397
|
+
.ue-ins__v--editable { cursor: text; text-decoration: underline dotted #30363d; }
|
|
398
|
+
.ue-ins__v--invalid { color: #f85149; }
|
|
399
|
+
.ue-ins__paused { color: #d29922; }
|
|
400
|
+
`;
|
|
401
|
+
|
|
402
|
+
// src/devtools/inspector.tsx
|
|
403
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
404
|
+
function Inspector({
|
|
405
|
+
name = DEFAULT_NAME,
|
|
406
|
+
position = "bottom-right",
|
|
407
|
+
limit = 50,
|
|
408
|
+
defaultOpen = false,
|
|
409
|
+
leaseMs = 3e3
|
|
410
|
+
} = {}) {
|
|
411
|
+
const [root, setRoot] = useState2(null);
|
|
412
|
+
const attach = (host) => {
|
|
413
|
+
if (!host || root) return;
|
|
414
|
+
setRoot(host.shadowRoot ?? host.attachShadow({ mode: "open" }));
|
|
415
|
+
};
|
|
416
|
+
return /* @__PURE__ */ jsx2("div", { ref: attach, "data-testid": "ue-inspector-host", children: root ? createPortal(
|
|
417
|
+
/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
418
|
+
/* @__PURE__ */ jsx2("style", { children: STYLES }),
|
|
419
|
+
/* @__PURE__ */ jsx2(
|
|
420
|
+
Panel,
|
|
421
|
+
{
|
|
422
|
+
name,
|
|
423
|
+
position,
|
|
424
|
+
limit,
|
|
425
|
+
defaultOpen,
|
|
426
|
+
leaseMs
|
|
427
|
+
}
|
|
428
|
+
)
|
|
429
|
+
] }),
|
|
430
|
+
root
|
|
431
|
+
) : null });
|
|
432
|
+
}
|
|
215
433
|
export {
|
|
216
434
|
Inspector
|
|
217
435
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(src_exports, {
|
|
|
26
26
|
DEFAULT_NAME: () => import_core.DEFAULT_NAME,
|
|
27
27
|
HandshakeTimeoutError: () => import_core4.HandshakeTimeoutError,
|
|
28
28
|
NoopTransport: () => import_core4.NoopTransport,
|
|
29
|
+
SharedWorkerTransport: () => import_core4.SharedWorkerTransport,
|
|
29
30
|
StorageTransport: () => import_core4.StorageTransport,
|
|
30
31
|
WIRE_VERSION: () => import_core4.WIRE_VERSION,
|
|
31
32
|
WindowClosedError: () => import_core4.WindowClosedError,
|
|
@@ -47,6 +48,7 @@ __export(src_exports, {
|
|
|
47
48
|
getWireSkew: () => import_core4.getWireSkew,
|
|
48
49
|
indexedDbAdapter: () => import_core4.indexedDbAdapter,
|
|
49
50
|
isBroadcastChannelAvailable: () => import_core4.isBroadcastChannelAvailable,
|
|
51
|
+
isSharedWorkerAvailable: () => import_core4.isSharedWorkerAvailable,
|
|
50
52
|
isStorageEventAvailable: () => import_core4.isStorageEventAvailable,
|
|
51
53
|
jsonSerializer: () => import_core4.jsonSerializer,
|
|
52
54
|
localStorageAdapter: () => import_core4.localStorageAdapter,
|
|
@@ -85,10 +87,17 @@ try {
|
|
|
85
87
|
} catch {
|
|
86
88
|
}
|
|
87
89
|
var warned = /* @__PURE__ */ new Set();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
var DOCS = "https://rxova.org/packages/use-everywhere/errors";
|
|
91
|
+
function diagnostic(code, message) {
|
|
92
|
+
return `[use-everywhere] ${code}: ${message}
|
|
93
|
+
\u2192 ${DOCS}/#${code.toLowerCase()}`;
|
|
94
|
+
}
|
|
95
|
+
function devWarn(code, message) {
|
|
96
|
+
if (!inDev) return;
|
|
97
|
+
const line = diagnostic(code, message);
|
|
98
|
+
if (warned.has(line)) return;
|
|
99
|
+
warned.add(line);
|
|
100
|
+
console.warn(line);
|
|
92
101
|
}
|
|
93
102
|
var seenInitials = /* @__PURE__ */ new Map();
|
|
94
103
|
function warnOnInitialMismatch(storeName, key, initial) {
|
|
@@ -102,7 +111,8 @@ function warnOnInitialMismatch(storeName, key, initial) {
|
|
|
102
111
|
const comparable = (v) => v === null || typeof v !== "object";
|
|
103
112
|
if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
|
|
104
113
|
devWarn(
|
|
105
|
-
|
|
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.`
|
|
106
116
|
);
|
|
107
117
|
}
|
|
108
118
|
}
|
|
@@ -188,7 +198,8 @@ function configureStore(name, scope, options) {
|
|
|
188
198
|
if (configSignature(storeConfig.get(key)) === configSignature(options)) return;
|
|
189
199
|
if (process.env.NODE_ENV !== "production") {
|
|
190
200
|
devWarn(
|
|
191
|
-
|
|
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.`
|
|
192
203
|
);
|
|
193
204
|
}
|
|
194
205
|
return;
|
|
@@ -232,7 +243,8 @@ function warnOnLeaderOptionConflict(name, options) {
|
|
|
232
243
|
if (requested !== void 0 && requested !== first?.[key]) {
|
|
233
244
|
if (process.env.NODE_ENV !== "production") {
|
|
234
245
|
devWarn(
|
|
235
|
-
|
|
246
|
+
"UE2003",
|
|
247
|
+
`leader "${name}": ${key} ignored \u2014 the first useLeader/getLeader call fixes the election timings for this tab.`
|
|
236
248
|
);
|
|
237
249
|
}
|
|
238
250
|
}
|
|
@@ -246,7 +258,8 @@ function configureChannel(name, options) {
|
|
|
246
258
|
if (before.join() === after.join()) return;
|
|
247
259
|
if (process.env.NODE_ENV !== "production") {
|
|
248
260
|
devWarn(
|
|
249
|
-
|
|
261
|
+
"UE2004",
|
|
262
|
+
`defineChannel('${name}') ran after that channel was already created, with different options. The live channel keeps the configuration it was built with. Move defineChannel to module scope, before any component sends or receives on it.`
|
|
250
263
|
);
|
|
251
264
|
}
|
|
252
265
|
return;
|
|
@@ -580,6 +593,7 @@ var import_core4 = require("@use-everywhere/core");
|
|
|
580
593
|
DEFAULT_NAME,
|
|
581
594
|
HandshakeTimeoutError,
|
|
582
595
|
NoopTransport,
|
|
596
|
+
SharedWorkerTransport,
|
|
583
597
|
StorageTransport,
|
|
584
598
|
WIRE_VERSION,
|
|
585
599
|
WindowClosedError,
|
|
@@ -601,6 +615,7 @@ var import_core4 = require("@use-everywhere/core");
|
|
|
601
615
|
getWireSkew,
|
|
602
616
|
indexedDbAdapter,
|
|
603
617
|
isBroadcastChannelAvailable,
|
|
618
|
+
isSharedWorkerAvailable,
|
|
604
619
|
isStorageEventAvailable,
|
|
605
620
|
jsonSerializer,
|
|
606
621
|
localStorageAdapter,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SharedStore, LeaderOptions, Leader, MessageMap, ReplyMap, Channel, MessageMeta, ChannelOptions, PersistAdapter, RestoreError, Peer, LeaderSnapshot, Namespace, OpenedWindow, WindowClosedError } from '@use-everywhere/core';
|
|
2
|
-
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, MessageEventLike, MessageMap, MessageMeta, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
2
|
+
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, MessageEventLike, MessageMap, MessageMeta, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, SharedWorkerTransport, SharedWorkerTransportOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isSharedWorkerAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* How far a shared value travels:
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SharedStore, LeaderOptions, Leader, MessageMap, ReplyMap, Channel, MessageMeta, ChannelOptions, PersistAdapter, RestoreError, Peer, LeaderSnapshot, Namespace, OpenedWindow, WindowClosedError } from '@use-everywhere/core';
|
|
2
|
-
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, MessageEventLike, MessageMap, MessageMeta, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
2
|
+
export { AskOptions, BroadcastChannelTransport, BusEvent, BusObserver, BusWire, CID_PARAM, Channel, ChannelOptions, CommonOptions, ConnectToOpenerOptions, DEFAULT_NAME, DebugOptions, HandshakeTimeoutError, IndexedDbAdapterOptions, InvalidPayload, Leader, LeaderOptions, LeaderSnapshot, LeaderStrategy, MessageEventLike, MessageMap, MessageMeta, Namespace, NoopTransport, OnInvalid, OnOptions, OpenWindowOptions, OpenedWindow, OpenerConnection, Peer, PeerKind, PersistAdapter, PersistOptions, Persisted, PostOptions, Presence, PresenceOptions, ReplyMap, RestoreError, SchemaMap, SchemaOptions, Serializer, SharedReducer, SharedReducerOptions, SharedStore, SharedStoreOptions, SharedWorkerTransport, SharedWorkerTransportOptions, StandardSchemaV1, StorageLike, StorageTransport, Transport, TransportKind, Version, WIRE_VERSION, WebStorageAdapterOptions, WindowClosedError, WindowEventTarget, WindowLike, connectToOpener, createChannel, createLeader, createPresence, createSharedReducer, createSharedStore, defaultTransport, enableDebug, getBusNames, getTransportKind, getWireSkew, indexedDbAdapter, isBroadcastChannelAvailable, isSharedWorkerAvailable, isStorageEventAvailable, jsonSerializer, localStorageAdapter, newer, observeBus, openWindow, sessionStorageAdapter, webStorageAdapter } from '@use-everywhere/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* How far a shared value travels:
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
usePeers,
|
|
13
13
|
usePresenceMetadata,
|
|
14
14
|
warnOnInitialMismatch
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-R7PBPLF7.js";
|
|
16
16
|
|
|
17
17
|
// src/use-shared-state.ts
|
|
18
18
|
import { useCallback, useSyncExternalStore } from "react";
|
|
@@ -313,9 +313,11 @@ import {
|
|
|
313
313
|
BroadcastChannelTransport,
|
|
314
314
|
NoopTransport,
|
|
315
315
|
StorageTransport,
|
|
316
|
+
SharedWorkerTransport,
|
|
316
317
|
defaultTransport,
|
|
317
318
|
isBroadcastChannelAvailable,
|
|
318
|
-
isStorageEventAvailable
|
|
319
|
+
isStorageEventAvailable,
|
|
320
|
+
isSharedWorkerAvailable
|
|
319
321
|
} from "@use-everywhere/core";
|
|
320
322
|
export {
|
|
321
323
|
BroadcastChannelTransport,
|
|
@@ -323,6 +325,7 @@ export {
|
|
|
323
325
|
DEFAULT_NAME,
|
|
324
326
|
HandshakeTimeoutError,
|
|
325
327
|
NoopTransport,
|
|
328
|
+
SharedWorkerTransport,
|
|
326
329
|
StorageTransport,
|
|
327
330
|
WIRE_VERSION,
|
|
328
331
|
WindowClosedError2 as WindowClosedError,
|
|
@@ -344,6 +347,7 @@ export {
|
|
|
344
347
|
getWireSkew,
|
|
345
348
|
indexedDbAdapter,
|
|
346
349
|
isBroadcastChannelAvailable,
|
|
350
|
+
isSharedWorkerAvailable,
|
|
347
351
|
isStorageEventAvailable,
|
|
348
352
|
jsonSerializer,
|
|
349
353
|
localStorageAdapter,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/shared-worker.ts
|
|
22
|
+
var shared_worker_exports = {};
|
|
23
|
+
__export(shared_worker_exports, {
|
|
24
|
+
startRelay: () => import_shared_worker.startRelay
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(shared_worker_exports);
|
|
27
|
+
var import_shared_worker = require("@use-everywhere/core/shared-worker");
|
|
28
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
29
|
+
0 && (module.exports = {
|
|
30
|
+
startRelay
|
|
31
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-everywhere",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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>",
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"type": "module",
|
|
28
|
-
"sideEffects":
|
|
28
|
+
"sideEffects": [
|
|
29
|
+
"./dist/shared-worker.js",
|
|
30
|
+
"./dist/shared-worker.cjs"
|
|
31
|
+
],
|
|
29
32
|
"main": "./dist/index.cjs",
|
|
30
33
|
"module": "./dist/index.js",
|
|
31
34
|
"types": "./dist/index.d.ts",
|
|
@@ -50,6 +53,16 @@
|
|
|
50
53
|
"default": "./dist/devtools/index.cjs"
|
|
51
54
|
}
|
|
52
55
|
},
|
|
56
|
+
"./shared-worker": {
|
|
57
|
+
"import": {
|
|
58
|
+
"types": "./dist/shared-worker.d.ts",
|
|
59
|
+
"default": "./dist/shared-worker.js"
|
|
60
|
+
},
|
|
61
|
+
"require": {
|
|
62
|
+
"types": "./dist/shared-worker.d.cts",
|
|
63
|
+
"default": "./dist/shared-worker.cjs"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
53
66
|
"./testing": {
|
|
54
67
|
"import": {
|
|
55
68
|
"types": "./dist/testing.d.ts",
|
|
@@ -123,7 +136,13 @@
|
|
|
123
136
|
"name": "Inspector (devtools subpath)",
|
|
124
137
|
"path": "dist/devtools/index.js",
|
|
125
138
|
"import": "{ Inspector }",
|
|
126
|
-
"limit": "
|
|
139
|
+
"limit": "7.20 kB"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "SharedWorker relay (shared-worker subpath)",
|
|
143
|
+
"path": "dist/shared-worker.js",
|
|
144
|
+
"import": "*",
|
|
145
|
+
"limit": "280 B"
|
|
127
146
|
},
|
|
128
147
|
{
|
|
129
148
|
"name": "MemoryHub (testing subpath)",
|
|
@@ -133,10 +152,16 @@
|
|
|
133
152
|
}
|
|
134
153
|
],
|
|
135
154
|
"dependencies": {
|
|
136
|
-
"@use-everywhere/core": "0.
|
|
155
|
+
"@use-everywhere/core": "0.10.0"
|
|
137
156
|
},
|
|
138
157
|
"peerDependencies": {
|
|
139
|
-
"react": ">=18"
|
|
158
|
+
"react": ">=18",
|
|
159
|
+
"react-dom": ">=18"
|
|
160
|
+
},
|
|
161
|
+
"peerDependenciesMeta": {
|
|
162
|
+
"react-dom": {
|
|
163
|
+
"optional": true
|
|
164
|
+
}
|
|
140
165
|
},
|
|
141
166
|
"devDependencies": {
|
|
142
167
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
@@ -159,6 +184,9 @@
|
|
|
159
184
|
"devtools": [
|
|
160
185
|
"./dist/devtools/index.d.ts"
|
|
161
186
|
],
|
|
187
|
+
"shared-worker": [
|
|
188
|
+
"./dist/shared-worker.d.ts"
|
|
189
|
+
],
|
|
162
190
|
"testing": [
|
|
163
191
|
"./dist/testing.d.ts"
|
|
164
192
|
]
|