@jtfmumm/patchwork-standalone-frame 0.1.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 +34 -0
- package/dist/confirm-modal.d.ts +10 -0
- package/dist/doc-history.d.ts +10 -0
- package/dist/frame.d.ts +10 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +711 -0
- package/dist/modal-styles.d.ts +17 -0
- package/dist/mount.d.ts +2 -0
- package/dist/new-doc-modal.d.ts +8 -0
- package/dist/share-modal.d.ts +10 -0
- package/dist/url-hash.d.ts +3 -0
- package/package.json +39 -0
- package/src/confirm-modal.tsx +68 -0
- package/src/doc-history.ts +58 -0
- package/src/frame.tsx +660 -0
- package/src/index.ts +25 -0
- package/src/modal-styles.ts +18 -0
- package/src/mount.tsx +10 -0
- package/src/new-doc-modal.tsx +98 -0
- package/src/share-modal.tsx +349 -0
- package/src/url-hash.ts +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
import { delegateEvents as ve, createComponent as g, insert as s, effect as I, style as z, memo as te, setStyleProperty as X, template as $, use as Me, setAttribute as je, render as Je } from "solid-js/web";
|
|
2
|
+
import { createSignal as w, createMemo as Q, createEffect as se, onCleanup as Z, Show as k, For as Re, onMount as be } from "solid-js";
|
|
3
|
+
import { Repo as We } from "@automerge/automerge-repo";
|
|
4
|
+
import { IndexedDBStorageAdapter as Ae } from "@automerge/automerge-repo-storage-indexeddb";
|
|
5
|
+
import { BrowserWebSocketClientAdapter as Ke } from "@automerge/automerge-repo-network-websocket";
|
|
6
|
+
import { docIdFromAutomergeUrl as $e, uint8ArrayToHex as de, ContactCard as Le, Identifier as He, Access as De, initKeyhiveWasm as Be, initializeAutomergeRepoKeyhive as Ye } from "@automerge/automerge-repo-keyhive";
|
|
7
|
+
const Ve = 100;
|
|
8
|
+
function Pe(e, t) {
|
|
9
|
+
return `${e}-doc-history-${t}`;
|
|
10
|
+
}
|
|
11
|
+
function me(e, t) {
|
|
12
|
+
return `${e}-standalone-${t}`;
|
|
13
|
+
}
|
|
14
|
+
function we(e, t) {
|
|
15
|
+
try {
|
|
16
|
+
const a = localStorage.getItem(Pe(e, t));
|
|
17
|
+
return a ? JSON.parse(a) : [];
|
|
18
|
+
} catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function Fe(e, t, a) {
|
|
23
|
+
localStorage.setItem(Pe(e, t), JSON.stringify(a));
|
|
24
|
+
}
|
|
25
|
+
function Ie(e, t, a, y) {
|
|
26
|
+
const b = we(e, t), f = b.findIndex((A) => A.url === a);
|
|
27
|
+
f !== -1 ? (b[f].title = y, b[f].lastOpened = Date.now()) : b.push({ url: a, title: y, lastOpened: Date.now() }), b.sort((A, x) => x.lastOpened - A.lastOpened);
|
|
28
|
+
const C = b.slice(0, Ve);
|
|
29
|
+
return Fe(e, t, C), C;
|
|
30
|
+
}
|
|
31
|
+
function qe(e, t, a) {
|
|
32
|
+
const y = we(e, t).filter((b) => b.url !== a);
|
|
33
|
+
return Fe(e, t, y), y;
|
|
34
|
+
}
|
|
35
|
+
function Ge(e) {
|
|
36
|
+
const t = "automerge:";
|
|
37
|
+
if (e.startsWith(t)) {
|
|
38
|
+
const a = e.slice(t.length);
|
|
39
|
+
return t + a.slice(0, 12) + "...";
|
|
40
|
+
}
|
|
41
|
+
return e;
|
|
42
|
+
}
|
|
43
|
+
function Te() {
|
|
44
|
+
const e = window.location.hash.slice(1);
|
|
45
|
+
return e && e.startsWith("automerge:") ? e : null;
|
|
46
|
+
}
|
|
47
|
+
function le(e) {
|
|
48
|
+
window.history.replaceState(null, "", `#${e}`);
|
|
49
|
+
}
|
|
50
|
+
const ke = {
|
|
51
|
+
position: "fixed",
|
|
52
|
+
inset: "0",
|
|
53
|
+
background: "rgba(0,0,0,0.5)",
|
|
54
|
+
display: "flex",
|
|
55
|
+
"align-items": "center",
|
|
56
|
+
"justify-content": "center",
|
|
57
|
+
"z-index": "2000"
|
|
58
|
+
}, Ce = {
|
|
59
|
+
background: "#191e24",
|
|
60
|
+
color: "#edf2f7",
|
|
61
|
+
"border-radius": "8px",
|
|
62
|
+
padding: "20px 24px",
|
|
63
|
+
"box-shadow": "0 8px 24px rgba(0,0,0,0.5)",
|
|
64
|
+
"font-family": "system-ui, sans-serif"
|
|
65
|
+
};
|
|
66
|
+
var Qe = /* @__PURE__ */ $("<span style=font-size:13px>This document is <strong>public"), Xe = /* @__PURE__ */ $("<button>Revoke Public Access"), Ze = /* @__PURE__ */ $("<button>Make Public"), ze = /* @__PURE__ */ $("<hr>"), et = /* @__PURE__ */ $('<form><textarea placeholder="Paste ContactCard JSON..."rows=3 style="width:100%;background:#15191e;border:1px solid #2a323c;color:#edf2f7;border-radius:4px;padding:6px 8px;font-size:12px;font-family:monospace;resize:vertical;box-sizing:border-box"></textarea><div style=display:flex;justify-content:flex-end;margin-top:6px><button type=submit>'), tt = /* @__PURE__ */ $("<p style=font-size:13px;color:#6b7280>Loading..."), nt = /* @__PURE__ */ $("<p style=font-size:13px;color:#6b7280>No users have access yet"), rt = /* @__PURE__ */ $("<div>"), it = /* @__PURE__ */ $('<div><div><div style=display:flex;justify-content:space-between;align-items:center;margin-bottom:8px><h2 style=margin:0;font-size:16px>Share this document</h2><button aria-label="Close modal"style="border:none;font-size:18px;padding:0 4px">×</button></div><section><h3>Public Access</h3><div style=display:flex;align-items:center;gap:12px></div></section><section><h3>Current Access'), ot = /* @__PURE__ */ $('<button aria-label="Remove member"style="color:#c66;border:1px solid #944;padding:2px 8px">Revoke'), lt = /* @__PURE__ */ $('<div style="display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-bottom:1px solid #15191e;font-size:13px"><div><span style=margin-right:8px></span><span style=color:#6b7280;font-size:11px>');
|
|
67
|
+
const Ee = ["Pull", "Read", "Write", "Admin"];
|
|
68
|
+
async function ae(e, t) {
|
|
69
|
+
const a = $e(t), y = {};
|
|
70
|
+
return (await e.docMemberCapabilities(a)).forEach((f) => {
|
|
71
|
+
const C = de(f.who.id.toBytes());
|
|
72
|
+
y[C] = f.can.toString();
|
|
73
|
+
}), y;
|
|
74
|
+
}
|
|
75
|
+
const at = {
|
|
76
|
+
...Ce,
|
|
77
|
+
width: "420px",
|
|
78
|
+
"max-height": "80vh",
|
|
79
|
+
"overflow-y": "auto"
|
|
80
|
+
}, ce = {
|
|
81
|
+
background: "none",
|
|
82
|
+
border: "1px solid #2a323c",
|
|
83
|
+
color: "#edf2f7",
|
|
84
|
+
padding: "4px 12px",
|
|
85
|
+
"border-radius": "4px",
|
|
86
|
+
cursor: "pointer",
|
|
87
|
+
"font-size": "12px"
|
|
88
|
+
}, Ue = {
|
|
89
|
+
"font-size": "13px",
|
|
90
|
+
color: "#6b7280",
|
|
91
|
+
margin: "16px 0 8px"
|
|
92
|
+
}, Oe = {
|
|
93
|
+
border: "none",
|
|
94
|
+
"border-top": "1px solid #2a323c",
|
|
95
|
+
margin: "12px 0"
|
|
96
|
+
};
|
|
97
|
+
function ct(e) {
|
|
98
|
+
const [t, a] = w(""), [y, b] = w({}), [f, C] = w(!0), [A, x] = w(void 0), [U, T] = w(!1), ne = Q(() => $e(e.docUrl)), O = Q(() => {
|
|
99
|
+
const i = e.hive.active.individual.id;
|
|
100
|
+
return i ? de(i.toBytes()) : null;
|
|
101
|
+
}), _ = Q(() => {
|
|
102
|
+
const i = e.hive.syncServer;
|
|
103
|
+
if (!i) return null;
|
|
104
|
+
const d = Le.fromJson(i.contactCard.toJson());
|
|
105
|
+
return d ? de(d.individualId.bytes) : null;
|
|
106
|
+
}), Y = Q(() => {
|
|
107
|
+
const i = He.publicId();
|
|
108
|
+
return de(i.toBytes());
|
|
109
|
+
}), N = Q(() => y()[Y()] || null), V = Q(() => A() === "Admin");
|
|
110
|
+
se(() => {
|
|
111
|
+
if (!e.isOpen) return;
|
|
112
|
+
let i = !1;
|
|
113
|
+
(async () => {
|
|
114
|
+
const d = e.hive.active.individual.id;
|
|
115
|
+
if (!d) {
|
|
116
|
+
i || x(void 0);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const L = await e.hive.accessForDoc(d, ne());
|
|
121
|
+
i || x(L ? L.toString() : void 0);
|
|
122
|
+
} catch (L) {
|
|
123
|
+
i || (console.error("[ShareModal] Error checking access:", L), x(void 0));
|
|
124
|
+
}
|
|
125
|
+
})(), Z(() => {
|
|
126
|
+
i = !0;
|
|
127
|
+
});
|
|
128
|
+
}), se(() => {
|
|
129
|
+
if (!e.isOpen) return;
|
|
130
|
+
let i = !1;
|
|
131
|
+
(async () => {
|
|
132
|
+
i || C(!0);
|
|
133
|
+
try {
|
|
134
|
+
const d = await ae(e.hive, e.docUrl);
|
|
135
|
+
i || (b(d), C(!1));
|
|
136
|
+
} catch (d) {
|
|
137
|
+
i || (console.error("[ShareModal] Error loading access list:", d), b({}), C(!1));
|
|
138
|
+
}
|
|
139
|
+
})(), Z(() => {
|
|
140
|
+
i = !0;
|
|
141
|
+
});
|
|
142
|
+
}), se(() => {
|
|
143
|
+
if (!e.isOpen) return;
|
|
144
|
+
const i = (d) => {
|
|
145
|
+
d.key === "Escape" && e.onClose();
|
|
146
|
+
};
|
|
147
|
+
document.addEventListener("keydown", i), Z(() => document.removeEventListener("keydown", i));
|
|
148
|
+
});
|
|
149
|
+
const re = async (i) => {
|
|
150
|
+
i.preventDefault();
|
|
151
|
+
const d = t().trim();
|
|
152
|
+
if (d) {
|
|
153
|
+
T(!0);
|
|
154
|
+
try {
|
|
155
|
+
const L = Le.fromJson(d);
|
|
156
|
+
if (!L) throw new Error("Invalid ContactCard JSON");
|
|
157
|
+
const q = De.tryFromString("write");
|
|
158
|
+
if (!q) throw new Error("Invalid access level");
|
|
159
|
+
await e.hive.addMemberToDoc(e.docUrl, L, q), a("");
|
|
160
|
+
} catch (L) {
|
|
161
|
+
console.error("[ShareModal]", L);
|
|
162
|
+
} finally {
|
|
163
|
+
const L = await ae(e.hive, e.docUrl);
|
|
164
|
+
b(L), T(!1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}, xe = async (i) => {
|
|
168
|
+
try {
|
|
169
|
+
await e.hive.revokeMemberFromDoc(e.docUrl, i);
|
|
170
|
+
} catch (d) {
|
|
171
|
+
console.error("[ShareModal]", d);
|
|
172
|
+
} finally {
|
|
173
|
+
const d = await ae(e.hive, e.docUrl);
|
|
174
|
+
b(d);
|
|
175
|
+
}
|
|
176
|
+
}, ie = async () => {
|
|
177
|
+
try {
|
|
178
|
+
const i = De.tryFromString("write");
|
|
179
|
+
if (!i) throw new Error("Invalid access level");
|
|
180
|
+
await e.hive.setPublicAccess(e.docUrl, i);
|
|
181
|
+
} catch (i) {
|
|
182
|
+
console.error("[ShareModal]", i);
|
|
183
|
+
} finally {
|
|
184
|
+
const i = await ae(e.hive, e.docUrl);
|
|
185
|
+
b(i);
|
|
186
|
+
}
|
|
187
|
+
}, ue = async () => {
|
|
188
|
+
try {
|
|
189
|
+
await e.hive.revokeMemberFromDoc(e.docUrl, Y());
|
|
190
|
+
} catch (i) {
|
|
191
|
+
console.error("[ShareModal]", i);
|
|
192
|
+
} finally {
|
|
193
|
+
const i = await ae(e.hive, e.docUrl);
|
|
194
|
+
b(i);
|
|
195
|
+
}
|
|
196
|
+
}, fe = (i) => `0x${i.slice(0, 12)}...`, ee = Q(() => Object.entries(y()).sort(([i], [d]) => i.localeCompare(d)));
|
|
197
|
+
return g(k, {
|
|
198
|
+
get when() {
|
|
199
|
+
return e.isOpen;
|
|
200
|
+
},
|
|
201
|
+
get children() {
|
|
202
|
+
var i = it(), d = i.firstChild, L = d.firstChild, q = L.firstChild, j = q.nextSibling, he = L.nextSibling, J = he.firstChild, oe = J.nextSibling, H = he.nextSibling, M = H.firstChild;
|
|
203
|
+
return i.$$click = (n) => {
|
|
204
|
+
n.target === n.currentTarget && e.onClose();
|
|
205
|
+
}, d.$$click = (n) => n.stopPropagation(), j.$$click = () => e.onClose(), s(oe, g(k, {
|
|
206
|
+
get when() {
|
|
207
|
+
return N();
|
|
208
|
+
},
|
|
209
|
+
get children() {
|
|
210
|
+
return Qe();
|
|
211
|
+
}
|
|
212
|
+
}), null), s(oe, g(k, {
|
|
213
|
+
get when() {
|
|
214
|
+
return V();
|
|
215
|
+
},
|
|
216
|
+
get children() {
|
|
217
|
+
return [g(k, {
|
|
218
|
+
get when() {
|
|
219
|
+
return N();
|
|
220
|
+
},
|
|
221
|
+
get children() {
|
|
222
|
+
var n = Xe();
|
|
223
|
+
return n.$$click = ue, I((u) => z(n, ce, u)), n;
|
|
224
|
+
}
|
|
225
|
+
}), g(k, {
|
|
226
|
+
get when() {
|
|
227
|
+
return !N();
|
|
228
|
+
},
|
|
229
|
+
get children() {
|
|
230
|
+
var n = Ze();
|
|
231
|
+
return n.$$click = ie, I((u) => z(n, ce, u)), n;
|
|
232
|
+
}
|
|
233
|
+
})];
|
|
234
|
+
}
|
|
235
|
+
}), null), s(d, g(k, {
|
|
236
|
+
get when() {
|
|
237
|
+
return V();
|
|
238
|
+
},
|
|
239
|
+
get children() {
|
|
240
|
+
return [(() => {
|
|
241
|
+
var n = ze();
|
|
242
|
+
return I((u) => z(n, Oe, u)), n;
|
|
243
|
+
})(), (() => {
|
|
244
|
+
var n = et(), u = n.firstChild, P = u.nextSibling, E = P.firstChild;
|
|
245
|
+
return n.addEventListener("submit", re), u.$$input = (S) => a(S.currentTarget.value), s(E, () => U() ? "Adding..." : "Add Member"), I((S) => {
|
|
246
|
+
var W = {
|
|
247
|
+
...ce,
|
|
248
|
+
opacity: U() || !t().trim() ? "0.5" : "1"
|
|
249
|
+
}, G = U() || !t().trim();
|
|
250
|
+
return S.e = z(E, W, S.e), G !== S.t && (E.disabled = S.t = G), S;
|
|
251
|
+
}, {
|
|
252
|
+
e: void 0,
|
|
253
|
+
t: void 0
|
|
254
|
+
}), I(() => u.value = t()), n;
|
|
255
|
+
})(), (() => {
|
|
256
|
+
var n = ze();
|
|
257
|
+
return I((u) => z(n, Oe, u)), n;
|
|
258
|
+
})()];
|
|
259
|
+
}
|
|
260
|
+
}), H), s(H, g(k, {
|
|
261
|
+
get when() {
|
|
262
|
+
return f();
|
|
263
|
+
},
|
|
264
|
+
get children() {
|
|
265
|
+
return tt();
|
|
266
|
+
}
|
|
267
|
+
}), null), s(H, g(k, {
|
|
268
|
+
get when() {
|
|
269
|
+
return te(() => !f())() && ee().length === 0;
|
|
270
|
+
},
|
|
271
|
+
get children() {
|
|
272
|
+
return nt();
|
|
273
|
+
}
|
|
274
|
+
}), null), s(H, g(k, {
|
|
275
|
+
get when() {
|
|
276
|
+
return te(() => !f())() && ee().length > 0;
|
|
277
|
+
},
|
|
278
|
+
get children() {
|
|
279
|
+
var n = rt();
|
|
280
|
+
return s(n, g(Re, {
|
|
281
|
+
get each() {
|
|
282
|
+
return ee();
|
|
283
|
+
},
|
|
284
|
+
children: ([u, P]) => {
|
|
285
|
+
const E = u === O(), S = u === _(), W = u === Y(), G = Ee.indexOf(A()), pe = Ee.indexOf(P), ye = G >= 0 && pe >= 0 && pe <= G && !E && !S, r = () => E ? "You" : S ? "Sync Server" : W ? "Public" : fe(u);
|
|
286
|
+
return (() => {
|
|
287
|
+
var o = lt(), h = o.firstChild, c = h.firstChild, p = c.nextSibling;
|
|
288
|
+
return X(c, "color", E ? "#7ab4f5" : W ? "#b5bd68" : "#edf2f7"), s(c, r), s(p, P), s(o, g(k, {
|
|
289
|
+
when: ye,
|
|
290
|
+
get children() {
|
|
291
|
+
var m = ot();
|
|
292
|
+
return m.$$click = () => xe(u), I((R) => z(m, {
|
|
293
|
+
...ce
|
|
294
|
+
}, R)), m;
|
|
295
|
+
}
|
|
296
|
+
}), null), o;
|
|
297
|
+
})();
|
|
298
|
+
}
|
|
299
|
+
})), n;
|
|
300
|
+
}
|
|
301
|
+
}), null), I((n) => {
|
|
302
|
+
var u = ke, P = at, E = {
|
|
303
|
+
...ce
|
|
304
|
+
}, S = Ue, W = Ue;
|
|
305
|
+
return n.e = z(i, u, n.e), n.t = z(d, P, n.t), n.a = z(j, E, n.a), n.o = z(J, S, n.o), n.i = z(M, W, n.i), n;
|
|
306
|
+
}, {
|
|
307
|
+
e: void 0,
|
|
308
|
+
t: void 0,
|
|
309
|
+
a: void 0,
|
|
310
|
+
o: void 0,
|
|
311
|
+
i: void 0
|
|
312
|
+
}), i;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
ve(["click", "input"]);
|
|
317
|
+
var st = /* @__PURE__ */ $('<div><div style=min-width:300px;max-width:400px><h3 style="margin:0 0 12px;font-size:15px"></h3><p style="margin:0 0 20px;font-size:13px;color:#6b7280"></p><div style=display:flex;justify-content:flex-end;gap:8px><button style="background:none;border:1px solid #2a323c;color:#edf2f7;padding:4px 14px;border-radius:4px;cursor:pointer;font-size:12px">Cancel</button><button style="background:#944;border:1px solid #a55;color:#fff;padding:4px 14px;border-radius:4px;cursor:pointer;font-size:12px">');
|
|
318
|
+
function dt(e) {
|
|
319
|
+
return se(() => {
|
|
320
|
+
if (!e.isOpen) return;
|
|
321
|
+
const t = (a) => {
|
|
322
|
+
a.key === "Escape" && e.onCancel();
|
|
323
|
+
};
|
|
324
|
+
document.addEventListener("keydown", t), Z(() => document.removeEventListener("keydown", t));
|
|
325
|
+
}), g(k, {
|
|
326
|
+
get when() {
|
|
327
|
+
return e.isOpen;
|
|
328
|
+
},
|
|
329
|
+
get children() {
|
|
330
|
+
var t = st(), a = t.firstChild, y = a.firstChild, b = y.nextSibling, f = b.nextSibling, C = f.firstChild, A = C.nextSibling;
|
|
331
|
+
return t.$$click = (x) => {
|
|
332
|
+
x.target === x.currentTarget && e.onCancel();
|
|
333
|
+
}, s(y, () => e.title), s(b, () => e.message), C.$$click = () => e.onCancel(), A.$$click = () => e.onConfirm(), s(A, () => e.confirmLabel ?? "Confirm"), I((x) => {
|
|
334
|
+
var U = ke, T = {
|
|
335
|
+
...Ce
|
|
336
|
+
};
|
|
337
|
+
return x.e = z(t, U, x.e), x.t = z(a, T, x.t), x;
|
|
338
|
+
}, {
|
|
339
|
+
e: void 0,
|
|
340
|
+
t: void 0
|
|
341
|
+
}), t;
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
ve(["click"]);
|
|
346
|
+
var ut = /* @__PURE__ */ $('<div><div style=min-width:300px;max-width:400px><h3 style="margin:0 0 12px;font-size:15px">New Document</h3><input type=text style="width:100%;background:#15191e;border:1px solid #2a323c;color:#edf2f7;font-size:14px;padding:8px 10px;border-radius:4px;outline:none;box-sizing:border-box;margin-bottom:16px"><div style=display:flex;justify-content:flex-end;gap:8px><button style="background:none;border:1px solid #2a323c;color:#edf2f7;padding:4px 14px;border-radius:4px;cursor:pointer;font-size:12px">Cancel</button><button style="background:#2a5a8a;border:1px solid #3a6a9a;color:#fff;padding:4px 14px;border-radius:4px;cursor:pointer;font-size:12px">Create');
|
|
347
|
+
function ft(e) {
|
|
348
|
+
const [t, a] = w("");
|
|
349
|
+
let y;
|
|
350
|
+
se(() => {
|
|
351
|
+
if (!e.isOpen) return;
|
|
352
|
+
a(""), requestAnimationFrame(() => y?.focus());
|
|
353
|
+
const f = (C) => {
|
|
354
|
+
C.key === "Escape" && e.onCancel();
|
|
355
|
+
};
|
|
356
|
+
document.addEventListener("keydown", f), Z(() => document.removeEventListener("keydown", f));
|
|
357
|
+
});
|
|
358
|
+
function b() {
|
|
359
|
+
const f = t().trim();
|
|
360
|
+
e.onConfirm(f || e.defaultTitle);
|
|
361
|
+
}
|
|
362
|
+
return g(k, {
|
|
363
|
+
get when() {
|
|
364
|
+
return e.isOpen;
|
|
365
|
+
},
|
|
366
|
+
get children() {
|
|
367
|
+
var f = ut(), C = f.firstChild, A = C.firstChild, x = A.nextSibling, U = x.nextSibling, T = U.firstChild, ne = T.nextSibling;
|
|
368
|
+
f.$$click = (_) => {
|
|
369
|
+
_.target === _.currentTarget && e.onCancel();
|
|
370
|
+
}, x.$$keydown = (_) => {
|
|
371
|
+
_.key === "Enter" && b();
|
|
372
|
+
}, x.$$input = (_) => a(_.currentTarget.value);
|
|
373
|
+
var O = y;
|
|
374
|
+
return typeof O == "function" ? Me(O, x) : y = x, T.$$click = () => e.onCancel(), ne.$$click = () => b(), I((_) => {
|
|
375
|
+
var Y = ke, N = {
|
|
376
|
+
...Ce
|
|
377
|
+
}, V = e.defaultTitle;
|
|
378
|
+
return _.e = z(f, Y, _.e), _.t = z(C, N, _.t), V !== _.a && je(x, "placeholder", _.a = V), _;
|
|
379
|
+
}, {
|
|
380
|
+
e: void 0,
|
|
381
|
+
t: void 0,
|
|
382
|
+
a: void 0
|
|
383
|
+
}), I(() => x.value = t()), f;
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
ve(["click", "input", "keydown"]);
|
|
388
|
+
const ht = {};
|
|
389
|
+
var pt = /* @__PURE__ */ $('<div style="padding:8px 10px;color:#6b7280;font-style:italic">No documents yet'), gt = /* @__PURE__ */ $('<div style="position:absolute;top:34px;left:0;background:#191e24;border:1px solid #2a323c;border-radius:4px;max-height:400px;overflow-y:auto;min-width:280px;max-width:420px;z-index:1000;box-shadow:0 4px 12px rgba(0,0,0,0.4)">'), mt = /* @__PURE__ */ $('<button style="background:none;border:1px solid #2a323c;color:#edf2f7;font-size:13px;padding:4px 10px;border-radius:4px;cursor:pointer;white-space:nowrap">Share'), vt = /* @__PURE__ */ $('<button title="Copy automerge URL"style="background:none;border:1px solid #2a323c;font-size:13px;padding:4px 10px;border-radius:4px;cursor:pointer;white-space:nowrap">'), xt = /* @__PURE__ */ $('<button style="background:none;border:1px solid #2a323c;font-size:13px;padding:4px 10px;border-radius:4px;cursor:pointer;white-space:nowrap">'), yt = /* @__PURE__ */ $('<button style="background:none;border:1px solid #944;color:#c66;font-size:13px;padding:4px 10px;border-radius:4px;cursor:pointer;white-space:nowrap">Remove Doc'), bt = /* @__PURE__ */ $('<div style=display:flex;flex-direction:column;height:100vh;background:#1d232a><div style="display:flex;align-items:center;height:52px;min-height:52px;background:#191e24;color:#edf2f7;font-size:14px;font-family:system-ui, sans-serif;padding:0 12px;border-bottom:1px solid #15191e;box-sizing:border-box"><button style="background:none;border:1px solid #2a323c;color:#edf2f7;font-size:13px;padding:4px 10px;border-radius:4px;cursor:pointer;flex-shrink:0;margin-right:12px;white-space:nowrap">+ New</button><input type=text placeholder="Paste automerge:… URL"style="background:#15191e;border:1px solid #2a323c;color:#edf2f7;font-size:13px;padding:4px 10px;border-radius:4px;width:200px;min-width:80px;flex-shrink:1;margin-right:12px;outline:none"><div data-doc-switcher style=position:relative;flex:1;min-width:120px><button style="background:none;border:none;color:#edf2f7;font-size:14px;cursor:pointer;padding:4px 8px;border-radius:4px;max-width:100%;display:flex;align-items:center;gap:4px"><span style=overflow:hidden;text-overflow:ellipsis;white-space:nowrap></span><span style=flex-shrink:0>▾</span></button></div><div style=display:flex;align-items:center;flex-shrink:0;gap:8px></div></div><div style=flex:1;min-height:0;overflow:hidden>'), $t = /* @__PURE__ */ $('<div style="padding:8px 12px;cursor:pointer;border-bottom:1px solid #15191e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"> <span style=color:#6b7280;font-size:12px>'), wt = /* @__PURE__ */ $('<div style="width:24px;height:24px;border:2px solid #2a323c;border-top-color:#6b7280;border-radius:50%;animation:spin 0.8s linear infinite">'), kt = /* @__PURE__ */ $('<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;height:100%;background:#1d232a;font-family:system-ui, sans-serif;font-size:14px">'), Ct = /* @__PURE__ */ $("<div style=height:100%>");
|
|
390
|
+
Be();
|
|
391
|
+
function St(e) {
|
|
392
|
+
const t = e.tool, [a, y] = w(null), [b, f] = w("..."), [C, A] = w([]), [x, U] = w(!1), [T, ne] = w(null), [O, _] = w(""), [Y, N] = w(!1), [V, re] = w(!1), [xe, ie] = w(!1), [ue, fe] = w(!1), [ee, i] = w(!1), [d, L] = w(!1), [q, j] = w(!1), [he, J] = w(null), [oe, H] = w(!1);
|
|
393
|
+
let M, n = null, u = 0;
|
|
394
|
+
function P(r) {
|
|
395
|
+
n && (n(), n = null);
|
|
396
|
+
const o = r.doc(), h = o ? t.getTitle(o) : t.defaultTitle;
|
|
397
|
+
f(h), A(Ie(t.id, O(), r.url, h));
|
|
398
|
+
const c = () => {
|
|
399
|
+
const p = r.doc();
|
|
400
|
+
if (p) {
|
|
401
|
+
const m = t.getTitle(p);
|
|
402
|
+
f(m), A(Ie(t.id, O(), r.url, m));
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
r.on("change", c), n = () => r.off("change", c);
|
|
406
|
+
}
|
|
407
|
+
async function E(r) {
|
|
408
|
+
const o = T();
|
|
409
|
+
if (!o) return !0;
|
|
410
|
+
try {
|
|
411
|
+
const h = $e(r), c = o.active.individual.id, p = He.publicId(), [m, R] = await Promise.all([o.accessForDoc(c, h).catch(() => null), o.accessForDoc(p, h).catch(() => null)]);
|
|
412
|
+
return console.log(`[${t.name}] Access check for ${r.slice(0, 30)}...: my=${m}, public=${R}`), !!(m || R);
|
|
413
|
+
} catch (h) {
|
|
414
|
+
return console.error(`[${t.name}] Access check error for ${r}:`, h), !0;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
async function S(r) {
|
|
418
|
+
const o = ++u;
|
|
419
|
+
n && (n(), n = null), y(null), j(!1), J(null), H(!0), f("Loading...");
|
|
420
|
+
try {
|
|
421
|
+
if (!await E(r)) {
|
|
422
|
+
if (o !== u) return;
|
|
423
|
+
console.warn(`[${t.name}] No access to doc: ${r}`), H(!1), j(!0), J(r), le(r);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (o !== u) return;
|
|
427
|
+
const h = (p) => {
|
|
428
|
+
const m = p.doc();
|
|
429
|
+
return m ? t.isDocReady ? t.isDocReady(m) : !!m : !1;
|
|
430
|
+
};
|
|
431
|
+
let c = await M.find(r);
|
|
432
|
+
if (await c.whenReady(), o !== u) return;
|
|
433
|
+
if (!h(c)) {
|
|
434
|
+
console.log(`[${t.name}] Doc incomplete, forcing re-sync for: ${r.slice(0, 30)}...`);
|
|
435
|
+
try {
|
|
436
|
+
M.delete(r);
|
|
437
|
+
} catch {
|
|
438
|
+
}
|
|
439
|
+
if (await new Promise((p) => setTimeout(p, 100)), o !== u || (c = await M.find(r), await c.whenReady(), o !== u)) return;
|
|
440
|
+
}
|
|
441
|
+
if (!h(c) && (le(r), await new Promise((p) => {
|
|
442
|
+
const m = () => {
|
|
443
|
+
if (o !== u) {
|
|
444
|
+
c.off("change", m), p();
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
h(c) && (c.off("change", m), p());
|
|
448
|
+
};
|
|
449
|
+
c.on("change", m), setTimeout(() => {
|
|
450
|
+
c.off("change", m), p();
|
|
451
|
+
}, 3e4);
|
|
452
|
+
}), o !== u))
|
|
453
|
+
return;
|
|
454
|
+
H(!1), le(r), localStorage.setItem(me(t.id, O()), r), P(c), y(c);
|
|
455
|
+
} catch (h) {
|
|
456
|
+
if (o !== u) return;
|
|
457
|
+
console.error(`[${t.name}] Failed to load doc: ${r}`, h), H(!1), j(!0), J(r), le(r);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
async function W(r = t.defaultTitle) {
|
|
461
|
+
const o = T();
|
|
462
|
+
if (!o) return;
|
|
463
|
+
const h = {};
|
|
464
|
+
t.init(h, M), t.setTitle && t.setTitle(h, r), h["@patchwork"] = {
|
|
465
|
+
type: t.id
|
|
466
|
+
};
|
|
467
|
+
const c = await M.create2(h);
|
|
468
|
+
console.log(`[${t.name}] Created document: ${c.url}`), await o.addSyncServerPullToDoc(c.url), await o.keyhiveStorage.saveKeyhiveWithHash(o.keyhive), y(c), le(c.url), localStorage.setItem(me(t.id, O()), c.url), P(c);
|
|
469
|
+
}
|
|
470
|
+
function G() {
|
|
471
|
+
n && (n(), n = null), y(null), f("..."), j(!1), J(null), localStorage.removeItem(me(t.id, O())), window.history.replaceState(null, "", window.location.pathname);
|
|
472
|
+
}
|
|
473
|
+
function pe() {
|
|
474
|
+
const r = a();
|
|
475
|
+
if (!r) return;
|
|
476
|
+
const o = r.url;
|
|
477
|
+
G(), M.delete(o), A(qe(t.id, O(), o));
|
|
478
|
+
}
|
|
479
|
+
async function ye() {
|
|
480
|
+
const r = T();
|
|
481
|
+
if (r)
|
|
482
|
+
try {
|
|
483
|
+
const o = r.active.contactCard.toJson();
|
|
484
|
+
await navigator.clipboard.writeText(o), fe(!0), setTimeout(() => fe(!1), 1500);
|
|
485
|
+
} catch (o) {
|
|
486
|
+
console.error(`[${t.name}] Failed to copy contact card:`, o);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return be(async () => {
|
|
490
|
+
const r = new Ae(`${t.id}-keyhive`), o = ht?.VITE_SYNC_URL, h = new Ke(o || t.syncUrl || "ws://localhost:3030"), c = `${t.id}-${Math.random().toString(36).slice(2)}`, p = await Ye({
|
|
491
|
+
storage: r,
|
|
492
|
+
peerIdSuffix: c,
|
|
493
|
+
networkAdapter: h,
|
|
494
|
+
automaticArchiveIngestion: !0,
|
|
495
|
+
onlyShareWithHardcodedServerPeerId: !0,
|
|
496
|
+
cacheHashes: !0
|
|
497
|
+
});
|
|
498
|
+
window.hive = p, M = new We({
|
|
499
|
+
storage: new Ae(),
|
|
500
|
+
network: [p.networkAdapter],
|
|
501
|
+
peerId: p.peerId,
|
|
502
|
+
sharePolicy: async (B) => B === p.syncServer?.peerId,
|
|
503
|
+
idFactory: p.idFactory
|
|
504
|
+
}), p.linkRepo(M), ne(p);
|
|
505
|
+
const m = de(p.active.individual.id.toBytes());
|
|
506
|
+
_(m), A(we(t.id, m)), L(!0), console.log(`[${t.name}] Keyhive initialized, identity: 0x${m.slice(0, 12)}...`), p.networkAdapter.on("ingest-remote", async () => {
|
|
507
|
+
const B = he();
|
|
508
|
+
if (B) {
|
|
509
|
+
await E(B) && (console.log(`[${t.name}] Access granted, loading: ${B}`), await S(B));
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const l = a();
|
|
513
|
+
l && (await E(l.url) || (console.log(`[${t.name}] Access revoked for: ${l.url}`), n && (n(), n = null), y(null), f("..."), j(!0), J(l.url)));
|
|
514
|
+
});
|
|
515
|
+
const R = Te();
|
|
516
|
+
if (R) {
|
|
517
|
+
console.log(`[${t.name}] Loading doc from hash: ${R}`), await S(R);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const K = localStorage.getItem(me(t.id, m));
|
|
521
|
+
if (K) {
|
|
522
|
+
console.log(`[${t.name}] Found existing doc: ${K}`), await S(K);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
console.log(`[${t.name}] No doc found, starting blank`);
|
|
526
|
+
}), be(() => {
|
|
527
|
+
const r = async () => {
|
|
528
|
+
const o = Te();
|
|
529
|
+
o && (console.log(`[${t.name}] Hash changed, loading: ${o}`), await S(o));
|
|
530
|
+
};
|
|
531
|
+
window.addEventListener("hashchange", r), Z(() => window.removeEventListener("hashchange", r));
|
|
532
|
+
}), be(() => {
|
|
533
|
+
const r = (o) => {
|
|
534
|
+
o.target.closest("[data-doc-switcher]") || U(!1);
|
|
535
|
+
};
|
|
536
|
+
document.addEventListener("mousedown", r), Z(() => document.removeEventListener("mousedown", r));
|
|
537
|
+
}), (() => {
|
|
538
|
+
var r = bt(), o = r.firstChild, h = o.firstChild, c = h.nextSibling, p = c.nextSibling, m = p.firstChild, R = m.firstChild;
|
|
539
|
+
R.nextSibling;
|
|
540
|
+
var K = p.nextSibling, B = o.nextSibling;
|
|
541
|
+
return h.$$click = () => ie(!0), c.$$keydown = (l) => {
|
|
542
|
+
if (l.key === "Enter") {
|
|
543
|
+
const v = l.currentTarget.value.trim();
|
|
544
|
+
if (v) {
|
|
545
|
+
const D = v.startsWith("automerge:") ? v : `automerge:${v}`;
|
|
546
|
+
S(D), l.currentTarget.value = "";
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}, m.$$click = () => U(!x()), s(R, b), s(p, g(k, {
|
|
550
|
+
get when() {
|
|
551
|
+
return x();
|
|
552
|
+
},
|
|
553
|
+
get children() {
|
|
554
|
+
var l = gt();
|
|
555
|
+
return s(l, g(Re, {
|
|
556
|
+
get each() {
|
|
557
|
+
return C();
|
|
558
|
+
},
|
|
559
|
+
children: (v) => (() => {
|
|
560
|
+
var D = $t(), ge = D.firstChild, Ne = ge.nextSibling;
|
|
561
|
+
return D.addEventListener("mouseleave", (F) => {
|
|
562
|
+
F.currentTarget.style.background = "transparent";
|
|
563
|
+
}), D.addEventListener("mouseenter", (F) => {
|
|
564
|
+
F.currentTarget.style.background = "#1d232a";
|
|
565
|
+
}), D.$$click = () => {
|
|
566
|
+
S(v.url), U(!1);
|
|
567
|
+
}, s(D, () => v.title || "Untitled", ge), s(Ne, () => Ge(v.url)), I((F) => {
|
|
568
|
+
var Se = a()?.url === v.url ? "#7ab4f5" : "#edf2f7", _e = a()?.url === v.url ? "bold" : "normal";
|
|
569
|
+
return Se !== F.e && X(D, "color", F.e = Se), _e !== F.t && X(D, "font-weight", F.t = _e), F;
|
|
570
|
+
}, {
|
|
571
|
+
e: void 0,
|
|
572
|
+
t: void 0
|
|
573
|
+
}), D;
|
|
574
|
+
})()
|
|
575
|
+
}), null), s(l, g(k, {
|
|
576
|
+
get when() {
|
|
577
|
+
return C().length === 0;
|
|
578
|
+
},
|
|
579
|
+
get children() {
|
|
580
|
+
return pt();
|
|
581
|
+
}
|
|
582
|
+
}), null), l;
|
|
583
|
+
}
|
|
584
|
+
}), null), s(K, g(k, {
|
|
585
|
+
get when() {
|
|
586
|
+
return te(() => !!a())() && T();
|
|
587
|
+
},
|
|
588
|
+
get children() {
|
|
589
|
+
var l = mt();
|
|
590
|
+
return l.$$click = () => N(!0), l;
|
|
591
|
+
}
|
|
592
|
+
}), null), s(K, g(k, {
|
|
593
|
+
get when() {
|
|
594
|
+
return a();
|
|
595
|
+
},
|
|
596
|
+
get children() {
|
|
597
|
+
var l = vt();
|
|
598
|
+
return l.$$click = async () => {
|
|
599
|
+
const v = a();
|
|
600
|
+
v && (await navigator.clipboard.writeText(v.url), i(!0), setTimeout(() => i(!1), 1500));
|
|
601
|
+
}, s(l, () => ee() ? "Copied!" : "Copy URL"), I((v) => X(l, "color", ee() ? "#b5bd68" : "#edf2f7")), l;
|
|
602
|
+
}
|
|
603
|
+
}), null), s(K, g(k, {
|
|
604
|
+
get when() {
|
|
605
|
+
return T();
|
|
606
|
+
},
|
|
607
|
+
get children() {
|
|
608
|
+
var l = xt();
|
|
609
|
+
return l.$$click = () => void ye(), s(l, () => ue() ? "Copied!" : "Contact Card"), I((v) => X(l, "color", ue() ? "#b5bd68" : "#edf2f7")), l;
|
|
610
|
+
}
|
|
611
|
+
}), null), s(K, g(k, {
|
|
612
|
+
get when() {
|
|
613
|
+
return a();
|
|
614
|
+
},
|
|
615
|
+
get children() {
|
|
616
|
+
var l = yt();
|
|
617
|
+
return l.$$click = () => re(!0), l;
|
|
618
|
+
}
|
|
619
|
+
}), null), s(B, g(k, {
|
|
620
|
+
get when() {
|
|
621
|
+
return a();
|
|
622
|
+
},
|
|
623
|
+
keyed: !0,
|
|
624
|
+
get fallback() {
|
|
625
|
+
return (() => {
|
|
626
|
+
var l = kt();
|
|
627
|
+
return s(l, g(k, {
|
|
628
|
+
get when() {
|
|
629
|
+
return oe() || !d();
|
|
630
|
+
},
|
|
631
|
+
get children() {
|
|
632
|
+
return wt();
|
|
633
|
+
}
|
|
634
|
+
}), null), s(l, (() => {
|
|
635
|
+
var v = te(() => !!q());
|
|
636
|
+
return () => v() ? "Document unavailable: you may not have access" : te(() => !!oe())() ? "Loading document..." : d() ? "No document open" : "Initializing keyhive...";
|
|
637
|
+
})(), null), I((v) => X(l, "color", q() ? "#c66" : "#6b7280")), l;
|
|
638
|
+
})();
|
|
639
|
+
},
|
|
640
|
+
children: (l) => {
|
|
641
|
+
const v = document.createElement("div");
|
|
642
|
+
return v.repo = M, v.style.height = "100%", (() => {
|
|
643
|
+
var D = Ct();
|
|
644
|
+
return Me((ge) => {
|
|
645
|
+
ge.appendChild(v), t.render(l, v);
|
|
646
|
+
}, D), D;
|
|
647
|
+
})();
|
|
648
|
+
}
|
|
649
|
+
})), s(r, g(k, {
|
|
650
|
+
get when() {
|
|
651
|
+
return te(() => !!T())() && a();
|
|
652
|
+
},
|
|
653
|
+
get children() {
|
|
654
|
+
return g(ct, {
|
|
655
|
+
get isOpen() {
|
|
656
|
+
return Y();
|
|
657
|
+
},
|
|
658
|
+
get docUrl() {
|
|
659
|
+
return a().url;
|
|
660
|
+
},
|
|
661
|
+
get hive() {
|
|
662
|
+
return T();
|
|
663
|
+
},
|
|
664
|
+
onClose: () => N(!1)
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
}), null), s(r, g(ft, {
|
|
668
|
+
get isOpen() {
|
|
669
|
+
return xe();
|
|
670
|
+
},
|
|
671
|
+
get defaultTitle() {
|
|
672
|
+
return t.defaultTitle;
|
|
673
|
+
},
|
|
674
|
+
onConfirm: (l) => {
|
|
675
|
+
ie(!1), W(l);
|
|
676
|
+
},
|
|
677
|
+
onCancel: () => ie(!1)
|
|
678
|
+
}), null), s(r, g(dt, {
|
|
679
|
+
get isOpen() {
|
|
680
|
+
return V();
|
|
681
|
+
},
|
|
682
|
+
title: "Remove Document",
|
|
683
|
+
message: "Remove this document from your history? The document data will be deleted locally.",
|
|
684
|
+
confirmLabel: "Remove",
|
|
685
|
+
onConfirm: () => {
|
|
686
|
+
re(!1), pe();
|
|
687
|
+
},
|
|
688
|
+
onCancel: () => re(!1)
|
|
689
|
+
}), null), I((l) => {
|
|
690
|
+
var v = !d(), D = d() ? "1" : "0.4";
|
|
691
|
+
return v !== l.e && (h.disabled = l.e = v), D !== l.t && X(h, "opacity", l.t = D), l;
|
|
692
|
+
}, {
|
|
693
|
+
e: void 0,
|
|
694
|
+
t: void 0
|
|
695
|
+
}), r;
|
|
696
|
+
})();
|
|
697
|
+
}
|
|
698
|
+
ve(["click", "keydown"]);
|
|
699
|
+
function zt(e, t) {
|
|
700
|
+
Je(() => g(St, {
|
|
701
|
+
tool: t
|
|
702
|
+
}), e);
|
|
703
|
+
}
|
|
704
|
+
export {
|
|
705
|
+
dt as ConfirmModal,
|
|
706
|
+
ft as NewDocModal,
|
|
707
|
+
ct as ShareModal,
|
|
708
|
+
Ce as cardStyle,
|
|
709
|
+
zt as mountStandaloneApp,
|
|
710
|
+
ke as overlayStyle
|
|
711
|
+
};
|