use-everywhere 0.8.0 → 0.9.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 +139 -4
- package/dist/devtools/index.js +140 -5
- package/dist/index.cjs +19 -8
- package/dist/index.js +1 -1
- package/package.json +3 -3
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
|
@@ -162,6 +162,13 @@ var STYLES = `
|
|
|
162
162
|
.ue-ins__row { display: flex; gap: 8px; padding: 1px 0; }
|
|
163
163
|
.ue-ins__k { color: #79c0ff; flex: none; }
|
|
164
164
|
.ue-ins__v { color: #e6edf3; overflow-wrap: anywhere; }
|
|
165
|
+
button.ue-ins__v {
|
|
166
|
+
background: none;
|
|
167
|
+
border: 0;
|
|
168
|
+
padding: 0;
|
|
169
|
+
font: inherit;
|
|
170
|
+
text-align: left;
|
|
171
|
+
}
|
|
165
172
|
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
166
173
|
.ue-ins__empty { color: #6e7681; }
|
|
167
174
|
|
|
@@ -172,6 +179,43 @@ var STYLES = `
|
|
|
172
179
|
.ue-ins__dir--in { color: #3fb950; }
|
|
173
180
|
.ue-ins__scope { color: #e6edf3; }
|
|
174
181
|
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
182
|
+
|
|
183
|
+
.ue-ins__tools { display: flex; gap: 6px; align-items: center; margin-bottom: 5px; }
|
|
184
|
+
.ue-ins__btn {
|
|
185
|
+
background: #21262d;
|
|
186
|
+
border: 1px solid #30363d;
|
|
187
|
+
border-radius: 5px;
|
|
188
|
+
color: #c9d1d9;
|
|
189
|
+
font: inherit;
|
|
190
|
+
font-size: 10px;
|
|
191
|
+
padding: 1px 7px;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
}
|
|
194
|
+
.ue-ins__btn[aria-pressed='true'] { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
|
195
|
+
.ue-ins__filter {
|
|
196
|
+
flex: 1;
|
|
197
|
+
min-width: 0;
|
|
198
|
+
background: #0d1117;
|
|
199
|
+
border: 1px solid #30363d;
|
|
200
|
+
border-radius: 5px;
|
|
201
|
+
color: #c9d1d9;
|
|
202
|
+
font: inherit;
|
|
203
|
+
font-size: 10px;
|
|
204
|
+
padding: 1px 6px;
|
|
205
|
+
}
|
|
206
|
+
.ue-ins__edit {
|
|
207
|
+
flex: 1;
|
|
208
|
+
min-width: 0;
|
|
209
|
+
background: #0d1117;
|
|
210
|
+
border: 1px solid #1f6feb;
|
|
211
|
+
border-radius: 4px;
|
|
212
|
+
color: #e6edf3;
|
|
213
|
+
font: inherit;
|
|
214
|
+
padding: 0 4px;
|
|
215
|
+
}
|
|
216
|
+
.ue-ins__v--editable { cursor: text; text-decoration: underline dotted #30363d; }
|
|
217
|
+
.ue-ins__v--invalid { color: #f85149; }
|
|
218
|
+
.ue-ins__paused { color: #d29922; }
|
|
175
219
|
`;
|
|
176
220
|
|
|
177
221
|
// src/devtools/inspector.tsx
|
|
@@ -190,8 +234,15 @@ function Inspector({
|
|
|
190
234
|
const [open, setOpen] = (0, import_react2.useState)(defaultOpen);
|
|
191
235
|
const [wires, setWires] = (0, import_react2.useState)([]);
|
|
192
236
|
const [crown, setCrown] = (0, import_react2.useState)(null);
|
|
237
|
+
const [paused, setPaused] = (0, import_react2.useState)(false);
|
|
238
|
+
const [filter, setFilter] = (0, import_react2.useState)("");
|
|
239
|
+
const [editing, setEditing] = (0, import_react2.useState)(null);
|
|
193
240
|
const nextId = (0, import_react2.useRef)(0);
|
|
194
241
|
const crownAt = (0, import_react2.useRef)(0);
|
|
242
|
+
const pausedRef = (0, import_react2.useRef)(false);
|
|
243
|
+
(0, import_react2.useEffect)(() => {
|
|
244
|
+
pausedRef.current = paused;
|
|
245
|
+
}, [paused]);
|
|
195
246
|
const peers = usePeers({ name });
|
|
196
247
|
const store = getSharedStore(name);
|
|
197
248
|
const subscribe = (0, import_react2.useCallback)((onChange) => store.subscribe(onChange), [store]);
|
|
@@ -217,12 +268,14 @@ function Inspector({
|
|
|
217
268
|
crownAt.current = Date.now();
|
|
218
269
|
}
|
|
219
270
|
}
|
|
271
|
+
if (pausedRef.current) return;
|
|
220
272
|
setWires(
|
|
221
273
|
(prev) => [
|
|
222
274
|
...prev.slice(-(limit - 1)),
|
|
223
275
|
{
|
|
224
276
|
id: nextId.current++,
|
|
225
277
|
direction,
|
|
278
|
+
scope: wire.scope,
|
|
226
279
|
label: wireLabel(wire),
|
|
227
280
|
from: short(wire.clientId)
|
|
228
281
|
}
|
|
@@ -247,6 +300,28 @@ function Inspector({
|
|
|
247
300
|
}, [leaseMs]);
|
|
248
301
|
const selfId = store.clientId;
|
|
249
302
|
const entries = Object.entries(versions);
|
|
303
|
+
const needle = filter.trim().toLowerCase();
|
|
304
|
+
const shown = needle ? wires.filter(
|
|
305
|
+
(wire) => wire.label.toLowerCase().includes(needle) || wire.from.toLowerCase().includes(needle)
|
|
306
|
+
) : wires;
|
|
307
|
+
const commit = (key, draft) => {
|
|
308
|
+
let value;
|
|
309
|
+
try {
|
|
310
|
+
value = JSON.parse(draft);
|
|
311
|
+
} catch {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
store.set(key, value);
|
|
315
|
+
setEditing(null);
|
|
316
|
+
};
|
|
317
|
+
const draftIsValid = (draft) => {
|
|
318
|
+
try {
|
|
319
|
+
JSON.parse(draft);
|
|
320
|
+
return true;
|
|
321
|
+
} catch {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
};
|
|
250
325
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `ue-ins ue-ins--${position}`, "data-testid": "ue-inspector", children: [
|
|
251
326
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: STYLES }),
|
|
252
327
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -294,7 +369,31 @@ function Inspector({
|
|
|
294
369
|
] }),
|
|
295
370
|
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
371
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__k", children: key }),
|
|
297
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
372
|
+
editing?.key === key ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
373
|
+
"input",
|
|
374
|
+
{
|
|
375
|
+
className: `ue-ins__edit${draftIsValid(editing.draft) ? "" : " ue-ins__v--invalid"}`,
|
|
376
|
+
value: editing.draft,
|
|
377
|
+
autoFocus: true,
|
|
378
|
+
"aria-label": `Value of ${key}`,
|
|
379
|
+
onChange: (event) => setEditing({ key, draft: event.target.value }),
|
|
380
|
+
onKeyDown: (event) => {
|
|
381
|
+
if (event.key === "Enter") commit(key, editing.draft);
|
|
382
|
+
if (event.key === "Escape") setEditing(null);
|
|
383
|
+
},
|
|
384
|
+
onBlur: () => setEditing(null),
|
|
385
|
+
"data-testid": `ue-edit-${key}`
|
|
386
|
+
}
|
|
387
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
388
|
+
"button",
|
|
389
|
+
{
|
|
390
|
+
type: "button",
|
|
391
|
+
className: "ue-ins__v ue-ins__v--editable",
|
|
392
|
+
onClick: () => setEditing({ key, draft: JSON.stringify(snapshot[key]) ?? "" }),
|
|
393
|
+
"data-testid": `ue-value-${key}`,
|
|
394
|
+
children: JSON.stringify(snapshot[key])
|
|
395
|
+
}
|
|
396
|
+
),
|
|
298
397
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ue-ins__ver", children: [
|
|
299
398
|
version[0],
|
|
300
399
|
"\xB7",
|
|
@@ -305,10 +404,46 @@ function Inspector({
|
|
|
305
404
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__section", children: [
|
|
306
405
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__h", children: [
|
|
307
406
|
"Wires (",
|
|
308
|
-
|
|
309
|
-
"
|
|
407
|
+
shown.length,
|
|
408
|
+
shown.length === wires.length ? "" : ` of ${wires.length}`,
|
|
409
|
+
")",
|
|
410
|
+
paused ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__paused", children: " \xB7 paused" }) : null
|
|
411
|
+
] }),
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__tools", children: [
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
414
|
+
"button",
|
|
415
|
+
{
|
|
416
|
+
type: "button",
|
|
417
|
+
className: "ue-ins__btn",
|
|
418
|
+
"aria-pressed": paused,
|
|
419
|
+
onClick: () => setPaused((value) => !value),
|
|
420
|
+
"data-testid": "ue-pause",
|
|
421
|
+
children: paused ? "resume" : "pause"
|
|
422
|
+
}
|
|
423
|
+
),
|
|
424
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
425
|
+
"button",
|
|
426
|
+
{
|
|
427
|
+
type: "button",
|
|
428
|
+
className: "ue-ins__btn",
|
|
429
|
+
onClick: () => setWires([]),
|
|
430
|
+
"data-testid": "ue-clear",
|
|
431
|
+
children: "clear"
|
|
432
|
+
}
|
|
433
|
+
),
|
|
434
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
435
|
+
"input",
|
|
436
|
+
{
|
|
437
|
+
className: "ue-ins__filter",
|
|
438
|
+
value: filter,
|
|
439
|
+
placeholder: "filter",
|
|
440
|
+
"aria-label": "Filter wires",
|
|
441
|
+
onChange: (event) => setFilter(event.target.value),
|
|
442
|
+
"data-testid": "ue-filter"
|
|
443
|
+
}
|
|
444
|
+
)
|
|
310
445
|
] }),
|
|
311
|
-
|
|
446
|
+
shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__empty", children: wires.length === 0 ? "nothing yet" : "no matches" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ue-ins__log", children: shown.map((wire) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ue-ins__wire", children: [
|
|
312
447
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `ue-ins__dir ue-ins__dir--${wire.direction}`, children: wire.direction === "out" ? "\u2192" : "\u2190" }),
|
|
313
448
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__scope", children: wire.label }),
|
|
314
449
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__from", children: wire.from })
|
package/dist/devtools/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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
8
|
import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
@@ -57,6 +57,13 @@ var STYLES = `
|
|
|
57
57
|
.ue-ins__row { display: flex; gap: 8px; padding: 1px 0; }
|
|
58
58
|
.ue-ins__k { color: #79c0ff; flex: none; }
|
|
59
59
|
.ue-ins__v { color: #e6edf3; overflow-wrap: anywhere; }
|
|
60
|
+
button.ue-ins__v {
|
|
61
|
+
background: none;
|
|
62
|
+
border: 0;
|
|
63
|
+
padding: 0;
|
|
64
|
+
font: inherit;
|
|
65
|
+
text-align: left;
|
|
66
|
+
}
|
|
60
67
|
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
61
68
|
.ue-ins__empty { color: #6e7681; }
|
|
62
69
|
|
|
@@ -67,6 +74,43 @@ var STYLES = `
|
|
|
67
74
|
.ue-ins__dir--in { color: #3fb950; }
|
|
68
75
|
.ue-ins__scope { color: #e6edf3; }
|
|
69
76
|
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
77
|
+
|
|
78
|
+
.ue-ins__tools { display: flex; gap: 6px; align-items: center; margin-bottom: 5px; }
|
|
79
|
+
.ue-ins__btn {
|
|
80
|
+
background: #21262d;
|
|
81
|
+
border: 1px solid #30363d;
|
|
82
|
+
border-radius: 5px;
|
|
83
|
+
color: #c9d1d9;
|
|
84
|
+
font: inherit;
|
|
85
|
+
font-size: 10px;
|
|
86
|
+
padding: 1px 7px;
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
}
|
|
89
|
+
.ue-ins__btn[aria-pressed='true'] { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
|
90
|
+
.ue-ins__filter {
|
|
91
|
+
flex: 1;
|
|
92
|
+
min-width: 0;
|
|
93
|
+
background: #0d1117;
|
|
94
|
+
border: 1px solid #30363d;
|
|
95
|
+
border-radius: 5px;
|
|
96
|
+
color: #c9d1d9;
|
|
97
|
+
font: inherit;
|
|
98
|
+
font-size: 10px;
|
|
99
|
+
padding: 1px 6px;
|
|
100
|
+
}
|
|
101
|
+
.ue-ins__edit {
|
|
102
|
+
flex: 1;
|
|
103
|
+
min-width: 0;
|
|
104
|
+
background: #0d1117;
|
|
105
|
+
border: 1px solid #1f6feb;
|
|
106
|
+
border-radius: 4px;
|
|
107
|
+
color: #e6edf3;
|
|
108
|
+
font: inherit;
|
|
109
|
+
padding: 0 4px;
|
|
110
|
+
}
|
|
111
|
+
.ue-ins__v--editable { cursor: text; text-decoration: underline dotted #30363d; }
|
|
112
|
+
.ue-ins__v--invalid { color: #f85149; }
|
|
113
|
+
.ue-ins__paused { color: #d29922; }
|
|
70
114
|
`;
|
|
71
115
|
|
|
72
116
|
// src/devtools/inspector.tsx
|
|
@@ -85,8 +129,15 @@ function Inspector({
|
|
|
85
129
|
const [open, setOpen] = useState(defaultOpen);
|
|
86
130
|
const [wires, setWires] = useState([]);
|
|
87
131
|
const [crown, setCrown] = useState(null);
|
|
132
|
+
const [paused, setPaused] = useState(false);
|
|
133
|
+
const [filter, setFilter] = useState("");
|
|
134
|
+
const [editing, setEditing] = useState(null);
|
|
88
135
|
const nextId = useRef(0);
|
|
89
136
|
const crownAt = useRef(0);
|
|
137
|
+
const pausedRef = useRef(false);
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
pausedRef.current = paused;
|
|
140
|
+
}, [paused]);
|
|
90
141
|
const peers = usePeers({ name });
|
|
91
142
|
const store = getSharedStore(name);
|
|
92
143
|
const subscribe = useCallback((onChange) => store.subscribe(onChange), [store]);
|
|
@@ -112,12 +163,14 @@ function Inspector({
|
|
|
112
163
|
crownAt.current = Date.now();
|
|
113
164
|
}
|
|
114
165
|
}
|
|
166
|
+
if (pausedRef.current) return;
|
|
115
167
|
setWires(
|
|
116
168
|
(prev) => [
|
|
117
169
|
...prev.slice(-(limit - 1)),
|
|
118
170
|
{
|
|
119
171
|
id: nextId.current++,
|
|
120
172
|
direction,
|
|
173
|
+
scope: wire.scope,
|
|
121
174
|
label: wireLabel(wire),
|
|
122
175
|
from: short(wire.clientId)
|
|
123
176
|
}
|
|
@@ -142,6 +195,28 @@ function Inspector({
|
|
|
142
195
|
}, [leaseMs]);
|
|
143
196
|
const selfId = store.clientId;
|
|
144
197
|
const entries = Object.entries(versions);
|
|
198
|
+
const needle = filter.trim().toLowerCase();
|
|
199
|
+
const shown = needle ? wires.filter(
|
|
200
|
+
(wire) => wire.label.toLowerCase().includes(needle) || wire.from.toLowerCase().includes(needle)
|
|
201
|
+
) : wires;
|
|
202
|
+
const commit = (key, draft) => {
|
|
203
|
+
let value;
|
|
204
|
+
try {
|
|
205
|
+
value = JSON.parse(draft);
|
|
206
|
+
} catch {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
store.set(key, value);
|
|
210
|
+
setEditing(null);
|
|
211
|
+
};
|
|
212
|
+
const draftIsValid = (draft) => {
|
|
213
|
+
try {
|
|
214
|
+
JSON.parse(draft);
|
|
215
|
+
return true;
|
|
216
|
+
} catch {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
145
220
|
return /* @__PURE__ */ jsxs("div", { className: `ue-ins ue-ins--${position}`, "data-testid": "ue-inspector", children: [
|
|
146
221
|
/* @__PURE__ */ jsx("style", { children: STYLES }),
|
|
147
222
|
/* @__PURE__ */ jsxs(
|
|
@@ -189,7 +264,31 @@ function Inspector({
|
|
|
189
264
|
] }),
|
|
190
265
|
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
266
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__k", children: key }),
|
|
192
|
-
/* @__PURE__ */ jsx(
|
|
267
|
+
editing?.key === key ? /* @__PURE__ */ jsx(
|
|
268
|
+
"input",
|
|
269
|
+
{
|
|
270
|
+
className: `ue-ins__edit${draftIsValid(editing.draft) ? "" : " ue-ins__v--invalid"}`,
|
|
271
|
+
value: editing.draft,
|
|
272
|
+
autoFocus: true,
|
|
273
|
+
"aria-label": `Value of ${key}`,
|
|
274
|
+
onChange: (event) => setEditing({ key, draft: event.target.value }),
|
|
275
|
+
onKeyDown: (event) => {
|
|
276
|
+
if (event.key === "Enter") commit(key, editing.draft);
|
|
277
|
+
if (event.key === "Escape") setEditing(null);
|
|
278
|
+
},
|
|
279
|
+
onBlur: () => setEditing(null),
|
|
280
|
+
"data-testid": `ue-edit-${key}`
|
|
281
|
+
}
|
|
282
|
+
) : /* @__PURE__ */ jsx(
|
|
283
|
+
"button",
|
|
284
|
+
{
|
|
285
|
+
type: "button",
|
|
286
|
+
className: "ue-ins__v ue-ins__v--editable",
|
|
287
|
+
onClick: () => setEditing({ key, draft: JSON.stringify(snapshot[key]) ?? "" }),
|
|
288
|
+
"data-testid": `ue-value-${key}`,
|
|
289
|
+
children: JSON.stringify(snapshot[key])
|
|
290
|
+
}
|
|
291
|
+
),
|
|
193
292
|
/* @__PURE__ */ jsxs("span", { className: "ue-ins__ver", children: [
|
|
194
293
|
version[0],
|
|
195
294
|
"\xB7",
|
|
@@ -200,10 +299,46 @@ function Inspector({
|
|
|
200
299
|
/* @__PURE__ */ jsxs("div", { className: "ue-ins__section", children: [
|
|
201
300
|
/* @__PURE__ */ jsxs("div", { className: "ue-ins__h", children: [
|
|
202
301
|
"Wires (",
|
|
203
|
-
|
|
204
|
-
"
|
|
302
|
+
shown.length,
|
|
303
|
+
shown.length === wires.length ? "" : ` of ${wires.length}`,
|
|
304
|
+
")",
|
|
305
|
+
paused ? /* @__PURE__ */ jsx("span", { className: "ue-ins__paused", children: " \xB7 paused" }) : null
|
|
306
|
+
] }),
|
|
307
|
+
/* @__PURE__ */ jsxs("div", { className: "ue-ins__tools", children: [
|
|
308
|
+
/* @__PURE__ */ jsx(
|
|
309
|
+
"button",
|
|
310
|
+
{
|
|
311
|
+
type: "button",
|
|
312
|
+
className: "ue-ins__btn",
|
|
313
|
+
"aria-pressed": paused,
|
|
314
|
+
onClick: () => setPaused((value) => !value),
|
|
315
|
+
"data-testid": "ue-pause",
|
|
316
|
+
children: paused ? "resume" : "pause"
|
|
317
|
+
}
|
|
318
|
+
),
|
|
319
|
+
/* @__PURE__ */ jsx(
|
|
320
|
+
"button",
|
|
321
|
+
{
|
|
322
|
+
type: "button",
|
|
323
|
+
className: "ue-ins__btn",
|
|
324
|
+
onClick: () => setWires([]),
|
|
325
|
+
"data-testid": "ue-clear",
|
|
326
|
+
children: "clear"
|
|
327
|
+
}
|
|
328
|
+
),
|
|
329
|
+
/* @__PURE__ */ jsx(
|
|
330
|
+
"input",
|
|
331
|
+
{
|
|
332
|
+
className: "ue-ins__filter",
|
|
333
|
+
value: filter,
|
|
334
|
+
placeholder: "filter",
|
|
335
|
+
"aria-label": "Filter wires",
|
|
336
|
+
onChange: (event) => setFilter(event.target.value),
|
|
337
|
+
"data-testid": "ue-filter"
|
|
338
|
+
}
|
|
339
|
+
)
|
|
205
340
|
] }),
|
|
206
|
-
|
|
341
|
+
shown.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ue-ins__empty", children: wires.length === 0 ? "nothing yet" : "no matches" }) : /* @__PURE__ */ jsx("div", { className: "ue-ins__log", children: shown.map((wire) => /* @__PURE__ */ jsxs("div", { className: "ue-ins__wire", children: [
|
|
207
342
|
/* @__PURE__ */ jsx("span", { className: `ue-ins__dir ue-ins__dir--${wire.direction}`, children: wire.direction === "out" ? "\u2192" : "\u2190" }),
|
|
208
343
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__scope", children: wire.label }),
|
|
209
344
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__from", children: wire.from })
|
package/dist/index.cjs
CHANGED
|
@@ -85,10 +85,17 @@ try {
|
|
|
85
85
|
} catch {
|
|
86
86
|
}
|
|
87
87
|
var warned = /* @__PURE__ */ new Set();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
var DOCS = "https://rxova.org/packages/use-everywhere/errors";
|
|
89
|
+
function diagnostic(code, message) {
|
|
90
|
+
return `[use-everywhere] ${code}: ${message}
|
|
91
|
+
\u2192 ${DOCS}/#${code.toLowerCase()}`;
|
|
92
|
+
}
|
|
93
|
+
function devWarn(code, message) {
|
|
94
|
+
if (!inDev) return;
|
|
95
|
+
const line = diagnostic(code, message);
|
|
96
|
+
if (warned.has(line)) return;
|
|
97
|
+
warned.add(line);
|
|
98
|
+
console.warn(line);
|
|
92
99
|
}
|
|
93
100
|
var seenInitials = /* @__PURE__ */ new Map();
|
|
94
101
|
function warnOnInitialMismatch(storeName, key, initial) {
|
|
@@ -102,7 +109,8 @@ function warnOnInitialMismatch(storeName, key, initial) {
|
|
|
102
109
|
const comparable = (v) => v === null || typeof v !== "object";
|
|
103
110
|
if (comparable(first) && comparable(initial) && !Object.is(first, initial)) {
|
|
104
111
|
devWarn(
|
|
105
|
-
|
|
112
|
+
"UE2001",
|
|
113
|
+
`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
114
|
);
|
|
107
115
|
}
|
|
108
116
|
}
|
|
@@ -188,7 +196,8 @@ function configureStore(name, scope, options) {
|
|
|
188
196
|
if (configSignature(storeConfig.get(key)) === configSignature(options)) return;
|
|
189
197
|
if (process.env.NODE_ENV !== "production") {
|
|
190
198
|
devWarn(
|
|
191
|
-
|
|
199
|
+
"UE2002",
|
|
200
|
+
`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
201
|
);
|
|
193
202
|
}
|
|
194
203
|
return;
|
|
@@ -232,7 +241,8 @@ function warnOnLeaderOptionConflict(name, options) {
|
|
|
232
241
|
if (requested !== void 0 && requested !== first?.[key]) {
|
|
233
242
|
if (process.env.NODE_ENV !== "production") {
|
|
234
243
|
devWarn(
|
|
235
|
-
|
|
244
|
+
"UE2003",
|
|
245
|
+
`leader "${name}": ${key} ignored \u2014 the first useLeader/getLeader call fixes the election timings for this tab.`
|
|
236
246
|
);
|
|
237
247
|
}
|
|
238
248
|
}
|
|
@@ -246,7 +256,8 @@ function configureChannel(name, options) {
|
|
|
246
256
|
if (before.join() === after.join()) return;
|
|
247
257
|
if (process.env.NODE_ENV !== "production") {
|
|
248
258
|
devWarn(
|
|
249
|
-
|
|
259
|
+
"UE2004",
|
|
260
|
+
`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
261
|
);
|
|
251
262
|
}
|
|
252
263
|
return;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-everywhere",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.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>",
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
"name": "Inspector (devtools subpath)",
|
|
124
124
|
"path": "dist/devtools/index.js",
|
|
125
125
|
"import": "{ Inspector }",
|
|
126
|
-
"limit": "6.
|
|
126
|
+
"limit": "6.70 kB"
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
129
|
"name": "MemoryHub (testing subpath)",
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
}
|
|
134
134
|
],
|
|
135
135
|
"dependencies": {
|
|
136
|
-
"@use-everywhere/core": "0.
|
|
136
|
+
"@use-everywhere/core": "0.9.0"
|
|
137
137
|
},
|
|
138
138
|
"peerDependencies": {
|
|
139
139
|
"react": ">=18"
|