@korso/shepherd-ui 0.3.1 → 0.4.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/lib/index.js CHANGED
@@ -1,444 +1,696 @@
1
- import { u as U, d as N, f as F, D as W } from "./Dashboard-Bgi50wCo.js";
2
- import { E as ie, S as ae, a as le, c as re } from "./Dashboard-Bgi50wCo.js";
3
- import { jsxs as a, jsx as e } from "react/jsx-runtime";
4
- import { useId as B, useState as i, useEffect as $, useCallback as D } from "react";
5
- function K({
6
- workspaces: l,
7
- selected: t,
8
- onChanged: r,
9
- onSelect: b,
10
- onMembersChanged: d
1
+ import { u as A, d as I, f as D, D as P } from "./Dashboard-CTXdGRxM.js";
2
+ import { E as de, S as ue, a as he, c as me } from "./Dashboard-CTXdGRxM.js";
3
+ import { jsxs as n, jsx as e, Fragment as H } from "react/jsx-runtime";
4
+ import { useId as U, useRef as K, useState as a, useEffect as j, useCallback as Y } from "react";
5
+ function F(t) {
6
+ return (t.trim()[0] ?? "?").toUpperCase();
7
+ }
8
+ function J({
9
+ workspaces: t,
10
+ selected: i,
11
+ onSelect: r,
12
+ onChanged: p,
13
+ onMembersChanged: o
11
14
  }) {
12
- const y = U(), C = B(), [g, k] = i(""), [m, u] = i(""), [o, w] = i(null), [h, s] = i(null), [p, v] = i(!1), [S, R] = i(""), [x, E] = i(null), [c, f] = i(!1), _ = (t == null ? void 0 : t.role) === "admin";
13
- async function I() {
14
- if (!(!g.trim() || p)) {
15
- v(!0), s(null);
16
- try {
17
- await y.createWorkspace({ name: g.trim() }), k(""), r();
18
- } catch (n) {
19
- s(N(n));
20
- } finally {
21
- v(!1);
22
- }
23
- }
15
+ const h = A(), v = U(), m = K(null), [l, f] = a(!1), [b, N] = a("menu"), [g, w] = a(""), [c, C] = a(""), [E, d] = a(null), [k, _] = a(!1);
16
+ function S() {
17
+ f(!1), N("menu"), w(""), C(""), d(null);
24
18
  }
25
- async function L() {
26
- if (!(!m.trim() || p)) {
27
- v(!0), s(null);
28
- try {
29
- await y.redeemInvite(m.trim()), u(""), r(), d == null || d();
30
- } catch (n) {
31
- s(N(n));
32
- } finally {
33
- v(!1);
34
- }
19
+ j(() => {
20
+ if (!l) return;
21
+ function s(B) {
22
+ m.current && !m.current.contains(B.target) && S();
35
23
  }
36
- }
37
- async function H() {
38
- if (!(!t || p)) {
39
- v(!0), s(null);
40
- try {
41
- const n = await y.createInvite(t.id, {});
42
- w(n), d == null || d();
43
- } catch (n) {
44
- s(N(n));
45
- } finally {
46
- v(!1);
47
- }
24
+ function R(B) {
25
+ B.key === "Escape" && S();
48
26
  }
49
- }
50
- async function O() {
51
- if (!(!t || !S.trim() || c)) {
52
- f(!0), E(null);
27
+ return document.addEventListener("mousedown", s), document.addEventListener("keydown", R), () => {
28
+ document.removeEventListener("mousedown", s), document.removeEventListener("keydown", R);
29
+ };
30
+ }, [l]);
31
+ async function x() {
32
+ if (!(!g.trim() || k)) {
33
+ _(!0), d(null);
53
34
  try {
54
- const n = await y.inviteByEmail(t.id, S.trim());
55
- E(`Invite sent to ${n.email}.`), R(""), d == null || d();
56
- } catch (n) {
57
- E(N(n));
35
+ const s = await h.createWorkspace({ name: g.trim() });
36
+ r(s.id), p(), S();
37
+ } catch (s) {
38
+ d(I(s));
58
39
  } finally {
59
- f(!1);
40
+ _(!1);
60
41
  }
61
42
  }
62
43
  }
63
- async function A() {
64
- if (!(!t || !o || p)) {
65
- v(!0), s(null);
44
+ async function L() {
45
+ if (!(!c.trim() || k)) {
46
+ _(!0), d(null);
66
47
  try {
67
- await y.revokeInvite(t.id, o.code), w(null);
68
- } catch (n) {
69
- s(N(n));
48
+ const s = await h.redeemInvite(c.trim());
49
+ r(s.workspace.id), p(), o == null || o(), S();
50
+ } catch (s) {
51
+ d(I(s));
70
52
  } finally {
71
- v(!1);
53
+ _(!1);
72
54
  }
73
55
  }
74
56
  }
75
- $(() => {
76
- w(null), E(null);
77
- }, [t == null ? void 0 : t.id]);
78
- const j = o ? `${window.location.origin}/shepherd/join/${encodeURIComponent(o.code)}` : null;
79
- return /* @__PURE__ */ a("section", { className: "shepherd-workspaces", "aria-labelledby": C, children: [
80
- /* @__PURE__ */ a("div", { className: "card-head", children: [
81
- /* @__PURE__ */ e("h3", { id: C, children: "Workspace management" }),
82
- /* @__PURE__ */ e("p", { className: "card-sub", children: "Create a workspace to get started, or join an existing one with an invite code." })
83
- ] }),
84
- /* @__PURE__ */ a("div", { className: "card-body", children: [
85
- h && /* @__PURE__ */ e("p", { role: "alert", children: h }),
86
- l.length > 1 && b && /* @__PURE__ */ a("div", { className: "field switcher", children: [
87
- /* @__PURE__ */ e("label", { htmlFor: "ws-switcher", children: "Active workspace" }),
88
- /* @__PURE__ */ e(
89
- "select",
90
- {
91
- id: "ws-switcher",
92
- value: (t == null ? void 0 : t.id) ?? "",
93
- onChange: (n) => b(n.target.value),
94
- children: l.map((n) => /* @__PURE__ */ e("option", { value: n.id, children: n.name }, n.id))
95
- }
96
- )
97
- ] }),
98
- /* @__PURE__ */ a("div", { className: "field create", children: [
99
- /* @__PURE__ */ e("label", { htmlFor: "ws-name", children: "Workspace name" }),
100
- /* @__PURE__ */ e("p", { className: "helper", children: "Start a fresh workspace — you'll be its admin." }),
101
- /* @__PURE__ */ a("div", { className: "field__row", children: [
57
+ const y = i !== null, T = i ? i.name : "Get started";
58
+ return /* @__PURE__ */ n("div", { className: "ws-switcher", ref: m, children: [
59
+ /* @__PURE__ */ n(
60
+ "button",
61
+ {
62
+ type: "button",
63
+ className: "ws-trig" + (y ? "" : " ws-trig--empty"),
64
+ "aria-haspopup": "menu",
65
+ "aria-expanded": l,
66
+ "aria-controls": l ? v : void 0,
67
+ onClick: () => l ? S() : f(!0),
68
+ children: [
69
+ y ? /* @__PURE__ */ e("span", { className: "ws-avatar", "aria-hidden": "true", children: F(T) }) : /* @__PURE__ */ e("span", { className: "ws-plus", "aria-hidden": "true", children: "+" }),
70
+ /* @__PURE__ */ e("span", { className: "ws-name", children: T }),
71
+ /* @__PURE__ */ e("span", { className: "ws-caret", "aria-hidden": "true", children: "▾" })
72
+ ]
73
+ }
74
+ ),
75
+ l && /* @__PURE__ */ n("div", { className: "ws-menu", id: v, role: "menu", children: [
76
+ b === "menu" && /* @__PURE__ */ n(H, { children: [
77
+ /* @__PURE__ */ e("p", { className: "ws-menu__head", children: y ? "Switch workspace" : "Your workspaces" }),
78
+ t.length === 0 ? /* @__PURE__ */ e("p", { className: "ws-menu__none", children: "None yet" }) : /* @__PURE__ */ e("ul", { className: "ws-menu__list", children: t.map((s) => {
79
+ const R = s.id === (i == null ? void 0 : i.id);
80
+ return /* @__PURE__ */ e("li", { children: /* @__PURE__ */ n(
81
+ "button",
82
+ {
83
+ type: "button",
84
+ role: "menuitemradio",
85
+ "aria-checked": R,
86
+ className: "ws-mi" + (R ? " ws-mi--on" : ""),
87
+ onClick: () => {
88
+ r(s.id), S();
89
+ },
90
+ children: [
91
+ /* @__PURE__ */ e("span", { className: "ws-avatar ws-avatar--sm", "aria-hidden": "true", children: F(s.name) }),
92
+ /* @__PURE__ */ e("span", { className: "ws-mi__name", children: s.name }),
93
+ R && /* @__PURE__ */ e("span", { className: "ws-mi__check", "aria-hidden": "true", children: "✓" })
94
+ ]
95
+ }
96
+ ) }, s.id);
97
+ }) }),
98
+ /* @__PURE__ */ n("div", { className: "ws-menu__actions", children: [
102
99
  /* @__PURE__ */ e(
103
- "input",
100
+ "button",
104
101
  {
105
- id: "ws-name",
106
- type: "text",
107
- placeholder: "e.g. Acme Engineering",
108
- value: g,
109
- onChange: (n) => k(n.target.value)
102
+ type: "button",
103
+ role: "menuitem",
104
+ className: "ws-action",
105
+ onClick: () => {
106
+ d(null), N("create");
107
+ },
108
+ children: "+ Create workspace"
110
109
  }
111
110
  ),
112
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void I(), disabled: p, children: "Create workspace" })
113
- ] })
114
- ] }),
115
- /* @__PURE__ */ a("div", { className: "field join", children: [
116
- /* @__PURE__ */ e("label", { htmlFor: "invite-code", children: "Invite code" }),
117
- /* @__PURE__ */ e("p", { className: "helper", children: "Paste an invite code someone shared to join their workspace." }),
118
- /* @__PURE__ */ a("div", { className: "field__row", children: [
119
111
  /* @__PURE__ */ e(
120
- "input",
112
+ "button",
121
113
  {
122
- id: "invite-code",
123
- type: "text",
124
- placeholder: "Invite code",
125
- value: m,
126
- onChange: (n) => u(n.target.value)
114
+ type: "button",
115
+ role: "menuitem",
116
+ className: "ws-action",
117
+ onClick: () => {
118
+ d(null), N("join");
119
+ },
120
+ children: "⎘ Join with a code"
127
121
  }
128
- ),
129
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void L(), disabled: p, children: "Join" })
122
+ )
130
123
  ] })
131
124
  ] }),
132
- _ && t && /* @__PURE__ */ a("div", { className: "admin", children: [
133
- /* @__PURE__ */ a("div", { className: "invites", children: [
134
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void H(), disabled: p, children: "Create invite" }),
135
- o && /* @__PURE__ */ a("div", { className: "invite-result", children: [
136
- /* @__PURE__ */ a("div", { className: "invite-result__row", children: [
137
- /* @__PURE__ */ e("code", { children: o.code }),
138
- /* @__PURE__ */ e("span", { className: "invite-uses", children: o.maxUses === null ? `${o.useCount} uses` : `${o.useCount} / ${o.maxUses} uses` }),
139
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void A(), disabled: p, children: "Revoke invite" })
140
- ] }),
141
- /* @__PURE__ */ e("a", { href: j ?? void 0, children: j })
142
- ] })
143
- ] }),
144
- /* @__PURE__ */ a("div", { className: "field email-invite", children: [
145
- /* @__PURE__ */ e("label", { htmlFor: "invite-email", children: "Email invite" }),
146
- /* @__PURE__ */ e("p", { className: "helper", children: "Send a one-time-use join link directly to someone's inbox." }),
147
- /* @__PURE__ */ a("div", { className: "field__row", children: [
125
+ b === "create" && /* @__PURE__ */ n(
126
+ "form",
127
+ {
128
+ className: "ws-form",
129
+ onSubmit: (s) => {
130
+ s.preventDefault(), x();
131
+ },
132
+ children: [
133
+ /* @__PURE__ */ e("label", { htmlFor: `${v}-name`, children: "New workspace name" }),
148
134
  /* @__PURE__ */ e(
149
135
  "input",
150
136
  {
151
- id: "invite-email",
152
- type: "email",
153
- placeholder: "name@example.com",
154
- value: S,
155
- onChange: (n) => R(n.target.value)
137
+ id: `${v}-name`,
138
+ type: "text",
139
+ placeholder: "e.g. Acme Engineering",
140
+ value: g,
141
+ autoFocus: !0,
142
+ onChange: (s) => w(s.target.value)
156
143
  }
157
144
  ),
158
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void O(), disabled: c, children: "Send invite" })
159
- ] }),
160
- x && /* @__PURE__ */ e("p", { className: "email-invite__status", children: x })
161
- ] })
145
+ /* @__PURE__ */ n("div", { className: "ws-form__row", children: [
146
+ /* @__PURE__ */ e("button", { type: "button", className: "ws-form__back", onClick: () => N("menu"), children: "Back" }),
147
+ /* @__PURE__ */ e("button", { type: "submit", disabled: k || !g.trim(), children: "Create" })
148
+ ] })
149
+ ]
150
+ }
151
+ ),
152
+ b === "join" && /* @__PURE__ */ n(
153
+ "form",
154
+ {
155
+ className: "ws-form",
156
+ onSubmit: (s) => {
157
+ s.preventDefault(), L();
158
+ },
159
+ children: [
160
+ /* @__PURE__ */ e("label", { htmlFor: `${v}-code`, children: "Invite code" }),
161
+ /* @__PURE__ */ e(
162
+ "input",
163
+ {
164
+ id: `${v}-code`,
165
+ type: "text",
166
+ placeholder: "Paste an invite code",
167
+ value: c,
168
+ autoFocus: !0,
169
+ onChange: (s) => C(s.target.value)
170
+ }
171
+ ),
172
+ /* @__PURE__ */ n("div", { className: "ws-form__row", children: [
173
+ /* @__PURE__ */ e("button", { type: "button", className: "ws-form__back", onClick: () => N("menu"), children: "Back" }),
174
+ /* @__PURE__ */ e("button", { type: "submit", disabled: k || !c.trim(), children: "Join" })
175
+ ] })
176
+ ]
177
+ }
178
+ ),
179
+ E && /* @__PURE__ */ e("p", { className: "ws-menu__error", role: "alert", children: E })
180
+ ] })
181
+ ] });
182
+ }
183
+ function V({ workspace: t, onLeft: i }) {
184
+ const r = A(), p = U(), [o, h] = a(null), [v, m] = a(!1);
185
+ async function l() {
186
+ if (!v) {
187
+ m(!0), h(null);
188
+ try {
189
+ await r.leave(t.id), i == null || i();
190
+ } catch (f) {
191
+ h(I(f));
192
+ } finally {
193
+ m(!1);
194
+ }
195
+ }
196
+ }
197
+ return /* @__PURE__ */ n("section", { className: "shepherd-general", "aria-labelledby": p, children: [
198
+ /* @__PURE__ */ n("div", { className: "card-head", children: [
199
+ /* @__PURE__ */ e("h3", { id: p, children: "General" }),
200
+ /* @__PURE__ */ e("p", { className: "card-sub", children: "Your active workspace and its settings." })
201
+ ] }),
202
+ /* @__PURE__ */ n("div", { className: "card-body", children: [
203
+ o && /* @__PURE__ */ e("p", { role: "alert", children: o }),
204
+ /* @__PURE__ */ n("div", { className: "field", children: [
205
+ /* @__PURE__ */ e("label", { children: "Workspace name" }),
206
+ /* @__PURE__ */ e("p", { className: "readonly-value", children: t.name })
207
+ ] }),
208
+ /* @__PURE__ */ n("div", { className: "field", children: [
209
+ /* @__PURE__ */ e("label", { children: "Your role" }),
210
+ /* @__PURE__ */ e("p", { className: "readonly-value", children: t.role })
211
+ ] }),
212
+ /* @__PURE__ */ n("div", { className: "field leave", children: [
213
+ /* @__PURE__ */ e("label", { children: "Leave workspace" }),
214
+ /* @__PURE__ */ e("p", { className: "helper", children: "Remove yourself from this workspace. You'll need a new invite to rejoin." }),
215
+ /* @__PURE__ */ e("button", { type: "button", className: "danger", onClick: () => void l(), disabled: v, children: "Leave workspace" })
162
216
  ] })
163
217
  ] })
164
218
  ] });
165
219
  }
166
- function G({ workspaceId: l, refreshKey: t = 0, canRemove: r = !1, onLeft: b }) {
167
- const d = U(), y = B(), [C, g] = i([]), [k, m] = i(null), [u, o] = i(null), [w, h] = i(!0), [s, p] = i(null), [v, S] = i(!1);
168
- async function R({ keepError: c = !1 } = {}) {
169
- c || m(null);
220
+ function X({ workspaceId: t, refreshKey: i = 0, canRemove: r = !1 }) {
221
+ const p = A(), o = U(), [h, v] = a([]), [m, l] = a(null), [f, b] = a(null), [N, g] = a(!0), [w, c] = a(null);
222
+ async function C({ keepError: d = !1 } = {}) {
223
+ d || l(null);
170
224
  try {
171
- const f = await d.listMembers(l);
172
- g(f.members);
173
- } catch (f) {
174
- m(N(f));
225
+ const k = await p.listMembers(t);
226
+ v(k.members);
227
+ } catch (k) {
228
+ l(I(k));
175
229
  } finally {
176
- h(!1);
230
+ g(!1);
177
231
  }
178
232
  }
179
- $(() => {
180
- h(!0), R();
181
- }, [d, l, t]);
182
- async function x(c, f) {
183
- if (!s) {
184
- p(c), m(null), o(null), g((_) => _.filter((I) => I.accountId !== c));
233
+ j(() => {
234
+ g(!0), C();
235
+ }, [p, t, i]);
236
+ async function E(d, k) {
237
+ if (!w) {
238
+ c(d), l(null), b(null), v((_) => _.filter((S) => S.accountId !== d));
185
239
  try {
186
- await d.removeMember(l, c), o(`Removed ${f}`);
240
+ await p.removeMember(t, d), b(`Removed ${k}`);
187
241
  } catch (_) {
188
- m(N(_)), R({ keepError: !0 });
242
+ l(I(_)), C({ keepError: !0 });
189
243
  } finally {
190
- p(null);
244
+ c(null);
191
245
  }
192
246
  }
193
247
  }
194
- async function E() {
195
- if (!v) {
196
- S(!0), m(null), o(null);
197
- try {
198
- await d.leave(l), o("Left workspace"), b == null || b();
199
- } catch (c) {
200
- m(N(c));
201
- } finally {
202
- S(!1);
203
- }
204
- }
205
- }
206
- return /* @__PURE__ */ a("section", { className: "shepherd-members", "aria-labelledby": y, children: [
207
- /* @__PURE__ */ e("div", { className: "card-head", children: /* @__PURE__ */ e("h3", { id: y, children: "Members" }) }),
208
- /* @__PURE__ */ a("div", { className: "card-body", children: [
209
- k && /* @__PURE__ */ e("p", { role: "alert", children: k }),
210
- u && /* @__PURE__ */ e("p", { role: "status", children: u }),
211
- w ? /* @__PURE__ */ e("p", { role: "status", children: "Loading…" }) : C.length === 0 ? /* @__PURE__ */ e("p", { children: "No members." }) : /* @__PURE__ */ e("ul", { children: C.map((c) => {
212
- const f = c.displayName ?? c.githubLogin ?? c.accountId;
213
- return /* @__PURE__ */ a("li", { children: [
214
- /* @__PURE__ */ e("span", { children: f }),
215
- /* @__PURE__ */ e("span", { className: "role", children: c.role }),
248
+ return /* @__PURE__ */ n("section", { className: "shepherd-members", "aria-labelledby": o, children: [
249
+ /* @__PURE__ */ e("div", { className: "card-head", children: /* @__PURE__ */ e("h3", { id: o, children: "Members" }) }),
250
+ /* @__PURE__ */ n("div", { className: "card-body", children: [
251
+ m && /* @__PURE__ */ e("p", { role: "alert", children: m }),
252
+ f && /* @__PURE__ */ e("p", { role: "status", children: f }),
253
+ N ? /* @__PURE__ */ e("p", { role: "status", children: "Loading…" }) : h.length === 0 ? /* @__PURE__ */ e("p", { children: "No members." }) : /* @__PURE__ */ e("ul", { children: h.map((d) => {
254
+ const k = d.displayName ?? d.githubLogin ?? d.accountId;
255
+ return /* @__PURE__ */ n("li", { children: [
256
+ /* @__PURE__ */ e("span", { children: k }),
257
+ /* @__PURE__ */ e("span", { className: "role", children: d.role }),
216
258
  r && /* @__PURE__ */ e(
217
259
  "button",
218
260
  {
219
261
  type: "button",
220
- "aria-label": `Remove ${f}`,
221
- onClick: () => void x(c.accountId, f),
222
- disabled: s === c.accountId,
262
+ "aria-label": `Remove ${k}`,
263
+ onClick: () => void E(d.accountId, k),
264
+ disabled: w === d.accountId,
223
265
  children: "Remove"
224
266
  }
225
267
  )
226
- ] }, c.accountId);
227
- }) }),
228
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void E(), disabled: v, children: "Leave workspace" })
268
+ ] }, d.accountId);
269
+ }) })
229
270
  ] })
230
271
  ] });
231
272
  }
232
- const J = [
273
+ function q({ workspaceId: t, onMembersChanged: i }) {
274
+ const r = A(), p = U(), [o, h] = a(null), [v, m] = a(null), [l, f] = a(!1), [b, N] = a(""), [g, w] = a(null), [c, C] = a(!1), [E, d] = a(null);
275
+ j(() => {
276
+ h(null), w(null);
277
+ }, [t]);
278
+ async function k() {
279
+ if (!l) {
280
+ f(!0), m(null);
281
+ try {
282
+ const y = await r.createInvite(t, {});
283
+ h(y), i == null || i();
284
+ } catch (y) {
285
+ m(I(y));
286
+ } finally {
287
+ f(!1);
288
+ }
289
+ }
290
+ }
291
+ async function _() {
292
+ if (!(!o || l)) {
293
+ f(!0), m(null);
294
+ try {
295
+ await r.revokeInvite(t, o.code), h(null);
296
+ } catch (y) {
297
+ m(I(y));
298
+ } finally {
299
+ f(!1);
300
+ }
301
+ }
302
+ }
303
+ async function S() {
304
+ if (!(!b.trim() || c)) {
305
+ C(!0), w(null);
306
+ try {
307
+ const y = await r.inviteByEmail(t, b.trim());
308
+ w(`Invite sent to ${y.email}.`), N(""), i == null || i();
309
+ } catch (y) {
310
+ w(I(y));
311
+ } finally {
312
+ C(!1);
313
+ }
314
+ }
315
+ }
316
+ const x = o ? `${window.location.origin}/shepherd/join/${encodeURIComponent(o.code)}` : null;
317
+ async function L(y, T) {
318
+ await navigator.clipboard.writeText(T), d(y), setTimeout(() => d((s) => s === y ? null : s), 2e3);
319
+ }
320
+ return /* @__PURE__ */ n("section", { className: "shepherd-invites", "aria-labelledby": p, children: [
321
+ /* @__PURE__ */ n("div", { className: "card-head", children: [
322
+ /* @__PURE__ */ e("h3", { id: p, children: "Invite people" }),
323
+ /* @__PURE__ */ e("p", { className: "card-sub", children: "Share a code, or send a one-time join link by email." })
324
+ ] }),
325
+ /* @__PURE__ */ n("div", { className: "card-body", children: [
326
+ v && /* @__PURE__ */ e("p", { role: "alert", children: v }),
327
+ /* @__PURE__ */ n("div", { className: "field invites", children: [
328
+ /* @__PURE__ */ e("label", { children: "Invite by code" }),
329
+ /* @__PURE__ */ e("p", { className: "helper", children: "Anyone with the code can join this workspace." }),
330
+ o && /* @__PURE__ */ n("div", { className: "invite-result", children: [
331
+ /* @__PURE__ */ n("div", { className: "invite-result__head", children: [
332
+ /* @__PURE__ */ e("span", { className: "invite-result__eyebrow", children: "Invite code" }),
333
+ /* @__PURE__ */ e("span", { className: "invite-uses", children: o.maxUses === null ? `${o.useCount} uses` : `${o.useCount} / ${o.maxUses} uses` }),
334
+ /* @__PURE__ */ e(
335
+ "button",
336
+ {
337
+ type: "button",
338
+ className: "link-btn",
339
+ "aria-label": "Revoke invite",
340
+ onClick: () => void _(),
341
+ disabled: l,
342
+ children: "Revoke"
343
+ }
344
+ )
345
+ ] }),
346
+ /* @__PURE__ */ n("div", { className: "invite-result__copyrow", children: [
347
+ /* @__PURE__ */ e("code", { children: o.code }),
348
+ /* @__PURE__ */ e(
349
+ "button",
350
+ {
351
+ type: "button",
352
+ className: "copy-btn",
353
+ onClick: () => void L("code", o.code),
354
+ children: E === "code" ? "Copied" : "Copy"
355
+ }
356
+ )
357
+ ] }),
358
+ x && /* @__PURE__ */ n("div", { className: "invite-result__copyrow invite-result__copyrow--link", children: [
359
+ /* @__PURE__ */ e("a", { href: x, children: x }),
360
+ /* @__PURE__ */ e(
361
+ "button",
362
+ {
363
+ type: "button",
364
+ className: "copy-btn",
365
+ onClick: () => void L("link", x),
366
+ children: E === "link" ? "Copied" : "Copy link"
367
+ }
368
+ )
369
+ ] })
370
+ ] }),
371
+ /* @__PURE__ */ e("button", { type: "button", onClick: () => void k(), disabled: l, children: "Create invite" })
372
+ ] }),
373
+ /* @__PURE__ */ n("div", { className: "field email-invite", children: [
374
+ /* @__PURE__ */ e("label", { htmlFor: "invite-email", children: "Invite by email" }),
375
+ /* @__PURE__ */ e("p", { className: "helper", children: "Send a one-time-use join link directly to someone's inbox." }),
376
+ /* @__PURE__ */ n("div", { className: "field__row", children: [
377
+ /* @__PURE__ */ e(
378
+ "input",
379
+ {
380
+ id: "invite-email",
381
+ type: "email",
382
+ placeholder: "name@example.com",
383
+ value: b,
384
+ onChange: (y) => N(y.target.value)
385
+ }
386
+ ),
387
+ /* @__PURE__ */ e("button", { type: "button", onClick: () => void S(), disabled: c, children: "Send invite" })
388
+ ] }),
389
+ g && /* @__PURE__ */ e("p", { className: "email-invite__status", children: g })
390
+ ] })
391
+ ] })
392
+ ] });
393
+ }
394
+ const z = [
233
395
  { id: "claude", label: "Claude Code" },
234
396
  { id: "codex", label: "Codex" },
235
397
  { id: "pi", label: "Pi" },
236
398
  { id: "generic", label: "Generic (JSON)" }
237
- ], X = "shp_<paste-after-generating>", q = {
399
+ ], Q = "shp_<paste-after-generating>", Z = {
238
400
  claude: "claude mcp add shepherd -s user \\",
239
401
  codex: "codex mcp add shepherd \\",
240
402
  pi: "pi mcp add shepherd \\"
241
403
  };
242
- function z(l, t) {
243
- const r = `created ${F(l.createdAt, t)}`, b = l.lastUsedAt ? `last used ${F(l.lastUsedAt, t)}` : "never used";
244
- return `${r} · ${b}`;
404
+ function M(t, i) {
405
+ const r = `created ${D(t.createdAt, i)}`, p = t.lastUsedAt ? `last used ${D(t.lastUsedAt, i)}` : "never used";
406
+ return `${r} · ${p}`;
245
407
  }
246
- function Q(l, t, r) {
247
- return l === "generic" ? JSON.stringify(
408
+ function ee(t, i, r) {
409
+ return t === "generic" ? JSON.stringify(
248
410
  {
249
411
  mcpServers: {
250
412
  shepherd: {
251
413
  command: "npx",
252
414
  args: ["-y", "@korso/shepherd"],
253
- env: { HUB_URL: t, SHEPHERD_TOKEN: r }
415
+ env: { HUB_URL: i, SHEPHERD_TOKEN: r }
254
416
  }
255
417
  }
256
418
  },
257
419
  null,
258
420
  2
259
421
  ) : [
260
- q[l],
261
- ` -e HUB_URL=${t} \\`,
422
+ Z[t],
423
+ ` -e HUB_URL=${i} \\`,
262
424
  ` -e SHEPHERD_TOKEN=${r} \\`,
263
425
  " -- npx -y @korso/shepherd"
264
426
  ].join(`
265
427
  `);
266
428
  }
267
- function V({ workspaceId: l, hubUrl: t }) {
268
- const r = U(), b = t ?? r.baseUrl, d = B(), [y, C] = i("claude"), [g, k] = i(""), [m, u] = i(null), [o, w] = i([]), [h, s] = i(null), [p, v] = i(null), [S, R] = i(!1), [x, E] = i(!1), [c, f] = i(!0), [_, I] = i(null);
269
- async function L() {
429
+ function ne({ workspaceId: t, hubUrl: i }) {
430
+ const r = A(), p = i ?? r.baseUrl, o = U(), [h, v] = a("claude"), [m, l] = a(""), [f, b] = a(null), [N, g] = a([]), [w, c] = a(null), [C, E] = a(null), [d, k] = a(!1), [_, S] = a(!1), [x, L] = a(!0), [y, T] = a(null);
431
+ async function s() {
270
432
  try {
271
- const n = await r.listTokens(l);
272
- w(n.tokens);
273
- } catch (n) {
274
- s(N(n));
433
+ const u = await r.listTokens(t);
434
+ g(u.tokens);
435
+ } catch (u) {
436
+ c(I(u));
275
437
  } finally {
276
- f(!1);
438
+ L(!1);
277
439
  }
278
440
  }
279
- $(() => {
280
- f(!0), L();
281
- }, [r, l]), $(() => {
282
- u(null);
283
- }, [l]);
284
- async function H() {
285
- R(!0), s(null);
441
+ j(() => {
442
+ L(!0), s();
443
+ }, [r, t]), j(() => {
444
+ b(null);
445
+ }, [t]);
446
+ async function R() {
447
+ k(!0), c(null);
286
448
  try {
287
- const n = await r.mintToken(
288
- l,
289
- g.trim() ? { name: g.trim() } : {}
449
+ const u = await r.mintToken(
450
+ t,
451
+ m.trim() ? { name: m.trim() } : {}
290
452
  );
291
- u(n.token), k(""), await L();
292
- } catch (n) {
293
- s(N(n));
453
+ b(u.token), l(""), await s();
454
+ } catch (u) {
455
+ c(I(u));
294
456
  } finally {
295
- R(!1);
457
+ k(!1);
296
458
  }
297
459
  }
298
- async function O(n) {
299
- if (!_) {
300
- I(n), s(null), v(null);
460
+ async function B(u) {
461
+ if (!y) {
462
+ T(u), c(null), E(null);
301
463
  try {
302
- await r.revokeToken(l, n), w((T) => T.filter((P) => P.id !== n)), v("Token revoked");
303
- } catch (T) {
304
- s(N(T));
464
+ await r.revokeToken(t, u), g(($) => $.filter((G) => G.id !== u)), E("Token revoked");
465
+ } catch ($) {
466
+ c(I($));
305
467
  } finally {
306
- I(null);
468
+ T(null);
307
469
  }
308
470
  }
309
471
  }
310
- const A = Q(y, b, m ?? X);
311
- async function j() {
312
- await navigator.clipboard.writeText(A), E(!0), setTimeout(() => E(!1), 2e3);
472
+ const O = ee(h, p, f ?? Q);
473
+ async function W() {
474
+ await navigator.clipboard.writeText(O), S(!0), setTimeout(() => S(!1), 2e3);
313
475
  }
314
- return /* @__PURE__ */ a("section", { className: "shepherd-connect-agent", "aria-labelledby": d, children: [
315
- /* @__PURE__ */ a("div", { className: "card-head", children: [
316
- /* @__PURE__ */ e("h3", { id: d, children: "Connect your agent" }),
476
+ return /* @__PURE__ */ n("section", { className: "shepherd-connect-agent", "aria-labelledby": o, children: [
477
+ /* @__PURE__ */ n("div", { className: "card-head", children: [
478
+ /* @__PURE__ */ e("h3", { id: o, children: "Connect your agent" }),
317
479
  /* @__PURE__ */ e("p", { className: "card-sub", children: "Generate a token, then paste the command into your coding tool." })
318
480
  ] }),
319
- /* @__PURE__ */ a("div", { className: "card-body", children: [
320
- /* @__PURE__ */ a("div", { className: "field", children: [
481
+ /* @__PURE__ */ n("div", { className: "card-body", children: [
482
+ /* @__PURE__ */ n("div", { className: "field", children: [
321
483
  /* @__PURE__ */ e("label", { htmlFor: "connect-tool", children: "Tool" }),
322
484
  /* @__PURE__ */ e(
323
485
  "select",
324
486
  {
325
487
  id: "connect-tool",
326
- value: y,
327
- onChange: (n) => C(n.target.value),
328
- children: J.map((n) => /* @__PURE__ */ e("option", { value: n.id, children: n.label }, n.id))
488
+ value: h,
489
+ onChange: (u) => v(u.target.value),
490
+ children: z.map((u) => /* @__PURE__ */ e("option", { value: u.id, children: u.label }, u.id))
329
491
  }
330
492
  )
331
493
  ] }),
332
- /* @__PURE__ */ a("div", { className: "field generate", children: [
494
+ /* @__PURE__ */ n("div", { className: "field generate", children: [
333
495
  /* @__PURE__ */ e("label", { htmlFor: "token-name", children: "Token name (optional)" }),
334
- /* @__PURE__ */ a("div", { className: "field__row", children: [
496
+ /* @__PURE__ */ n("div", { className: "field__row", children: [
335
497
  /* @__PURE__ */ e(
336
498
  "input",
337
499
  {
338
500
  id: "token-name",
339
501
  type: "text",
340
- value: g,
341
- onChange: (n) => k(n.target.value),
502
+ value: m,
503
+ onChange: (u) => l(u.target.value),
342
504
  placeholder: "e.g. laptop"
343
505
  }
344
506
  ),
345
- /* @__PURE__ */ e("button", { type: "button", onClick: () => void H(), disabled: S, children: "Generate token" })
507
+ /* @__PURE__ */ e("button", { type: "button", onClick: () => void R(), disabled: d, children: "Generate token" })
346
508
  ] })
347
509
  ] }),
348
- h && /* @__PURE__ */ e("p", { role: "alert", children: h }),
349
- p && /* @__PURE__ */ e("p", { role: "status", children: p }),
350
- m && /* @__PURE__ */ e("p", { className: "token-once", role: "status", children: "Copy this token now — it won't be shown again." }),
351
- /* @__PURE__ */ a("div", { className: "install-command", children: [
352
- /* @__PURE__ */ e("pre", { "data-testid": "install-command", children: A }),
353
- /* @__PURE__ */ e("button", { type: "button", className: "install-command__copy", onClick: () => void j(), children: x ? "Copied" : "Copy" })
510
+ w && /* @__PURE__ */ e("p", { role: "alert", children: w }),
511
+ C && /* @__PURE__ */ e("p", { role: "status", children: C }),
512
+ f && /* @__PURE__ */ e("p", { className: "token-once", role: "status", children: "Copy this token now — it won't be shown again." }),
513
+ /* @__PURE__ */ n("div", { className: "install-command", children: [
514
+ /* @__PURE__ */ e("pre", { "data-testid": "install-command", children: O }),
515
+ /* @__PURE__ */ e(
516
+ "button",
517
+ {
518
+ type: "button",
519
+ className: "install-command__copy",
520
+ "aria-label": _ ? "Copied" : "Copy command",
521
+ title: _ ? "Copied" : "Copy",
522
+ onClick: () => void W(),
523
+ children: _ ? /* @__PURE__ */ e(
524
+ "svg",
525
+ {
526
+ width: "15",
527
+ height: "15",
528
+ viewBox: "0 0 24 24",
529
+ fill: "none",
530
+ stroke: "currentColor",
531
+ strokeWidth: "2.5",
532
+ strokeLinecap: "round",
533
+ strokeLinejoin: "round",
534
+ "aria-hidden": "true",
535
+ children: /* @__PURE__ */ e("path", { d: "M20 6 9 17l-5-5" })
536
+ }
537
+ ) : /* @__PURE__ */ n(
538
+ "svg",
539
+ {
540
+ width: "15",
541
+ height: "15",
542
+ viewBox: "0 0 24 24",
543
+ fill: "none",
544
+ stroke: "currentColor",
545
+ strokeWidth: "2",
546
+ strokeLinecap: "round",
547
+ strokeLinejoin: "round",
548
+ "aria-hidden": "true",
549
+ children: [
550
+ /* @__PURE__ */ e("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
551
+ /* @__PURE__ */ e("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
552
+ ]
553
+ }
554
+ )
555
+ }
556
+ )
354
557
  ] }),
355
558
  /* @__PURE__ */ e("h4", { children: "Existing tokens" }),
356
- c ? /* @__PURE__ */ e("p", { role: "status", children: "Loading…" }) : o.length === 0 ? /* @__PURE__ */ e("p", { children: "No tokens yet." }) : /* @__PURE__ */ e("ul", { children: o.map((n) => {
357
- const T = n.name ?? n.id;
358
- return /* @__PURE__ */ a("li", { children: [
359
- /* @__PURE__ */ e("span", { children: T }),
360
- /* @__PURE__ */ e("span", { className: "token-meta", children: z(n, Date.now()) }),
361
- n.revokedAt ? /* @__PURE__ */ e("span", { className: "revoked", children: "revoked" }) : /* @__PURE__ */ e(
559
+ x ? /* @__PURE__ */ e("p", { role: "status", children: "Loading…" }) : N.length === 0 ? /* @__PURE__ */ e("p", { children: "No tokens yet." }) : /* @__PURE__ */ e("ul", { children: N.map((u) => {
560
+ const $ = u.name ?? u.id;
561
+ return /* @__PURE__ */ n("li", { children: [
562
+ /* @__PURE__ */ e("span", { children: $ }),
563
+ /* @__PURE__ */ e("span", { className: "token-meta", children: M(u, Date.now()) }),
564
+ u.revokedAt ? /* @__PURE__ */ e("span", { className: "revoked", children: "revoked" }) : /* @__PURE__ */ e(
362
565
  "button",
363
566
  {
364
567
  type: "button",
365
- "aria-label": `Revoke token ${T}`,
366
- onClick: () => void O(n.id),
367
- disabled: _ === n.id,
568
+ "aria-label": `Revoke token ${$}`,
569
+ onClick: () => void B(u.id),
570
+ disabled: y === u.id,
368
571
  children: "Revoke"
369
572
  }
370
573
  )
371
- ] }, n.id);
574
+ ] }, u.id);
372
575
  }) })
373
576
  ] })
374
577
  ] });
375
578
  }
376
- function ee({ hubUrl: l }) {
377
- const t = U(), [r, b] = i({ status: "loading" }), [d, y] = i(null), [C, g] = i(0), k = D(async () => {
579
+ const te = [
580
+ { id: "general", label: "General" },
581
+ { id: "members", label: "Members" },
582
+ { id: "agent", label: "Agent" }
583
+ ];
584
+ function ae({
585
+ workspace: t,
586
+ hubUrl: i,
587
+ membersRefreshKey: r,
588
+ onMembersChanged: p,
589
+ onLeft: o
590
+ }) {
591
+ const [h, v] = a("general"), m = t.role === "admin";
592
+ return /* @__PURE__ */ n("div", { className: "config-layout", children: [
593
+ /* @__PURE__ */ e("nav", { className: "config-nav", "aria-label": "Configuration sections", children: te.map(({ id: l, label: f }) => /* @__PURE__ */ e(
594
+ "button",
595
+ {
596
+ type: "button",
597
+ className: "config-nav__item" + (h === l ? " config-nav__item--on" : ""),
598
+ "aria-current": h === l ? "page" : void 0,
599
+ onClick: () => v(l),
600
+ children: f
601
+ },
602
+ l
603
+ )) }),
604
+ /* @__PURE__ */ n("div", { className: "config-panel", children: [
605
+ h === "general" && /* @__PURE__ */ e(V, { workspace: t, onLeft: o }),
606
+ h === "members" && /* @__PURE__ */ n(H, { children: [
607
+ /* @__PURE__ */ e(
608
+ X,
609
+ {
610
+ workspaceId: t.id,
611
+ refreshKey: r,
612
+ canRemove: m
613
+ }
614
+ ),
615
+ m && /* @__PURE__ */ e(q, { workspaceId: t.id, onMembersChanged: p })
616
+ ] }),
617
+ h === "agent" && /* @__PURE__ */ e(ne, { workspaceId: t.id, hubUrl: i })
618
+ ] })
619
+ ] });
620
+ }
621
+ function se({ hubUrl: t }) {
622
+ const i = A(), [r, p] = a({ status: "loading" }), [o, h] = a(null), [v, m] = a(0), l = Y(async () => {
378
623
  try {
379
- const h = await t.listWorkspaces();
380
- b({ status: "ready", workspaces: h.workspaces }), y(
381
- (s) => {
382
- var p;
383
- return s && h.workspaces.some((v) => v.id === s) ? s : ((p = h.workspaces[0]) == null ? void 0 : p.id) ?? null;
624
+ const c = await i.listWorkspaces();
625
+ p({ status: "ready", workspaces: c.workspaces }), h(
626
+ (C) => {
627
+ var E;
628
+ return C && c.workspaces.some((d) => d.id === C) ? C : ((E = c.workspaces[0]) == null ? void 0 : E.id) ?? null;
384
629
  }
385
630
  );
386
- } catch (h) {
387
- b({ status: "error", message: N(h) });
631
+ } catch (c) {
632
+ p({ status: "error", message: I(c) });
388
633
  }
389
- }, [t]);
390
- $(() => {
391
- k();
392
- }, [k]);
393
- const m = r.status === "ready" ? r.workspaces : [], u = m.find((h) => h.id === d) ?? null;
634
+ }, [i]);
635
+ j(() => {
636
+ l();
637
+ }, [l]);
638
+ const f = r.status === "ready" ? r.workspaces : [], b = f.find((c) => c.id === o) ?? null;
394
639
  if (r.status === "loading")
395
640
  return /* @__PURE__ */ e("div", { className: "shepherd-root", children: /* @__PURE__ */ e("p", { role: "status", children: "Loading…" }) });
396
641
  if (r.status === "error")
397
642
  return /* @__PURE__ */ e("div", { className: "shepherd-root", children: /* @__PURE__ */ e("p", { role: "alert", children: r.message }) });
398
- const o = m.length > 0, w = /* @__PURE__ */ a("section", { className: "shepherd-config", "aria-labelledby": "config-heading", children: [
643
+ const N = f.length > 0, g = /* @__PURE__ */ e(
644
+ J,
645
+ {
646
+ workspaces: f,
647
+ selected: b,
648
+ onSelect: h,
649
+ onChanged: () => {
650
+ l();
651
+ },
652
+ onMembersChanged: () => m((c) => c + 1)
653
+ }
654
+ ), w = /* @__PURE__ */ n("section", { className: "shepherd-config", "aria-labelledby": "config-heading", children: [
399
655
  /* @__PURE__ */ e("h2", { id: "config-heading", children: "Configuration" }),
400
- /* @__PURE__ */ e(
401
- K,
656
+ b ? /* @__PURE__ */ e(
657
+ ae,
402
658
  {
403
- workspaces: m,
404
- selected: u,
405
- onChanged: () => {
406
- k();
407
- },
408
- onSelect: y,
409
- onMembersChanged: () => g((h) => h + 1)
659
+ workspace: b,
660
+ hubUrl: t,
661
+ membersRefreshKey: v,
662
+ onMembersChanged: () => m((c) => c + 1),
663
+ onLeft: () => void l()
410
664
  }
411
- ),
412
- u && /* @__PURE__ */ e(
413
- G,
414
- {
415
- workspaceId: u.id,
416
- refreshKey: C,
417
- canRemove: u.role === "admin",
418
- onLeft: () => void k()
419
- }
420
- ),
421
- u && /* @__PURE__ */ e(V, { workspaceId: u.id, hubUrl: l })
665
+ ) : /* @__PURE__ */ n("p", { className: "config-none", children: [
666
+ "You're not in a workspace yet. Use the ",
667
+ /* @__PURE__ */ e("b", { children: "Get started ▾" }),
668
+ " menu at the top to create one or join with an invite code."
669
+ ] })
422
670
  ] });
423
671
  return /* @__PURE__ */ e("div", { className: "shepherd-root", children: /* @__PURE__ */ e(
424
- W,
672
+ P,
425
673
  {
426
- workspaceId: u == null ? void 0 : u.id,
674
+ workspaceId: b == null ? void 0 : b.id,
427
675
  config: w,
428
- hasWorkspace: o
676
+ switcher: g,
677
+ hasWorkspace: N
429
678
  }
430
679
  ) });
431
680
  }
432
681
  export {
433
- V as ConnectAgent,
434
- W as Dashboard,
435
- ie as EmptyState,
436
- G as Members,
437
- ae as ShepherdClientError,
438
- le as ShepherdClientProvider,
439
- ee as ShepherdRoot,
440
- K as Workspaces,
441
- re as createShepherdClient,
442
- N as describeError,
443
- U as useShepherdClient
682
+ ae as ConfigPanel,
683
+ ne as ConnectAgent,
684
+ P as Dashboard,
685
+ de as EmptyState,
686
+ V as GeneralSettings,
687
+ q as Invites,
688
+ X as Members,
689
+ ue as ShepherdClientError,
690
+ he as ShepherdClientProvider,
691
+ se as ShepherdRoot,
692
+ J as WorkspaceSwitcher,
693
+ me as createShepherdClient,
694
+ I as describeError,
695
+ A as useShepherdClient
444
696
  };