@korso/shepherd-ui 0.2.2 → 0.3.1

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.
@@ -1,6 +1,6 @@
1
1
  import { jsx as e, jsxs as l } from "react/jsx-runtime";
2
2
  import { useState as s, useMemo as h } from "react";
3
- import { c as d, a as m, D as u } from "./Dashboard-B7nioe5N.js";
3
+ import { c as d, a as m, D as u } from "./Dashboard-Bgi50wCo.js";
4
4
  const i = "shepherd.token";
5
5
  function p() {
6
6
  try {
@@ -184,17 +184,20 @@
184
184
  column heads, hairline rules) so Config reads as part of the board. --- */
185
185
  .shepherd-root { max-width:1100px; margin:0 auto; padding:40px 44px; }
186
186
  .shepherd-root > main { padding-top:18px; }
187
- .shepherd-config { display:flex; flex-direction:column; gap:24px; }
188
- .shepherd-config h2 { font-size:16px; margin:0 0 4px; }
189
-
190
- /* Every config card shares one shell: a header band sitting on a hairline
191
- above a padded body. Nested cards (Members) reuse the same anatomy. */
192
- .shepherd-workspaces, .shepherd-members, .shepherd-connect-agent {
193
- border:1px solid var(--line); border-radius:12px; background:var(--card); overflow:hidden; }
194
- .shepherd-config .card-head { padding:18px 20px 14px; border-bottom:1px solid var(--line2); }
195
- .shepherd-config .card-head h3 { font-size:14px; font-weight:600; margin:0; }
196
- .shepherd-config .card-sub { margin:3px 0 0; font-size:12.5px; color:var(--ink3); }
197
- .shepherd-config .card-body { padding:16px 20px 18px; display:flex; flex-direction:column; gap:16px; }
187
+ .shepherd-config { display:flex; flex-direction:column; }
188
+ .shepherd-config h2 { font-size:16px; margin:0 0 22px; }
189
+
190
+ /* Flat sections: no card chrome. Each section sits directly on the page;
191
+ consecutive sections are set off by a hairline rather than a box. */
192
+ .shepherd-config > section { padding:26px 0; }
193
+ .shepherd-config > section:first-of-type { padding-top:0; }
194
+ .shepherd-config > section + section { border-top:1px solid var(--line2); }
195
+ .shepherd-config .card-head h3 {
196
+ font-size:13px; font-weight:600; letter-spacing:.04em; text-transform:uppercase;
197
+ color:var(--ink2); margin:0; }
198
+ .shepherd-config .card-sub { margin:4px 0 0; font-size:12.5px; color:var(--ink3); }
199
+ .shepherd-config .card-head { margin-bottom:16px; }
200
+ .shepherd-config .card-body { display:flex; flex-direction:column; gap:16px; }
198
201
  .shepherd-config .card-body > [role="alert"] { margin:0; color:var(--drop); font-size:13px; }
199
202
  .shepherd-config .card-body > [role="status"] { margin:0; color:var(--ink2); font-size:13px; }
200
203
 
@@ -205,13 +208,17 @@
205
208
  font-size:11px; font-weight:600; letter-spacing:.05em; text-transform:uppercase; color:var(--ink3); }
206
209
  .shepherd-config .helper { margin:0; font-size:12.5px; color:var(--ink2); }
207
210
  .shepherd-config .field > select { width:100%; }
211
+ .shepherd-config select {
212
+ appearance:none; -webkit-appearance:none; -moz-appearance:none;
213
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%239c917a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
214
+ background-repeat:no-repeat; background-position:right 28px center; padding-right:44px; }
208
215
  .shepherd-config .field__row { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
209
216
  .shepherd-config .field__row > input { flex:1; min-width:200px; }
210
217
 
211
- /* Admin zone (invites + roster) is set off from create/join by a hairline. */
218
+ /* Admin zone (invites) is set off from create/join by a hairline. */
212
219
  .shepherd-workspaces .admin { display:flex; flex-direction:column; gap:14px;
213
220
  padding-top:16px; border-top:1px solid var(--line2); }
214
- .shepherd-workspaces .invites { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
221
+ .shepherd-workspaces .invites { display:flex; flex-direction:column; gap:10px; align-items:flex-start; }
215
222
 
216
223
  .shepherd-config input, .shepherd-config select {
217
224
  padding:9px 12px; border-radius:8px; border:1px solid var(--line);
@@ -227,26 +234,75 @@
227
234
  .shepherd-config button:hover:not(:disabled) { background:#413a2a; }
228
235
  .shepherd-config button:disabled { opacity:.55; cursor:default; }
229
236
 
230
- /* Token / member rows: leading name grows, meta + action ride the right. */
231
- .shepherd-config ul { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:6px; }
232
- .shepherd-config li { display:flex; align-items:center; gap:10px; padding:8px 12px;
233
- border:1px solid var(--line2); border-radius:8px; background:var(--bg); font-size:13px; }
237
+ /* Token / member rows: leading name grows, meta + action ride the right.
238
+ Flat rows separated by hairlines (mirrors the board's .claim rows)
239
+ rather than individually boxed items. */
240
+ .shepherd-config ul { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; }
241
+ .shepherd-config li { display:flex; align-items:center; gap:10px; padding:10px 0; font-size:13px; }
242
+ .shepherd-config li + li { border-top:1px solid var(--line2); }
234
243
  .shepherd-config li > span:first-child { flex:1; min-width:0; font-weight:500; }
235
244
  .shepherd-config li button { padding:5px 12px; }
236
245
  .shepherd-config .role { color:var(--ink3); font-size:12px; }
246
+ .shepherd-config .token-meta { color:var(--ink3); font-size:12px; }
247
+ .shepherd-config .email-invite__status { margin:0; font-size:12.5px; color:var(--ink2); }
237
248
 
238
249
  /* Install command block. */
250
+ .shepherd-connect-agent .install-command { position:relative; }
239
251
  .shepherd-connect-agent pre { margin:0; padding:12px 14px; border-radius:8px;
240
252
  border:1px solid var(--line); background:var(--bg); color:var(--ink);
241
253
  font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12px; line-height:1.5;
242
254
  overflow-x:auto; white-space:pre-wrap; word-break:break-word; }
255
+ .shepherd-connect-agent .install-command__copy {
256
+ position:absolute; top:8px; right:8px; padding:4px 10px; font-size:11px;
257
+ border-radius:6px; border:1px solid var(--line); background:var(--card);
258
+ color:var(--ink2); cursor:pointer; transition:background .12s ease, color .12s ease; }
259
+ .shepherd-connect-agent .install-command__copy:hover { background:var(--ink); color:var(--bg); }
243
260
  .shepherd-connect-agent h4 { margin:6px 0 0; font-size:11px; font-weight:600;
244
261
  letter-spacing:.05em; text-transform:uppercase; color:var(--ink3); }
245
262
 
246
263
  .shepherd-config .invite-result, .shepherd-connect-agent .token-once {
247
264
  font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12px;
248
- word-break:break-all; padding:8px 10px; border-radius:8px;
265
+ padding:10px 12px; border-radius:8px;
249
266
  background:var(--chip); border:1px solid var(--line2); }
267
+ .shepherd-config .invite-result { display:flex; flex-direction:column; gap:8px; word-break:break-all; }
268
+ .shepherd-config .invite-result__row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
269
+ .shepherd-config .invite-result a { color:var(--ink2); }
250
270
  .shepherd-config .revoked { color:var(--ink3); text-decoration:line-through; }
251
271
  .shepherd-empty-state { text-align:center; color:var(--ink2); padding:48px 24px; }
252
272
  .shepherd-empty-state button { margin-top:14px; }
273
+
274
+ /* Feedback widget: fixed bottom-right, floats over every tab. */
275
+ .shepherd-feedback { position:fixed; right:20px; bottom:20px; z-index:10; }
276
+ .shepherd-feedback__trigger {
277
+ padding:9px 16px; border-radius:999px; border:1px solid var(--ink);
278
+ background:var(--ink); color:var(--bg); font-weight:600; font-size:13px; font:inherit;
279
+ cursor:pointer; box-shadow:0 8px 24px rgba(50,40,20,.18); }
280
+ .shepherd-feedback__trigger:hover { background:#413a2a; }
281
+ .shepherd-feedback__panel {
282
+ position:absolute; right:0; bottom:calc(100% + 10px); width:280px;
283
+ display:flex; flex-direction:column; gap:10px; padding:16px;
284
+ background:var(--card); border:1px solid var(--line); border-radius:12px;
285
+ box-shadow:0 8px 24px rgba(50,40,20,.18); }
286
+ .shepherd-feedback__panel h3 {
287
+ margin:0; font-size:13px; font-weight:600; letter-spacing:.04em;
288
+ text-transform:uppercase; color:var(--ink2); }
289
+ .shepherd-feedback__panel [role="status"] { margin:0; font-size:13px; color:var(--ink2); }
290
+ .shepherd-feedback__panel [role="alert"] { margin:0; font-size:13px; color:var(--drop); }
291
+ .shepherd-feedback__types { display:flex; gap:6px; }
292
+ .shepherd-feedback__types button {
293
+ flex:1; padding:6px 0; border-radius:8px; border:1px solid var(--line);
294
+ background:transparent; color:var(--ink2); font-size:12.5px; font:inherit;
295
+ cursor:pointer; transition:background .12s ease, color .12s ease; }
296
+ .shepherd-feedback__types button[aria-pressed="true"] {
297
+ background:var(--ink); color:var(--bg); border-color:var(--ink); font-weight:600; }
298
+ .shepherd-feedback__panel textarea {
299
+ min-height:80px; padding:9px 12px; border-radius:8px; border:1px solid var(--line);
300
+ background:var(--bg); color:var(--ink); font:inherit; resize:vertical; }
301
+ .shepherd-feedback__panel textarea::placeholder { color:var(--ink3); }
302
+ .shepherd-feedback__panel textarea:focus {
303
+ outline:none; border-color:var(--terr); box-shadow:0 0 0 3px rgba(122,106,72,.14); }
304
+ .shepherd-feedback__panel > button {
305
+ padding:9px 16px; border-radius:8px; border:1px solid var(--ink);
306
+ background:var(--ink); color:var(--bg); font-weight:600; cursor:pointer; font:inherit; }
307
+ .shepherd-feedback__panel > button:hover:not(:disabled) { background:#413a2a; }
308
+ .shepherd-feedback__panel > button:disabled { opacity:.55; cursor:default; }
@@ -0,0 +1 @@
1
+ import "./styles.css";
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { StrictMode } from "react";
3
+ import { createRoot } from "react-dom/client";
4
+ import "./styles.css";
5
+ import { ShepherdClientProvider } from "./context.js";
6
+ import { ShepherdRoot } from "./ShepherdRoot.js";
7
+ // ---------------------------------------------------------------------------
8
+ // Dev-only visual preview of the Config surface. NOT part of the published
9
+ // library or the self-host build (vite.config.app.ts's build:app only bundles
10
+ // index.html) — `npm run dev` serves this alongside it at /preview.html. Backs
11
+ // every ShepherdClient method with in-memory state instead of a real Hub, so
12
+ // the redesign can be clicked through without Postgres or a minted token.
13
+ // ---------------------------------------------------------------------------
14
+ const EMPTY_LANDSCAPE = {
15
+ agents: [],
16
+ tasks: [],
17
+ announcements: [],
18
+ serverTime: new Date().toISOString(),
19
+ };
20
+ const EMPTY_ANNOUNCE = { ok: true, announcementIds: [] };
21
+ let members = [
22
+ { accountId: "acc_admin", displayName: "Korso Admin", githubLogin: "korso-admin", avatarUrl: null, role: "admin" },
23
+ { accountId: "acc_1", displayName: "Alex Rivera", githubLogin: "arivera", avatarUrl: null, role: "member" },
24
+ { accountId: "acc_2", displayName: "Sam Okafor", githubLogin: "sokafor", avatarUrl: null, role: "member" },
25
+ ];
26
+ let tokens = [
27
+ {
28
+ id: "tok_1",
29
+ name: "laptop",
30
+ createdAt: "2026-06-01T00:00:00.000Z",
31
+ lastUsedAt: "2026-06-29T10:00:00.000Z",
32
+ revokedAt: null,
33
+ },
34
+ {
35
+ id: "tok_2",
36
+ name: null,
37
+ createdAt: "2026-06-20T00:00:00.000Z",
38
+ lastUsedAt: null,
39
+ revokedAt: null,
40
+ },
41
+ ];
42
+ let nextTokenId = 3;
43
+ let lastInvite = null;
44
+ const workspace = { id: "ws_preview", slug: "acme", name: "Acme Engineering", role: "admin" };
45
+ const previewClient = {
46
+ baseUrl: "https://shepherd-hub-preview.a.run.app",
47
+ listWorkspaces: async () => ({ workspaces: [workspace] }),
48
+ createWorkspace: async (_body) => workspace,
49
+ mintToken: async (_workspaceId, body) => {
50
+ const id = `tok_${nextTokenId++}`;
51
+ tokens = [
52
+ ...tokens,
53
+ { id, name: body.name ?? null, createdAt: new Date().toISOString(), lastUsedAt: null, revokedAt: null },
54
+ ];
55
+ return { token: `shp_previewtoken${id}`, id };
56
+ },
57
+ listTokens: async () => ({ tokens }),
58
+ revokeToken: async (_workspaceId, tokenId) => {
59
+ tokens = tokens.map((t) => (t.id === tokenId ? { ...t, revokedAt: new Date().toISOString() } : t));
60
+ },
61
+ createInvite: async (_workspaceId, body) => {
62
+ lastInvite = {
63
+ code: "PREVIEW-CODE",
64
+ expiresAt: null,
65
+ maxUses: body.maxUses ?? null,
66
+ useCount: 0,
67
+ };
68
+ return lastInvite;
69
+ },
70
+ inviteByEmail: async (_workspaceId, email) => ({
71
+ email,
72
+ sentAt: new Date().toISOString(),
73
+ }),
74
+ revokeInvite: async () => {
75
+ lastInvite = null;
76
+ },
77
+ redeemInvite: async () => ({ workspace }),
78
+ listMembers: async () => ({ members }),
79
+ removeMember: async (_workspaceId, accountId) => {
80
+ members = members.filter((m) => m.accountId !== accountId);
81
+ },
82
+ leave: async () => { },
83
+ landscape: async () => EMPTY_LANDSCAPE,
84
+ announceTo: async (_workspaceId, _body) => EMPTY_ANNOUNCE,
85
+ getLandscape: async () => EMPTY_LANDSCAPE,
86
+ announce: async (_body) => EMPTY_ANNOUNCE,
87
+ submitFeedback: async () => ({ ok: true, id: "fb_preview" }),
88
+ };
89
+ createRoot(document.getElementById("root")).render(_jsx(StrictMode, { children: _jsx(ShepherdClientProvider, { client: previewClient, children: _jsx(ShepherdRoot, { hubUrl: "https://shepherd-hub-preview.a.run.app" }) }) }));