use-everywhere 0.9.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/dist/devtools/index.cjs +215 -130
- package/dist/devtools/index.d.cts +13 -2
- package/dist/devtools/index.d.ts +13 -2
- package/dist/devtools/index.js +215 -132
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- 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/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,130 +118,28 @@ 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
|
-
button.ue-ins__v {
|
|
166
|
-
background: none;
|
|
167
|
-
border: 0;
|
|
168
|
-
padding: 0;
|
|
169
|
-
font: inherit;
|
|
170
|
-
text-align: left;
|
|
171
|
-
}
|
|
172
|
-
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
173
|
-
.ue-ins__empty { color: #6e7681; }
|
|
174
|
-
|
|
175
|
-
.ue-ins__log { display: flex; flex-direction: column-reverse; max-height: 190px; overflow-y: auto; }
|
|
176
|
-
.ue-ins__wire { display: flex; gap: 7px; padding: 1px 0; white-space: nowrap; }
|
|
177
|
-
.ue-ins__dir { flex: none; width: 9px; }
|
|
178
|
-
.ue-ins__dir--out { color: #d29922; }
|
|
179
|
-
.ue-ins__dir--in { color: #3fb950; }
|
|
180
|
-
.ue-ins__scope { color: #e6edf3; }
|
|
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; }
|
|
219
|
-
`;
|
|
220
|
-
|
|
221
|
-
// src/devtools/inspector.tsx
|
|
121
|
+
// src/devtools/panel.tsx
|
|
222
122
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
223
123
|
var short = (id) => id.slice(0, 6);
|
|
224
124
|
function wireLabel(wire) {
|
|
225
125
|
return `${wire.scope}/${wire.type}`;
|
|
226
126
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
limit
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
127
|
+
var SCOPES = ["all", "state", "leader", "presence", "channel"];
|
|
128
|
+
function Panel({
|
|
129
|
+
name,
|
|
130
|
+
limit,
|
|
131
|
+
leaseMs,
|
|
132
|
+
position,
|
|
133
|
+
defaultOpen
|
|
134
|
+
}) {
|
|
234
135
|
const [open, setOpen] = (0, import_react2.useState)(defaultOpen);
|
|
235
136
|
const [wires, setWires] = (0, import_react2.useState)([]);
|
|
236
137
|
const [crown, setCrown] = (0, import_react2.useState)(null);
|
|
237
138
|
const [paused, setPaused] = (0, import_react2.useState)(false);
|
|
238
139
|
const [filter, setFilter] = (0, import_react2.useState)("");
|
|
140
|
+
const [scopeView, setScopeView] = (0, import_react2.useState)("all");
|
|
239
141
|
const [editing, setEditing] = (0, import_react2.useState)(null);
|
|
142
|
+
const [frames, setFrames] = (0, import_react2.useState)([]);
|
|
240
143
|
const nextId = (0, import_react2.useRef)(0);
|
|
241
144
|
const crownAt = (0, import_react2.useRef)(0);
|
|
242
145
|
const pausedRef = (0, import_react2.useRef)(false);
|
|
@@ -269,20 +172,21 @@ function Inspector({
|
|
|
269
172
|
}
|
|
270
173
|
}
|
|
271
174
|
if (pausedRef.current) return;
|
|
175
|
+
const id = nextId.current++;
|
|
176
|
+
const label = wireLabel(wire);
|
|
272
177
|
setWires(
|
|
273
178
|
(prev) => [
|
|
274
179
|
...prev.slice(-(limit - 1)),
|
|
275
|
-
{
|
|
276
|
-
id: nextId.current++,
|
|
277
|
-
direction,
|
|
278
|
-
scope: wire.scope,
|
|
279
|
-
label: wireLabel(wire),
|
|
280
|
-
from: short(wire.clientId)
|
|
281
|
-
}
|
|
180
|
+
{ id, direction, scope: wire.scope, label, from: short(wire.clientId) }
|
|
282
181
|
].slice(-limit)
|
|
283
182
|
);
|
|
183
|
+
if (wire.scope === "state") {
|
|
184
|
+
setFrames(
|
|
185
|
+
(prev) => [...prev, { wireId: id, label, snapshot: { ...store.getSnapshot() } }].slice(-limit)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
284
188
|
});
|
|
285
|
-
}, [name, limit]);
|
|
189
|
+
}, [name, limit, store]);
|
|
286
190
|
(0, import_react2.useEffect)(() => {
|
|
287
191
|
const timer = setInterval(
|
|
288
192
|
() => {
|
|
@@ -291,9 +195,6 @@ function Inspector({
|
|
|
291
195
|
crownAt.current = 0;
|
|
292
196
|
}
|
|
293
197
|
},
|
|
294
|
-
// Quarter of the lease, so a vacated crown clears well within it. The
|
|
295
|
-
// floor is low enough that a short lease still works rather than being
|
|
296
|
-
// silently rounded up to something coarser than the lease itself.
|
|
297
198
|
Math.max(50, Math.floor(leaseMs / 4))
|
|
298
199
|
);
|
|
299
200
|
return () => clearInterval(timer);
|
|
@@ -301,9 +202,11 @@ function Inspector({
|
|
|
301
202
|
const selfId = store.clientId;
|
|
302
203
|
const entries = Object.entries(versions);
|
|
303
204
|
const needle = filter.trim().toLowerCase();
|
|
304
|
-
const shown =
|
|
305
|
-
(
|
|
306
|
-
|
|
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
|
+
});
|
|
307
210
|
const commit = (key, draft) => {
|
|
308
211
|
let value;
|
|
309
212
|
try {
|
|
@@ -322,8 +225,13 @@ function Inspector({
|
|
|
322
225
|
return false;
|
|
323
226
|
}
|
|
324
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
|
+
};
|
|
325
234
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `ue-ins ue-ins--${position}`, "data-testid": "ue-inspector", children: [
|
|
326
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: STYLES }),
|
|
327
235
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
328
236
|
"button",
|
|
329
237
|
{
|
|
@@ -426,7 +334,10 @@ function Inspector({
|
|
|
426
334
|
{
|
|
427
335
|
type: "button",
|
|
428
336
|
className: "ue-ins__btn",
|
|
429
|
-
onClick: () =>
|
|
337
|
+
onClick: () => {
|
|
338
|
+
setWires([]);
|
|
339
|
+
setFrames([]);
|
|
340
|
+
},
|
|
430
341
|
"data-testid": "ue-clear",
|
|
431
342
|
children: "clear"
|
|
432
343
|
}
|
|
@@ -443,15 +354,189 @@ function Inspector({
|
|
|
443
354
|
}
|
|
444
355
|
)
|
|
445
356
|
] }),
|
|
446
|
-
|
|
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: [
|
|
447
370
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `ue-ins__dir ue-ins__dir--${wire.direction}`, children: wire.direction === "out" ? "\u2192" : "\u2190" }),
|
|
448
371
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__scope", children: wire.label }),
|
|
449
372
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ue-ins__from", children: wire.from })
|
|
450
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)) })
|
|
451
399
|
] })
|
|
452
400
|
] }) : null
|
|
453
401
|
] });
|
|
454
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
|
+
}
|
|
455
540
|
// Annotate the CommonJS export names for ESM import in node:
|
|
456
541
|
0 && (module.exports = {
|
|
457
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
|
@@ -5,133 +5,34 @@ import {
|
|
|
5
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; }
|
|
47
|
-
|
|
48
|
-
.ue-ins__body { max-height: 60vh; overflow-y: auto; }
|
|
49
|
-
.ue-ins__section { border-top: 1px solid #21262d; padding: 8px 10px; }
|
|
50
|
-
.ue-ins__h {
|
|
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
|
-
button.ue-ins__v {
|
|
61
|
-
background: none;
|
|
62
|
-
border: 0;
|
|
63
|
-
padding: 0;
|
|
64
|
-
font: inherit;
|
|
65
|
-
text-align: left;
|
|
66
|
-
}
|
|
67
|
-
.ue-ins__ver { color: #6e7681; margin-left: auto; flex: none; }
|
|
68
|
-
.ue-ins__empty { color: #6e7681; }
|
|
69
|
-
|
|
70
|
-
.ue-ins__log { display: flex; flex-direction: column-reverse; max-height: 190px; overflow-y: auto; }
|
|
71
|
-
.ue-ins__wire { display: flex; gap: 7px; padding: 1px 0; white-space: nowrap; }
|
|
72
|
-
.ue-ins__dir { flex: none; width: 9px; }
|
|
73
|
-
.ue-ins__dir--out { color: #d29922; }
|
|
74
|
-
.ue-ins__dir--in { color: #3fb950; }
|
|
75
|
-
.ue-ins__scope { color: #e6edf3; }
|
|
76
|
-
.ue-ins__from { color: #6e7681; margin-left: auto; }
|
|
8
|
+
import { useState as useState2 } from "react";
|
|
9
|
+
import { createPortal } from "react-dom";
|
|
10
|
+
import { DEFAULT_NAME } from "@use-everywhere/core";
|
|
77
11
|
|
|
78
|
-
.
|
|
79
|
-
|
|
80
|
-
|
|
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; }
|
|
114
|
-
`;
|
|
115
|
-
|
|
116
|
-
// 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";
|
|
117
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
118
16
|
var short = (id) => id.slice(0, 6);
|
|
119
17
|
function wireLabel(wire) {
|
|
120
18
|
return `${wire.scope}/${wire.type}`;
|
|
121
19
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
limit
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
20
|
+
var SCOPES = ["all", "state", "leader", "presence", "channel"];
|
|
21
|
+
function Panel({
|
|
22
|
+
name,
|
|
23
|
+
limit,
|
|
24
|
+
leaseMs,
|
|
25
|
+
position,
|
|
26
|
+
defaultOpen
|
|
27
|
+
}) {
|
|
129
28
|
const [open, setOpen] = useState(defaultOpen);
|
|
130
29
|
const [wires, setWires] = useState([]);
|
|
131
30
|
const [crown, setCrown] = useState(null);
|
|
132
31
|
const [paused, setPaused] = useState(false);
|
|
133
32
|
const [filter, setFilter] = useState("");
|
|
33
|
+
const [scopeView, setScopeView] = useState("all");
|
|
134
34
|
const [editing, setEditing] = useState(null);
|
|
35
|
+
const [frames, setFrames] = useState([]);
|
|
135
36
|
const nextId = useRef(0);
|
|
136
37
|
const crownAt = useRef(0);
|
|
137
38
|
const pausedRef = useRef(false);
|
|
@@ -164,20 +65,21 @@ function Inspector({
|
|
|
164
65
|
}
|
|
165
66
|
}
|
|
166
67
|
if (pausedRef.current) return;
|
|
68
|
+
const id = nextId.current++;
|
|
69
|
+
const label = wireLabel(wire);
|
|
167
70
|
setWires(
|
|
168
71
|
(prev) => [
|
|
169
72
|
...prev.slice(-(limit - 1)),
|
|
170
|
-
{
|
|
171
|
-
id: nextId.current++,
|
|
172
|
-
direction,
|
|
173
|
-
scope: wire.scope,
|
|
174
|
-
label: wireLabel(wire),
|
|
175
|
-
from: short(wire.clientId)
|
|
176
|
-
}
|
|
73
|
+
{ id, direction, scope: wire.scope, label, from: short(wire.clientId) }
|
|
177
74
|
].slice(-limit)
|
|
178
75
|
);
|
|
76
|
+
if (wire.scope === "state") {
|
|
77
|
+
setFrames(
|
|
78
|
+
(prev) => [...prev, { wireId: id, label, snapshot: { ...store.getSnapshot() } }].slice(-limit)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
179
81
|
});
|
|
180
|
-
}, [name, limit]);
|
|
82
|
+
}, [name, limit, store]);
|
|
181
83
|
useEffect(() => {
|
|
182
84
|
const timer = setInterval(
|
|
183
85
|
() => {
|
|
@@ -186,9 +88,6 @@ function Inspector({
|
|
|
186
88
|
crownAt.current = 0;
|
|
187
89
|
}
|
|
188
90
|
},
|
|
189
|
-
// Quarter of the lease, so a vacated crown clears well within it. The
|
|
190
|
-
// floor is low enough that a short lease still works rather than being
|
|
191
|
-
// silently rounded up to something coarser than the lease itself.
|
|
192
91
|
Math.max(50, Math.floor(leaseMs / 4))
|
|
193
92
|
);
|
|
194
93
|
return () => clearInterval(timer);
|
|
@@ -196,9 +95,11 @@ function Inspector({
|
|
|
196
95
|
const selfId = store.clientId;
|
|
197
96
|
const entries = Object.entries(versions);
|
|
198
97
|
const needle = filter.trim().toLowerCase();
|
|
199
|
-
const shown =
|
|
200
|
-
(
|
|
201
|
-
|
|
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
|
+
});
|
|
202
103
|
const commit = (key, draft) => {
|
|
203
104
|
let value;
|
|
204
105
|
try {
|
|
@@ -217,8 +118,13 @@ function Inspector({
|
|
|
217
118
|
return false;
|
|
218
119
|
}
|
|
219
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
|
+
};
|
|
220
127
|
return /* @__PURE__ */ jsxs("div", { className: `ue-ins ue-ins--${position}`, "data-testid": "ue-inspector", children: [
|
|
221
|
-
/* @__PURE__ */ jsx("style", { children: STYLES }),
|
|
222
128
|
/* @__PURE__ */ jsxs(
|
|
223
129
|
"button",
|
|
224
130
|
{
|
|
@@ -321,7 +227,10 @@ function Inspector({
|
|
|
321
227
|
{
|
|
322
228
|
type: "button",
|
|
323
229
|
className: "ue-ins__btn",
|
|
324
|
-
onClick: () =>
|
|
230
|
+
onClick: () => {
|
|
231
|
+
setWires([]);
|
|
232
|
+
setFrames([]);
|
|
233
|
+
},
|
|
325
234
|
"data-testid": "ue-clear",
|
|
326
235
|
children: "clear"
|
|
327
236
|
}
|
|
@@ -338,15 +247,189 @@ function Inspector({
|
|
|
338
247
|
}
|
|
339
248
|
)
|
|
340
249
|
] }),
|
|
341
|
-
|
|
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: [
|
|
342
263
|
/* @__PURE__ */ jsx("span", { className: `ue-ins__dir ue-ins__dir--${wire.direction}`, children: wire.direction === "out" ? "\u2192" : "\u2190" }),
|
|
343
264
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__scope", children: wire.label }),
|
|
344
265
|
/* @__PURE__ */ jsx("span", { className: "ue-ins__from", children: wire.from })
|
|
345
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)) })
|
|
346
292
|
] })
|
|
347
293
|
] }) : null
|
|
348
294
|
] });
|
|
349
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
|
+
}
|
|
350
433
|
export {
|
|
351
434
|
Inspector
|
|
352
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,
|
|
@@ -591,6 +593,7 @@ var import_core4 = require("@use-everywhere/core");
|
|
|
591
593
|
DEFAULT_NAME,
|
|
592
594
|
HandshakeTimeoutError,
|
|
593
595
|
NoopTransport,
|
|
596
|
+
SharedWorkerTransport,
|
|
594
597
|
StorageTransport,
|
|
595
598
|
WIRE_VERSION,
|
|
596
599
|
WindowClosedError,
|
|
@@ -612,6 +615,7 @@ var import_core4 = require("@use-everywhere/core");
|
|
|
612
615
|
getWireSkew,
|
|
613
616
|
indexedDbAdapter,
|
|
614
617
|
isBroadcastChannelAvailable,
|
|
618
|
+
isSharedWorkerAvailable,
|
|
615
619
|
isStorageEventAvailable,
|
|
616
620
|
jsonSerializer,
|
|
617
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
|
@@ -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
|
]
|