@camstack/addon-tailscale-client 0.1.12

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.
Files changed (43) hide show
  1. package/dist/@mf-types/compiled-types/page/TailscaleClientOverviewPage.d.ts +20 -0
  2. package/dist/@mf-types/compiled-types/page/TailscaleClientOverviewPage.d.ts.map +1 -0
  3. package/dist/@mf-types/compiled-types/page/page.d.ts +8 -0
  4. package/dist/@mf-types/compiled-types/page/page.d.ts.map +1 -0
  5. package/dist/@mf-types/page.d.ts +2 -0
  6. package/dist/@mf-types.d.ts +3 -0
  7. package/dist/@mf-types.zip +0 -0
  8. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-bYM9BuS1.mjs +12 -0
  9. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-CtHD1dC0.mjs +12 -0
  10. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-fz-lQtUx.mjs +12 -0
  11. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-B-3nffMn.mjs +73 -0
  12. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.mjs-6CvhJC3f.mjs +42 -0
  13. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.mjs-Sv3rXvki.mjs +46 -0
  14. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare__react__loadShare__.mjs-BBqTAV2L.mjs +56 -0
  15. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-BK8BTUon.mjs +18 -0
  16. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare__react_mf_2_dom__loadShare__.mjs-B6pR25zU.mjs +28 -0
  17. package/dist/__mfe_internal__addon_tailscale_client_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.mjs-kyoamNQ7.mjs +18 -0
  18. package/dist/_stub.js +652 -0
  19. package/dist/_virtual_mf-localSharedImportMap___mfe_internal__addon_tailscale_client_page-PXP_-hRW.mjs +156 -0
  20. package/dist/addon-tailscale-client.css +3 -0
  21. package/dist/client-1J4MstR_.mjs +7592 -0
  22. package/dist/dist-C168hexw.mjs +17192 -0
  23. package/dist/dist-CPnIfsyh.mjs +2229 -0
  24. package/dist/dist-CmoRvaEc.mjs +2483 -0
  25. package/dist/dist-CwyDJZhZ.mjs +16329 -0
  26. package/dist/dist-DNrrMIdr.mjs +662 -0
  27. package/dist/dist-i1I4ldIE.mjs +1260 -0
  28. package/dist/getErrorShape-BPSzUA7W-C2H3tqHP.mjs +189 -0
  29. package/dist/hostInit-KpnzzkeJ.mjs +144 -0
  30. package/dist/index.js +9 -0
  31. package/dist/index.mjs +2 -0
  32. package/dist/jsx-runtime-BmcMHbj3.mjs +22 -0
  33. package/dist/modern-CWdms43F.mjs +2184 -0
  34. package/dist/react-BXkW-3WQ.mjs +293 -0
  35. package/dist/react-dom-BcGsvCWU.mjs +131 -0
  36. package/dist/remoteEntry.js +83 -0
  37. package/dist/rolldown-runtime-DC4cgjXG.mjs +20 -0
  38. package/dist/tailscale.addon.js +633 -0
  39. package/dist/tailscale.addon.js.map +1 -0
  40. package/dist/tailscale.addon.mjs +627 -0
  41. package/dist/tailscale.addon.mjs.map +1 -0
  42. package/dist/virtualExposes-wANYNTM2.mjs +27 -0
  43. package/package.json +94 -0
package/dist/_stub.js ADDED
@@ -0,0 +1,652 @@
1
+ import { d as e, h as t, i as n, l as r, n as i, o as a, r as o, u as s } from "./__mfe_internal__addon_tailscale_client_page__loadShare__react__loadShare__.mjs-BBqTAV2L.mjs";
2
+ import { a as c, i as l, n as u, o as d, r as f, t as p } from "./__mfe_internal__addon_tailscale_client_page__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-fz-lQtUx.mjs";
3
+ import { n as m, r as h, t as g } from "./__mfe_internal__addon_tailscale_client_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-BK8BTUon.mjs";
4
+ //#region node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
5
+ var _ = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), ee = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), v = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), y = (e) => {
6
+ let t = v(e);
7
+ return t.charAt(0).toUpperCase() + t.slice(1);
8
+ }, b = {
9
+ xmlns: "http://www.w3.org/2000/svg",
10
+ width: 24,
11
+ height: 24,
12
+ viewBox: "0 0 24 24",
13
+ fill: "none",
14
+ stroke: "currentColor",
15
+ strokeWidth: 2,
16
+ strokeLinecap: "round",
17
+ strokeLinejoin: "round"
18
+ }, x = (e) => {
19
+ for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
20
+ return !1;
21
+ };
22
+ //#endregion
23
+ //#region node_modules/lucide-react/dist/esm/Icon.js
24
+ t();
25
+ var S = o(({ color: e = "currentColor", size: t = 24, strokeWidth: n = 2, absoluteStrokeWidth: r, className: a = "", children: o, iconNode: s, ...c }, l) => i("svg", {
26
+ ref: l,
27
+ ...b,
28
+ width: t,
29
+ height: t,
30
+ stroke: e,
31
+ strokeWidth: r ? Number(n) * 24 / Number(t) : n,
32
+ className: _("lucide", a),
33
+ ...!o && !x(c) && { "aria-hidden": "true" },
34
+ ...c
35
+ }, [...s.map(([e, t]) => i(e, t)), ...Array.isArray(o) ? o : [o]]));
36
+ //#endregion
37
+ //#region node_modules/lucide-react/dist/esm/createLucideIcon.js
38
+ t();
39
+ var C = (e, t) => {
40
+ let n = o(({ className: n, ...r }, a) => i(S, {
41
+ ref: a,
42
+ iconNode: t,
43
+ className: _(`lucide-${ee(y(e))}`, `lucide-${e}`, n),
44
+ ...r
45
+ }));
46
+ return n.displayName = y(e), n;
47
+ }, w = C("arrow-down", [["path", {
48
+ d: "M12 5v14",
49
+ key: "s699le"
50
+ }], ["path", {
51
+ d: "m19 12-7 7-7-7",
52
+ key: "1idqje"
53
+ }]]), T = C("arrow-up", [["path", {
54
+ d: "m5 12 7-7 7 7",
55
+ key: "hav0vg"
56
+ }], ["path", {
57
+ d: "M12 19V5",
58
+ key: "x0mq9r"
59
+ }]]), te = C("chevron-down", [["path", {
60
+ d: "m6 9 6 6 6-6",
61
+ key: "qrunsl"
62
+ }]]), ne = C("chevron-up", [["path", {
63
+ d: "m18 15-6-6-6 6",
64
+ key: "153udz"
65
+ }]]), E = C("copy", [["rect", {
66
+ width: "14",
67
+ height: "14",
68
+ x: "8",
69
+ y: "8",
70
+ rx: "2",
71
+ ry: "2",
72
+ key: "17jyea"
73
+ }], ["path", {
74
+ d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",
75
+ key: "zix9uf"
76
+ }]]), re = C("external-link", [
77
+ ["path", {
78
+ d: "M15 3h6v6",
79
+ key: "1q9fwt"
80
+ }],
81
+ ["path", {
82
+ d: "M10 14 21 3",
83
+ key: "gplh6r"
84
+ }],
85
+ ["path", {
86
+ d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",
87
+ key: "a6xqqp"
88
+ }]
89
+ ]), D = C("loader-circle", [["path", {
90
+ d: "M21 12a9 9 0 1 1-6.219-8.56",
91
+ key: "13zald"
92
+ }]]), ie = C("network", [
93
+ ["rect", {
94
+ x: "16",
95
+ y: "16",
96
+ width: "6",
97
+ height: "6",
98
+ rx: "1",
99
+ key: "4q2zg0"
100
+ }],
101
+ ["rect", {
102
+ x: "2",
103
+ y: "16",
104
+ width: "6",
105
+ height: "6",
106
+ rx: "1",
107
+ key: "8cvhb9"
108
+ }],
109
+ ["rect", {
110
+ x: "9",
111
+ y: "2",
112
+ width: "6",
113
+ height: "6",
114
+ rx: "1",
115
+ key: "1egb70"
116
+ }],
117
+ ["path", {
118
+ d: "M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3",
119
+ key: "1jsf9p"
120
+ }],
121
+ ["path", {
122
+ d: "M12 12V8",
123
+ key: "2874zd"
124
+ }]
125
+ ]), O = C("refresh-cw", [
126
+ ["path", {
127
+ d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",
128
+ key: "v9h5vc"
129
+ }],
130
+ ["path", {
131
+ d: "M21 3v5h-5",
132
+ key: "1q7to0"
133
+ }],
134
+ ["path", {
135
+ d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",
136
+ key: "3uifl3"
137
+ }],
138
+ ["path", {
139
+ d: "M8 16H3v5",
140
+ key: "1cv678"
141
+ }]
142
+ ]), ae = C("save", [
143
+ ["path", {
144
+ d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",
145
+ key: "1c8476"
146
+ }],
147
+ ["path", {
148
+ d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",
149
+ key: "1ydtos"
150
+ }],
151
+ ["path", {
152
+ d: "M7 3v4a1 1 0 0 0 1 1h7",
153
+ key: "t51u73"
154
+ }]
155
+ ]), oe = C("shield-alert", [
156
+ ["path", {
157
+ d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
158
+ key: "oel41y"
159
+ }],
160
+ ["path", {
161
+ d: "M12 8v4",
162
+ key: "1got3b"
163
+ }],
164
+ ["path", {
165
+ d: "M12 16h.01",
166
+ key: "1drbdi"
167
+ }]
168
+ ]), se = C("x", [["path", {
169
+ d: "M18 6 6 18",
170
+ key: "1bl5f8"
171
+ }], ["path", {
172
+ d: "m6 6 12 12",
173
+ key: "d8bk6v"
174
+ }]]);
175
+ //#endregion
176
+ //#region src/page/TailscaleClientOverviewPage.tsx
177
+ t();
178
+ var k = "tailscale-client", ce = 2e3, le = 3e4;
179
+ function A({ trpc: t }) {
180
+ let [i, o] = e(null), [_, ee] = e([]), [v, y] = e(!0), [b, x] = e(!1), [S, C] = e(null), [w, T] = e(!1), [A, N] = e(null), P = s(null), [F, ge] = e("hostname"), [I, L] = e("asc"), [R, _e] = e(!1), [z, B] = e(null), [V, H] = e(""), [U, W] = e(""), [G, ve] = e(!1), [ye, K] = e(!1), q = n(async () => {
181
+ try {
182
+ let e = await t.meshNetwork.getStatus.query({ nodeId: "hub" });
183
+ return o(e), e;
184
+ } catch (e) {
185
+ return C(e instanceof Error ? e.message : "Failed to load Tailscale status"), null;
186
+ }
187
+ }, [t]), J = n(async () => {
188
+ x(!0);
189
+ try {
190
+ ee((await t.meshNetwork.listPeers.query({ nodeId: "hub" })).peers);
191
+ } catch (e) {
192
+ i?.joined && C(e instanceof Error ? e.message : "Failed to load peer list");
193
+ } finally {
194
+ x(!1);
195
+ }
196
+ }, [t, i?.joined]), Y = n(async () => {
197
+ try {
198
+ let e = me(await t.addonSettings.getGlobalSettings.query({ addonId: k }));
199
+ B(e), H(e.authKey), W(e.hostname);
200
+ } catch {
201
+ B({
202
+ authKey: "",
203
+ hostname: ""
204
+ }), H(""), W("");
205
+ }
206
+ }, [t]), X = n(async () => {
207
+ y(!0), C(null), await q(), await J(), await Y(), y(!1);
208
+ }, [
209
+ q,
210
+ J,
211
+ Y
212
+ ]);
213
+ a(() => {
214
+ X();
215
+ }, [X]), a(() => {
216
+ if (!i?.joined) return;
217
+ let e = setInterval(() => {
218
+ J();
219
+ }, le);
220
+ return () => clearInterval(e);
221
+ }, [i?.joined, J]);
222
+ let be = n(async () => {
223
+ T(!0), C(null), N(null);
224
+ let e = { cancelled: !1 };
225
+ P.current = e;
226
+ try {
227
+ let n = (z?.hostname ?? "").trim(), r = await t.meshNetwork.startLogin.mutate({
228
+ nodeId: "hub",
229
+ ...n ? { hostname: n } : {}
230
+ });
231
+ if (e.cancelled) return;
232
+ N(r.loginUrl), window.open(r.loginUrl, "_blank", "noopener,noreferrer");
233
+ let i = Date.now();
234
+ for (; !e.cancelled && (await pe(ce), !e.cancelled);) {
235
+ if ((await q())?.joined) {
236
+ N(null), await J();
237
+ break;
238
+ }
239
+ if (Date.now() - i > 6e5) {
240
+ C("Connect timed out — re-open the Tailscale login URL and try again.");
241
+ break;
242
+ }
243
+ }
244
+ } catch (e) {
245
+ C(e instanceof Error ? e.message : "Connect failed");
246
+ } finally {
247
+ T(!1), P.current = null;
248
+ }
249
+ }, [
250
+ t,
251
+ z?.hostname,
252
+ q,
253
+ J
254
+ ]), xe = n(() => {
255
+ P.current && (P.current.cancelled = !0), T(!1), N(null);
256
+ }, []), Se = n(async () => {
257
+ K(!0), C(null);
258
+ try {
259
+ await t.addonSettings.updateGlobalSettings.mutate({
260
+ addonId: k,
261
+ patch: {
262
+ authKey: V,
263
+ hostname: U
264
+ }
265
+ }), await Y();
266
+ } catch (e) {
267
+ C(e instanceof Error ? e.message : "Save failed");
268
+ } finally {
269
+ K(!1);
270
+ }
271
+ }, [
272
+ t,
273
+ V,
274
+ U,
275
+ Y
276
+ ]), Ce = z !== null && (V !== z.authKey || U !== z.hostname), Z = r(() => {
277
+ let e = [..._.map((e) => {
278
+ let t = e.addresses[0] ?? "", n = e.online ? "active" : "idle";
279
+ return {
280
+ id: e.id,
281
+ hostname: e.hostname,
282
+ os: e.os ?? "",
283
+ meshIp: t,
284
+ magicDns: "",
285
+ connection: n,
286
+ lastSeenMs: e.lastSeenMs,
287
+ isSelf: e.isSelf
288
+ };
289
+ })].sort((e, t) => ue(e, t, F));
290
+ return I === "asc" ? e : e.reverse();
291
+ }, [
292
+ _,
293
+ F,
294
+ I
295
+ ]), Q = n((e) => {
296
+ ge((t) => t === e ? (L((e) => e === "asc" ? "desc" : "asc"), t) : (L("asc"), e));
297
+ }, []), $ = n((e) => {
298
+ e && navigator.clipboard?.writeText(e);
299
+ }, []), we = r(() => [
300
+ {
301
+ key: "hostname",
302
+ headerRender: () => M("Hostname", "hostname", F, I, Q),
303
+ render: (e) => /* @__PURE__ */ h("div", {
304
+ className: "flex items-center gap-2",
305
+ children: [/* @__PURE__ */ m("span", {
306
+ className: "text-foreground font-medium",
307
+ children: e.hostname || "(unknown)"
308
+ }), e.isSelf && /* @__PURE__ */ m(p, {
309
+ variant: "info",
310
+ children: "self"
311
+ })]
312
+ })
313
+ },
314
+ {
315
+ key: "os",
316
+ headerRender: () => M("OS", "os", F, I, Q),
317
+ render: (e) => /* @__PURE__ */ m("span", {
318
+ className: "text-xs text-foreground-subtle",
319
+ children: e.os || "—"
320
+ })
321
+ },
322
+ {
323
+ key: "meshIp",
324
+ headerRender: () => M("Mesh IPv4", "meshIp", F, I, Q),
325
+ render: (e) => /* @__PURE__ */ h("div", {
326
+ className: "flex items-center gap-1",
327
+ children: [/* @__PURE__ */ m("span", {
328
+ className: "text-xs font-mono",
329
+ children: e.meshIp || "—"
330
+ }), e.meshIp && /* @__PURE__ */ m(u, {
331
+ size: "sm",
332
+ variant: "ghost",
333
+ onClick: () => $(e.meshIp),
334
+ "aria-label": "Copy mesh IP",
335
+ children: /* @__PURE__ */ m(E, { className: "h-3 w-3" })
336
+ })]
337
+ })
338
+ },
339
+ {
340
+ key: "magicDns",
341
+ headerRender: () => M("MagicDNS", "magicDns", F, I, Q),
342
+ render: (e) => /* @__PURE__ */ h("div", {
343
+ className: "flex items-center gap-1",
344
+ children: [/* @__PURE__ */ m("span", {
345
+ className: "text-xs font-mono",
346
+ children: e.magicDns || "—"
347
+ }), e.magicDns && /* @__PURE__ */ m(u, {
348
+ size: "sm",
349
+ variant: "ghost",
350
+ onClick: () => $(e.magicDns),
351
+ "aria-label": "Copy MagicDNS",
352
+ children: /* @__PURE__ */ m(E, { className: "h-3 w-3" })
353
+ })]
354
+ })
355
+ },
356
+ {
357
+ key: "connection",
358
+ headerRender: () => M("Connection", "connection", F, I, Q),
359
+ render: (e) => /* @__PURE__ */ m(p, {
360
+ variant: de(e.connection),
361
+ children: e.connection
362
+ })
363
+ },
364
+ {
365
+ key: "lastSeen",
366
+ headerRender: () => M("Last seen", "lastSeen", F, I, Q),
367
+ render: (e) => /* @__PURE__ */ m("span", {
368
+ className: "text-xs text-foreground-subtle",
369
+ children: e.lastSeenMs > 0 ? fe(e.lastSeenMs) : "—"
370
+ })
371
+ }
372
+ ], [
373
+ F,
374
+ I,
375
+ Q,
376
+ $
377
+ ]), Te = i?.endpoints.find((e) => e.id === "magicdns")?.hostname.split(".").slice(1).join(".") ?? "";
378
+ return /* @__PURE__ */ h("div", {
379
+ className: "p-6 space-y-6",
380
+ children: [
381
+ /* @__PURE__ */ h("header", {
382
+ className: "flex items-start gap-3",
383
+ children: [/* @__PURE__ */ m("div", {
384
+ className: "h-10 w-10 rounded-lg bg-primary/10 text-primary flex items-center justify-center shrink-0",
385
+ children: /* @__PURE__ */ m(ie, { className: "h-5 w-5" })
386
+ }), /* @__PURE__ */ h("div", {
387
+ className: "min-w-0",
388
+ children: [/* @__PURE__ */ m("h1", {
389
+ className: "text-xl font-semibold text-foreground",
390
+ children: "Tailscale"
391
+ }), /* @__PURE__ */ m("p", {
392
+ className: "text-sm text-foreground-subtle mt-1",
393
+ children: "Join this host to a Tailscale tailnet so the rest of the mesh can reach the hub. The browser-redirect flow below opens a Tailscale login URL in a new tab."
394
+ })]
395
+ })]
396
+ }),
397
+ S && /* @__PURE__ */ m(f, {
398
+ className: "border-danger/40",
399
+ children: /* @__PURE__ */ h("div", {
400
+ className: "p-4 text-sm text-danger flex items-center gap-2",
401
+ children: [/* @__PURE__ */ m(oe, { className: "h-4 w-4 shrink-0" }), S]
402
+ })
403
+ }),
404
+ /* @__PURE__ */ m(f, { children: /* @__PURE__ */ h("div", {
405
+ className: "p-4 space-y-3",
406
+ children: [
407
+ /* @__PURE__ */ h("div", {
408
+ className: "flex items-center justify-between gap-3",
409
+ children: [/* @__PURE__ */ h("div", {
410
+ className: "min-w-0",
411
+ children: [/* @__PURE__ */ m("h2", {
412
+ className: "text-sm font-semibold text-foreground",
413
+ children: "Connection"
414
+ }), /* @__PURE__ */ m("p", {
415
+ className: "text-xs text-foreground-subtle mt-1",
416
+ children: i?.joined ? "Host is joined to the tailnet." : "Click Connect to start the Tailscale login flow in a new browser tab."
417
+ })]
418
+ }), /* @__PURE__ */ h("div", {
419
+ className: "flex items-center gap-2",
420
+ children: [/* @__PURE__ */ m(u, {
421
+ size: "sm",
422
+ variant: "ghost",
423
+ onClick: () => void X(),
424
+ disabled: v,
425
+ children: v ? /* @__PURE__ */ m(D, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ m(O, { className: "h-3.5 w-3.5 mr-1" }), "Refresh"] })
426
+ }), i?.joined ? /* @__PURE__ */ m(u, {
427
+ size: "sm",
428
+ variant: "ghost",
429
+ onClick: () => void he(t, C, X),
430
+ children: "Leave"
431
+ }) : w ? /* @__PURE__ */ h(u, {
432
+ size: "sm",
433
+ variant: "ghost",
434
+ onClick: () => xe(),
435
+ children: [/* @__PURE__ */ m(se, { className: "h-3.5 w-3.5 mr-1" }), " Cancel"]
436
+ }) : /* @__PURE__ */ m(u, {
437
+ size: "sm",
438
+ variant: "primary",
439
+ onClick: () => void be(),
440
+ children: "Connect to Tailscale"
441
+ })]
442
+ })]
443
+ }),
444
+ w && /* @__PURE__ */ h("div", {
445
+ className: "rounded-md border border-border bg-surface-subtle p-3 text-xs space-y-2",
446
+ children: [/* @__PURE__ */ h("div", {
447
+ className: "flex items-center gap-2 text-foreground",
448
+ children: [/* @__PURE__ */ m(D, { className: "h-3.5 w-3.5 animate-spin" }), "Waiting for browser authentication…"]
449
+ }), A && /* @__PURE__ */ h("div", {
450
+ className: "flex items-center gap-2",
451
+ children: [/* @__PURE__ */ h("a", {
452
+ href: A,
453
+ target: "_blank",
454
+ rel: "noopener noreferrer",
455
+ className: "inline-flex items-center gap-1 text-primary hover:underline",
456
+ children: [/* @__PURE__ */ m(re, { className: "h-3 w-3" }), "Open login URL"]
457
+ }), /* @__PURE__ */ m(u, {
458
+ size: "sm",
459
+ variant: "ghost",
460
+ onClick: () => $(A),
461
+ "aria-label": "Copy login URL",
462
+ children: /* @__PURE__ */ m(E, { className: "h-3 w-3" })
463
+ })]
464
+ })]
465
+ }),
466
+ i?.joined && /* @__PURE__ */ h("div", {
467
+ className: "grid grid-cols-1 lg:grid-cols-2 gap-x-6 gap-y-2 text-sm pt-2 border-t border-border",
468
+ children: [
469
+ /* @__PURE__ */ m(j, {
470
+ label: "Mesh IPv4",
471
+ value: i.meshIp,
472
+ mono: !0
473
+ }),
474
+ /* @__PURE__ */ m(j, {
475
+ label: "MagicDNS",
476
+ value: i.magicDnsHostname,
477
+ mono: !0
478
+ }),
479
+ /* @__PURE__ */ m(j, {
480
+ label: "Tailnet",
481
+ value: Te || "—"
482
+ }),
483
+ /* @__PURE__ */ m(j, {
484
+ label: "Peers",
485
+ value: String(i.peerCount)
486
+ })
487
+ ]
488
+ })
489
+ ]
490
+ }) }),
491
+ /* @__PURE__ */ m(f, { children: /* @__PURE__ */ h("div", {
492
+ className: "p-4 space-y-3",
493
+ children: [/* @__PURE__ */ h("div", {
494
+ className: "flex items-center justify-between",
495
+ children: [/* @__PURE__ */ h("h2", {
496
+ className: "text-sm font-semibold text-foreground",
497
+ children: [
498
+ "Peers (",
499
+ _.length,
500
+ ")"
501
+ ]
502
+ }), /* @__PURE__ */ m(u, {
503
+ size: "sm",
504
+ variant: "ghost",
505
+ onClick: () => void J(),
506
+ disabled: b,
507
+ children: b ? /* @__PURE__ */ m(D, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ m(O, { className: "h-3.5 w-3.5 mr-1" }), "Refresh"] })
508
+ })]
509
+ }), Z.length === 0 ? /* @__PURE__ */ m(c, {
510
+ icon: ie,
511
+ title: "No peers",
512
+ description: i?.joined ? "Your tailnet is empty — invite another device from the Tailscale admin console." : "Join the tailnet to see peers."
513
+ }) : /* @__PURE__ */ m(l, {
514
+ columns: we,
515
+ rows: Z,
516
+ rowKey: (e) => e.id,
517
+ minWidthPx: 720
518
+ })]
519
+ }) }),
520
+ /* @__PURE__ */ m(f, { children: /* @__PURE__ */ h("div", {
521
+ className: "p-4 space-y-3",
522
+ children: [/* @__PURE__ */ h("button", {
523
+ type: "button",
524
+ onClick: () => _e((e) => !e),
525
+ className: "flex items-center gap-2 text-sm font-semibold text-foreground hover:text-primary",
526
+ children: [m(R ? ne : te, { className: "h-4 w-4" }), "Advanced — Headless / Auth Key"]
527
+ }), R && /* @__PURE__ */ h("div", {
528
+ className: "grid grid-cols-1 lg:grid-cols-2 gap-x-6 gap-y-3 pt-2 border-t border-border",
529
+ children: [
530
+ /* @__PURE__ */ h("div", {
531
+ className: "flex items-center justify-between gap-3 text-sm",
532
+ children: [/* @__PURE__ */ m("span", {
533
+ className: "text-foreground-subtle",
534
+ children: "Pre-auth key"
535
+ }), /* @__PURE__ */ h("div", {
536
+ className: "flex items-center gap-2 w-72",
537
+ children: [/* @__PURE__ */ m(d, {
538
+ type: G ? "text" : "password",
539
+ value: V,
540
+ onChange: (e) => H(e.target.value),
541
+ placeholder: "tskey-auth-…",
542
+ className: "h-8 text-xs font-mono flex-1"
543
+ }), /* @__PURE__ */ m(u, {
544
+ size: "sm",
545
+ variant: "ghost",
546
+ onClick: () => ve((e) => !e),
547
+ "aria-label": G ? "Hide key" : "Show key",
548
+ children: G ? "Hide" : "Show"
549
+ })]
550
+ })]
551
+ }),
552
+ /* @__PURE__ */ h("div", {
553
+ className: "flex items-center justify-between gap-3 text-sm",
554
+ children: [/* @__PURE__ */ m("span", {
555
+ className: "text-foreground-subtle",
556
+ children: "Hostname override"
557
+ }), /* @__PURE__ */ m(d, {
558
+ value: U,
559
+ onChange: (e) => W(e.target.value),
560
+ placeholder: "camstack-hub",
561
+ className: "w-72 h-8 text-xs font-mono"
562
+ })]
563
+ }),
564
+ Ce && /* @__PURE__ */ m("div", {
565
+ className: "lg:col-span-2 flex justify-end pt-2 border-t border-border",
566
+ children: /* @__PURE__ */ h(u, {
567
+ size: "sm",
568
+ variant: "primary",
569
+ onClick: () => void Se(),
570
+ disabled: ye,
571
+ children: [/* @__PURE__ */ m(ae, { className: "h-3.5 w-3.5 mr-1" }), "Save"]
572
+ })
573
+ }),
574
+ /* @__PURE__ */ m("p", {
575
+ className: "lg:col-span-2 text-xs text-foreground-subtle",
576
+ children: "When set, the addon auto-rejoins on boot if the daemon dropped offline (backoff 5/15/30/60/60 min). For first-time setup prefer the browser-redirect Connect button above."
577
+ })
578
+ ]
579
+ })]
580
+ }) })
581
+ ]
582
+ });
583
+ }
584
+ function j({ label: e, value: t, mono: n }) {
585
+ return /* @__PURE__ */ h("div", {
586
+ className: "flex items-center justify-between gap-3",
587
+ children: [/* @__PURE__ */ m("span", {
588
+ className: "text-foreground-subtle",
589
+ children: e
590
+ }), /* @__PURE__ */ m("span", {
591
+ className: n ? "text-xs font-mono" : "text-xs",
592
+ children: t || "—"
593
+ })]
594
+ });
595
+ }
596
+ function M(e, t, n, r, i) {
597
+ return /* @__PURE__ */ h("button", {
598
+ type: "button",
599
+ onClick: () => i(t),
600
+ className: "inline-flex items-center gap-1 text-xs font-semibold uppercase tracking-wide text-foreground-subtle hover:text-foreground",
601
+ children: [e, n === t && m(r === "asc" ? T : w, { className: "h-3 w-3" })]
602
+ });
603
+ }
604
+ function ue(e, t, n) {
605
+ if (e.isSelf !== t.isSelf) return e.isSelf ? -1 : 1;
606
+ switch (n) {
607
+ case "hostname": return e.hostname.localeCompare(t.hostname);
608
+ case "os": return e.os.localeCompare(t.os);
609
+ case "meshIp": return e.meshIp.localeCompare(t.meshIp);
610
+ case "magicDns": return e.magicDns.localeCompare(t.magicDns);
611
+ case "connection": return e.connection.localeCompare(t.connection);
612
+ case "lastSeen": return e.lastSeenMs - t.lastSeenMs;
613
+ }
614
+ }
615
+ function de(e) {
616
+ return e === "active" ? "success" : e === "relay" ? "warning" : "info";
617
+ }
618
+ function fe(e) {
619
+ let t = Date.now() - e;
620
+ return t < 6e4 ? "just now" : t < 36e5 ? `${Math.round(t / 6e4)}m ago` : t < 864e5 ? `${Math.round(t / 36e5)}h ago` : `${Math.round(t / 864e5)}d ago`;
621
+ }
622
+ function pe(e) {
623
+ return new Promise((t) => setTimeout(t, e));
624
+ }
625
+ function me(e) {
626
+ let t = {
627
+ authKey: "",
628
+ hostname: ""
629
+ };
630
+ if (!e || typeof e != "object") return t;
631
+ let n = e, r = /* @__PURE__ */ new Map();
632
+ for (let e of n.sections ?? []) for (let t of e.fields ?? []) typeof t.key == "string" && r.set(t.key, t.value);
633
+ let i = r.get("authKey"), a = r.get("hostname");
634
+ return {
635
+ authKey: typeof i == "string" ? i : "",
636
+ hostname: typeof a == "string" ? a : ""
637
+ };
638
+ }
639
+ async function he(e, t, n) {
640
+ try {
641
+ await e.meshNetwork.leave.mutate({ nodeId: "hub" });
642
+ } catch (e) {
643
+ t(e instanceof Error ? e.message : "Leave failed");
644
+ return;
645
+ }
646
+ await n();
647
+ }
648
+ //#endregion
649
+ //#region src/page/page.tsx
650
+ var N = A;
651
+ //#endregion
652
+ export { N as default };