@liiift-studio/deploy-vercel-from-sanity 0.1.6 → 0.2.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/index.js CHANGED
@@ -24,14 +24,14 @@ __export(index_exports, {
24
24
  vercelDeploySchema: () => vercelDeploySchema
25
25
  });
26
26
  module.exports = __toCommonJS(index_exports);
27
- var import_sanity4 = require("sanity");
28
- var import_icons6 = require("@sanity/icons");
27
+ var import_sanity5 = require("sanity");
28
+ var import_icons7 = require("@sanity/icons");
29
29
 
30
30
  // src/components/DeployTool.tsx
31
- var import_react4 = require("react");
32
- var import_sanity2 = require("sanity");
33
- var import_ui5 = require("@sanity/ui");
34
- var import_icons4 = require("@sanity/icons");
31
+ var import_react5 = require("react");
32
+ var import_sanity3 = require("sanity");
33
+ var import_ui6 = require("@sanity/ui");
34
+ var import_icons5 = require("@sanity/icons");
35
35
 
36
36
  // src/components/DeployItem.tsx
37
37
  var import_react2 = require("react");
@@ -180,7 +180,7 @@ function StatusBadge({ state, showSpinner }) {
180
180
  const spinning = showSpinner && (state === "QUEUED" || state === "INITIALIZING" || state === "BUILDING");
181
181
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ui.Flex, { align: "center", gap: 2, children: [
182
182
  spinning && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Spinner, { muted: true }),
183
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Badge, { tone, mode: "outline", children: label })
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Badge, { tone, padding: 2, children: label })
184
184
  ] });
185
185
  }
186
186
 
@@ -245,7 +245,7 @@ function DeployHistory({ target, token, onClose }) {
245
245
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Text, { size: 1, style: { textDecoration: "underline" }, children: d.url.length > 36 ? `${d.url.slice(0, 36)}\u2026` : d.url })
246
246
  }
247
247
  ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Text, { size: 1, muted: true, children: "\u2014" }) }),
248
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Box, { flex: 1, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Badge, { tone, mode: "outline", children: label }) }),
248
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Box, { flex: 1, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Badge, { tone, children: label }) }),
249
249
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Box, { flex: 2, style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui2.Stack, { space: 1, children: [
250
250
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Text, { size: 1, children: branch }),
251
251
  sha && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui2.Text, { size: 0, muted: true, children: [
@@ -275,7 +275,8 @@ function DeployHistory({ target, token, onClose }) {
275
275
  // src/components/DeployItem.tsx
276
276
  var import_jsx_runtime3 = require("react/jsx-runtime");
277
277
  var POLL_INTERVAL_MS = 5e3;
278
- function DeployItem({ target, token, onDelete }) {
278
+ var LABEL_WIDTH = 64;
279
+ function DeployItem({ target, token, onDelete, onEdit }) {
279
280
  const { projectId, hookId } = parseHookUrl(target.url);
280
281
  const [deployments, setDeployments] = (0, import_react2.useState)([]);
281
282
  const [loadingInitial, setLoadingInitial] = (0, import_react2.useState)(true);
@@ -285,6 +286,7 @@ function DeployItem({ target, token, onDelete }) {
285
286
  const [showHistory, setShowHistory] = (0, import_react2.useState)(false);
286
287
  const [elapsed, setElapsed] = (0, import_react2.useState)(0);
287
288
  const [copied, setCopied] = (0, import_react2.useState)(false);
289
+ const [showDetails, setShowDetails] = (0, import_react2.useState)(false);
288
290
  const [showErrorLogs, setShowErrorLogs] = (0, import_react2.useState)(false);
289
291
  const [errorLines, setErrorLines] = (0, import_react2.useState)([]);
290
292
  const [loadingLogs, setLoadingLogs] = (0, import_react2.useState)(false);
@@ -383,140 +385,134 @@ function DeployItem({ target, token, onDelete }) {
383
385
  }
384
386
  }, [latest?.uid, token, target.teamId]);
385
387
  const toggleErrorLogs = (0, import_react2.useCallback)(() => {
386
- if (!showErrorLogs && errorLines.length === 0 && !logError) {
387
- fetchErrorLogs();
388
- }
388
+ if (!showErrorLogs && errorLines.length === 0 && !logError) fetchErrorLogs();
389
389
  setShowErrorLogs((v) => !v);
390
390
  }, [showErrorLogs, errorLines.length, logError, fetchErrorLogs]);
391
391
  const branch = latest?.meta?.githubCommitRef;
392
392
  const commitMsg = latest?.meta?.githubCommitMessage?.split("\n")[0];
393
393
  const sha = shortSha(latest?.meta?.githubCommitSha);
394
+ const fullSha = latest?.meta?.githubCommitSha;
394
395
  const creator = latest?.creator?.username;
395
396
  const deployedAt = latest?.created ? timeAgo(latest.created) : null;
396
397
  const vercelProjectUrl = projectHref(latest?.inspectorUrl);
397
398
  const isError = latest?.state === "ERROR";
398
399
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
399
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Card, { padding: 4, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 4, align: "center", children: [
400
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, flex: 1, style: { minWidth: 0 }, children: [
401
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", justify: "space-between", gap: 2, children: [
402
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 2, weight: "semibold", children: target.name }),
403
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
404
- import_ui3.MenuButton,
405
- {
406
- button: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Button, { mode: "ghost", icon: import_icons2.EllipsisVerticalIcon, padding: 2 }),
407
- id: `menu-${target._id}`,
408
- menu: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Menu, { children: [
409
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
410
- import_ui3.MenuItem,
411
- {
412
- text: "History",
413
- icon: import_icons2.ClockIcon,
414
- onClick: () => setShowHistory(true)
415
- }
416
- ),
417
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
418
- import_ui3.MenuItem,
419
- {
420
- text: "Build logs",
421
- icon: import_icons2.LaunchIcon,
422
- as: "a",
423
- href: safeHref(latest?.inspectorUrl),
424
- target: "_blank",
425
- rel: "noreferrer"
426
- }
427
- ),
428
- vercelProjectUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
429
- import_ui3.MenuItem,
430
- {
431
- text: "Open in Vercel",
432
- icon: import_icons2.LaunchIcon,
433
- as: "a",
434
- href: vercelProjectUrl,
435
- target: "_blank",
436
- rel: "noreferrer"
437
- }
438
- ),
439
- !target.disableDeleteAction && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
440
- import_ui3.MenuItem,
441
- {
442
- text: "Delete",
443
- icon: import_icons2.TrashIcon,
444
- tone: "critical",
445
- onClick: () => onDelete(target)
446
- }
447
- )
448
- ] }),
449
- popover: { placement: "bottom-end" }
450
- }
451
- )
452
- ] }),
453
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, wrap: "wrap", children: [
454
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, children: projectId ? `${projectId.slice(0, 18)}\u2026` : "\u2014" }),
455
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, children: "\xB7" }),
456
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Text, { size: 0, muted: true, children: [
457
- "Hook: ",
458
- hookId || "\u2014"
459
- ] }),
460
- target.teamId && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
461
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, children: "\xB7" }),
462
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Text, { size: 0, muted: true, children: [
463
- "Team: ",
464
- target.teamId
465
- ] })
466
- ] })
467
- ] }),
468
- loadingInitial ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, children: [
469
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true }),
470
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: "Loading\u2026" })
471
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
472
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, wrap: "wrap", children: [
473
- triggering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, children: [
474
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true }),
475
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Badge, { tone: "caution", mode: "outline", children: "Triggering\u2026" })
476
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { state: latest?.state, showSpinner: true }),
477
- isActive && elapsed > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
478
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.ClockIcon, {}),
479
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: formatDuration(elapsed) })
480
- ] }) : !isActive && deployedAt ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: deployedAt }) : null,
481
- branch && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
482
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: "\xB7" }),
483
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Badge, { tone: "default", mode: "outline", children: branch })
400
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Card, { radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "stretch", className: "dvfs-card-flex", children: [
401
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { direction: "column", flex: 1, style: { minWidth: 0 }, children: [
402
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 3, padding: 3, style: { flex: 1 }, children: [
403
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", justify: "space-between", gap: 2, children: [
404
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, style: { minWidth: 0, flexWrap: "wrap" }, children: [
405
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 2, weight: "semibold", style: { flexShrink: 0 }, children: target.name }),
406
+ branch && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Badge, { tone: "default", padding: 2, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
407
+ branch,
408
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", style: { marginLeft: "-0.1em", opacity: 0.5 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 3.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm0 2.122a2.25 2.25 0 1 0-1.5 0v.878A2.25 2.25 0 0 0 5.75 8.5h1.5v2.128a2.251 2.251 0 1 0 1.5 0V8.5h1.5a2.25 2.25 0 0 0 2.25-2.25v-.878a2.25 2.25 0 1 0-1.5 0v.878a.75.75 0 0 1-.75.75h-4.5A.75.75 0 0 1 5 6.25v-.878zm3.75 7.378a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm3-8.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0z" }) })
409
+ ] }) }),
410
+ token && !loadingInitial && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
411
+ triggering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
412
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true }),
413
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Badge, { tone: "caution", padding: 2, children: "Triggering\u2026" })
414
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { state: latest?.state, showSpinner: true }),
415
+ isActive && elapsed > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
416
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.ClockIcon, {}),
417
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: formatDuration(elapsed) })
418
+ ] }) : !isActive && deployedAt ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: deployedAt }) : null
419
+ ] })
484
420
  ] }),
485
- sha && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
486
- import_ui3.Tooltip,
421
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
422
+ import_ui3.MenuButton,
487
423
  {
488
- content: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Box, { padding: 2, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: commitMsg ?? sha }) }),
489
- portal: true,
490
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
491
- import_ui3.Text,
492
- {
493
- size: 1,
494
- muted: true,
495
- style: { cursor: "default", fontFamily: "monospace" },
496
- children: sha
497
- }
498
- )
424
+ button: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Button, { mode: "ghost", icon: import_icons2.EllipsisVerticalIcon, padding: 2 }),
425
+ id: `menu-${target._id}`,
426
+ menu: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Menu, { children: [
427
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
428
+ import_ui3.MenuItem,
429
+ {
430
+ text: "Edit target",
431
+ icon: import_icons2.EditIcon,
432
+ onClick: () => onEdit(target)
433
+ }
434
+ ),
435
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
436
+ import_ui3.MenuItem,
437
+ {
438
+ text: "History",
439
+ icon: import_icons2.ClockIcon,
440
+ onClick: () => setShowHistory(true)
441
+ }
442
+ ),
443
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
444
+ import_ui3.MenuItem,
445
+ {
446
+ text: "Build logs",
447
+ icon: import_icons2.LaunchIcon,
448
+ as: "a",
449
+ href: safeHref(latest?.inspectorUrl),
450
+ target: "_blank",
451
+ rel: "noreferrer"
452
+ }
453
+ ),
454
+ vercelProjectUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
455
+ import_ui3.MenuItem,
456
+ {
457
+ text: "Open in Vercel",
458
+ icon: import_icons2.LaunchIcon,
459
+ as: "a",
460
+ href: vercelProjectUrl,
461
+ target: "_blank",
462
+ rel: "noreferrer"
463
+ }
464
+ ),
465
+ !target.disableDeleteAction && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
466
+ import_ui3.MenuItem,
467
+ {
468
+ text: "Delete",
469
+ icon: import_icons2.TrashIcon,
470
+ tone: "critical",
471
+ onClick: () => onDelete(target)
472
+ }
473
+ )
474
+ ] }),
475
+ popover: { placement: "bottom-end" }
499
476
  }
500
- ),
501
- creator && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Text, { size: 1, muted: true, children: [
502
- "by ",
503
- creator
504
- ] }),
505
- latest?.url && latest.state === "READY" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
506
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
477
+ )
478
+ ] }),
479
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("hr", { style: { border: "none", borderTop: "1px solid currentColor", opacity: 0.1, margin: 0 } }),
480
+ !token ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: "Connect a Vercel API token to see deployment status." }) : loadingInitial ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, children: [
481
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true }),
482
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: "Loading\u2026" })
483
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
484
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, wrap: "wrap", children: [
485
+ latest?.url && latest.state === "READY" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
507
486
  "a",
508
487
  {
509
488
  href: `https://${latest.url}`,
510
489
  target: "_blank",
511
490
  rel: "noreferrer",
512
491
  style: { color: "inherit" },
513
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
514
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.LaunchIcon, {}),
515
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: "Preview" })
516
- ] })
492
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Flex, { align: "center", gap: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: latest.url }) })
493
+ }
494
+ ) }),
495
+ sha && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
496
+ import_ui3.Tooltip,
497
+ {
498
+ content: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Box, { padding: 2, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: commitMsg ?? sha }) }),
499
+ portal: true,
500
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
501
+ import_ui3.Text,
502
+ {
503
+ size: 1,
504
+ muted: true,
505
+ style: { cursor: "default", fontFamily: "monospace" },
506
+ children: sha
507
+ }
508
+ )
517
509
  }
518
510
  ),
519
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
511
+ creator && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Text, { size: 1, muted: true, children: [
512
+ "by ",
513
+ creator
514
+ ] }),
515
+ latest?.url && latest.state === "READY" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
520
516
  import_ui3.Tooltip,
521
517
  {
522
518
  content: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Box, { padding: 2, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: copied ? "Copied!" : "Copy URL" }) }),
@@ -528,126 +524,162 @@ function DeployItem({ target, token, onDelete }) {
528
524
  icon: copied ? import_icons2.CheckmarkIcon : import_icons2.CopyIcon,
529
525
  padding: 1,
530
526
  tone: copied ? "positive" : "default",
531
- onClick: copyUrl
527
+ onClick: copyUrl,
528
+ style: { cursor: "pointer" }
532
529
  }
533
530
  )
534
531
  }
535
- )
532
+ ) })
533
+ ] }),
534
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, wrap: "wrap", children: [
535
+ commitMsg && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
536
+ import_ui3.Text,
537
+ {
538
+ size: 0,
539
+ muted: true,
540
+ style: { fontStyle: "italic" },
541
+ children: commitMsg
542
+ }
543
+ ),
544
+ isError && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
545
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
546
+ import_ui3.Button,
547
+ {
548
+ text: showErrorLogs ? "Hide error details" : "Show error details",
549
+ mode: "ghost",
550
+ tone: "critical",
551
+ icon: import_icons2.WarningOutlineIcon,
552
+ fontSize: 1,
553
+ padding: 2,
554
+ onClick: toggleErrorLogs,
555
+ style: { alignSelf: "flex-start", cursor: "pointer" }
556
+ }
557
+ ),
558
+ showErrorLogs && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Card, { tone: "critical", radius: 2, padding: 3, children: [
559
+ loadingLogs && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, children: [
560
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true }),
561
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: "Loading logs\u2026" })
562
+ ] }),
563
+ logError && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
564
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: logError }),
565
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
566
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.LaunchIcon, {}),
567
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: "View full logs in Vercel" })
568
+ ] }) })
569
+ ] }),
570
+ !loadingLogs && !logError && errorLines.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
571
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Box, { style: { maxHeight: 240, overflowY: "auto", fontFamily: "monospace", fontSize: 11, lineHeight: 1.6 }, children: errorLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Code, { size: 1, style: { display: "block", whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: line }, i)) }),
572
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
573
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.LaunchIcon, {}),
574
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: "View full logs in Vercel" })
575
+ ] }) })
576
+ ] })
577
+ ] })
578
+ ] }),
579
+ deployError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Card, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: deployError }) })
536
580
  ] })
537
- ] }),
538
- commitMsg && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
539
- import_ui3.Text,
581
+ ] })
582
+ ] }),
583
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Box, { children: [
584
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
585
+ import_ui3.Button,
540
586
  {
541
- size: 0,
542
- muted: true,
543
- style: {
544
- overflow: "hidden",
545
- textOverflow: "ellipsis",
546
- whiteSpace: "nowrap"
547
- },
548
- children: commitMsg
587
+ mode: "ghost",
588
+ iconRight: showDetails ? import_icons2.ChevronUpIcon : import_icons2.ChevronDownIcon,
589
+ text: "Details",
590
+ fontSize: 0,
591
+ padding: 3,
592
+ onClick: () => setShowDetails((v) => !v),
593
+ style: { width: "100%", justifyContent: "flex-start", borderRadius: 0, cursor: "pointer" }
549
594
  }
550
595
  ),
551
- isError && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
552
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
596
+ showDetails && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Card, { tone: "primary", padding: 3, style: { borderRadius: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
597
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
598
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Project" }),
599
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: projectId || "\u2014" })
600
+ ] }),
601
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
602
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Hook" }),
603
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: hookId || "\u2014" })
604
+ ] }),
605
+ target.teamId && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Team" }),
607
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: target.teamId })
608
+ ] }),
609
+ fullSha && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "flex-start", children: [
610
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Commit" }),
611
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: fullSha })
612
+ ] }),
613
+ latest?.meta?.githubCommitAuthorName && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
614
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Author" }),
615
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, children: latest.meta.githubCommitAuthorName })
616
+ ] }),
617
+ branch && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
618
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Branch" }),
619
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: branch })
620
+ ] }),
621
+ latest?.uid && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
622
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Deploy ID" }),
623
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: latest.uid })
624
+ ] }),
625
+ latest?.url && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "flex-start", children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "URL" }),
627
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: latest.url })
628
+ ] }),
629
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
630
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Inspector" }),
631
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: "Open in Vercel" }),
633
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.LaunchIcon, { style: { width: 10, height: 10 } })
634
+ ] }) })
635
+ ] }),
636
+ latest?.created && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { gap: 2, align: "center", children: [
637
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Created" }),
638
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 0, muted: true, children: new Date(latest.created).toLocaleString() })
639
+ ] })
640
+ ] }) })
641
+ ] })
642
+ ] }),
643
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
644
+ import_ui3.Flex,
645
+ {
646
+ direction: "column",
647
+ gap: 2,
648
+ className: "dvfs-deploy-col",
649
+ style: { flexShrink: 0, alignSelf: "stretch" },
650
+ children: [
651
+ isActiveState(latest?.state) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
553
652
  import_ui3.Button,
554
653
  {
555
- text: showErrorLogs ? "Hide error details" : "Show error details",
654
+ text: "Cancel",
556
655
  mode: "ghost",
557
656
  tone: "critical",
558
- icon: import_icons2.WarningOutlineIcon,
559
- fontSize: 1,
560
- padding: 2,
561
- onClick: toggleErrorLogs,
562
- style: { alignSelf: "flex-start" }
657
+ loading: canceling,
658
+ disabled: canceling,
659
+ onClick: cancel,
660
+ style: { cursor: "pointer" }
563
661
  }
564
662
  ),
565
- showErrorLogs && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Card, { tone: "critical", radius: 2, padding: 3, children: [
566
- loadingLogs && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 2, children: [
567
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Spinner, { muted: true }),
568
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, muted: true, children: "Loading logs\u2026" })
569
- ] }),
570
- logError && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
571
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: logError }),
572
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
573
- "a",
574
- {
575
- href: safeHref(latest?.inspectorUrl),
576
- target: "_blank",
577
- rel: "noreferrer",
578
- style: { color: "inherit" },
579
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
580
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.LaunchIcon, {}),
581
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: "View full logs in Vercel" })
582
- ] })
583
- }
584
- )
585
- ] }),
586
- !loadingLogs && !logError && errorLines.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, children: [
587
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
588
- import_ui3.Box,
589
- {
590
- style: {
591
- maxHeight: 240,
592
- overflowY: "auto",
593
- fontFamily: "monospace",
594
- fontSize: 11,
595
- lineHeight: 1.6
596
- },
597
- children: errorLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
598
- import_ui3.Code,
599
- {
600
- size: 1,
601
- style: { display: "block", whiteSpace: "pre-wrap", wordBreak: "break-all" },
602
- children: line
603
- },
604
- i
605
- ))
606
- }
607
- ),
608
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
609
- "a",
610
- {
611
- href: safeHref(latest?.inspectorUrl),
612
- target: "_blank",
613
- rel: "noreferrer",
614
- style: { color: "inherit" },
615
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, { align: "center", gap: 1, children: [
616
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.LaunchIcon, {}),
617
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: "View full logs in Vercel" })
618
- ] })
619
- }
620
- )
621
- ] })
622
- ] })
623
- ] }),
624
- deployError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Card, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { size: 1, children: deployError }) })
625
- ] })
626
- ] }),
627
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 2, style: { flexShrink: 0 }, children: [
628
- isActiveState(latest?.state) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
629
- import_ui3.Button,
630
- {
631
- text: "Cancel",
632
- mode: "ghost",
633
- tone: "critical",
634
- loading: canceling,
635
- disabled: canceling,
636
- onClick: cancel
637
- }
638
- ),
639
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
640
- import_ui3.Button,
641
- {
642
- text: "Deploy",
643
- tone: "primary",
644
- icon: import_icons2.RocketIcon,
645
- loading: triggering,
646
- disabled: isActive,
647
- onClick: deploy
648
- }
649
- )
650
- ] })
663
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
664
+ import_ui3.Button,
665
+ {
666
+ text: "Deploy",
667
+ tone: "primary",
668
+ loading: triggering,
669
+ disabled: isActive,
670
+ onClick: deploy,
671
+ style: {
672
+ flex: 1,
673
+ borderRadius: 0,
674
+ borderTopRightRadius: 3,
675
+ borderBottomRightRadius: 3,
676
+ cursor: "pointer"
677
+ }
678
+ }
679
+ )
680
+ ]
681
+ }
682
+ )
651
683
  ] }) }),
652
684
  showHistory && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
653
685
  DeployHistory,
@@ -667,7 +699,7 @@ var import_ui4 = require("@sanity/ui");
667
699
  var import_icons3 = require("@sanity/icons");
668
700
  var import_jsx_runtime4 = require("react/jsx-runtime");
669
701
  var TOKEN_DOC_ID = "config.vercelDeploy";
670
- function TokenSetup({ onSaved }) {
702
+ function TokenSetup({ onSaved, onCancel }) {
671
703
  const client = (0, import_sanity.useClient)({ apiVersion: "2025-01-01" });
672
704
  const [token, setToken] = (0, import_react3.useState)("");
673
705
  const [saving, setSaving] = (0, import_react3.useState)(false);
@@ -689,68 +721,206 @@ function TokenSetup({ onSaved }) {
689
721
  setSaving(false);
690
722
  }
691
723
  }, [client, token, onSaved]);
692
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Card, { height: "fill", tone: "transparent", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Flex, { align: "center", justify: "center", height: "fill", padding: 6, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Card, { padding: 5, radius: 3, shadow: 1, style: { maxWidth: 480, width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 5, children: [
693
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Flex, { align: "center", gap: 3, children: [
694
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { size: 3, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons3.TokenIcon, {}) }),
695
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Heading, { size: 2, children: "Connect to Vercel" })
696
- ] }),
697
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 3, children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Text, { size: 1, muted: true, children: [
699
- "A Vercel API token is required to read deployment status, history, and build logs. Your token is stored securely in the Sanity dataset under a",
700
- " ",
701
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { children: "secrets.*" }),
702
- " document ID that is not publicly readable."
724
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
725
+ import_ui4.Dialog,
726
+ {
727
+ header: "Connect Vercel API token",
728
+ id: "token-setup",
729
+ onClose: onCancel,
730
+ width: 1,
731
+ footer: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
732
+ onCancel && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Button, { text: "Cancel", mode: "ghost", onClick: onCancel, style: { cursor: "pointer" } }),
733
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
734
+ import_ui4.Button,
735
+ {
736
+ text: "Save and connect",
737
+ tone: "primary",
738
+ icon: import_icons3.CheckmarkCircleIcon,
739
+ loading: saving,
740
+ disabled: !token.trim() || saving,
741
+ onClick: save,
742
+ style: { cursor: "pointer" }
743
+ }
744
+ )
703
745
  ] }),
704
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Text, { size: 1, muted: true, children: [
705
- "Create a token at",
706
- " ",
707
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "vercel.com \u2192 Settings \u2192 Tokens" }),
708
- ". Choose ",
709
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Full Account" }),
710
- " scope."
746
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 4, padding: 4, children: [
747
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 3, children: [
748
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { size: 1, muted: true, children: "A Vercel API token lets this tool read deployment status, history, build logs, and branch metadata. Without it you can still trigger deploys \u2014 you just won't see any feedback." }),
749
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Text, { size: 1, muted: true, children: [
750
+ "Create one at ",
751
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "vercel.com \u2192 Settings \u2192 Tokens" }),
752
+ " with",
753
+ " ",
754
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Full Account" }),
755
+ " scope. The token is stored in your Sanity dataset and shared across all authenticated studio users."
756
+ ] })
757
+ ] }),
758
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 2, children: [
759
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { size: 1, weight: "semibold", children: "Vercel API Token" }),
760
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
761
+ import_ui4.TextInput,
762
+ {
763
+ value: token,
764
+ onChange: (e) => setToken(e.target.value),
765
+ placeholder: "xxxxxxxxxxxxxxxxxxxxxxxx",
766
+ type: "password"
767
+ }
768
+ )
769
+ ] }),
770
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Card, { tone: "critical", padding: 3, radius: 2, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { size: 1, children: error }) })
711
771
  ] })
712
- ] }),
713
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 3, children: [
714
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { size: 1, weight: "semibold", children: "Vercel API Token" }),
715
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
716
- import_ui4.TextInput,
717
- {
718
- value: token,
719
- onChange: (e) => setToken(e.target.value),
720
- placeholder: "xxxxxxxxxxxxxxxxxxxxxxxx",
721
- type: "password"
722
- }
723
- )
724
- ] }),
725
- error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Card, { tone: "critical", padding: 3, radius: 2, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { size: 1, children: error }) }),
726
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
727
- import_ui4.Button,
728
- {
729
- text: "Save and connect",
730
- tone: "primary",
731
- icon: import_icons3.CheckmarkCircleIcon,
732
- loading: saving,
733
- disabled: !token.trim() || saving,
734
- onClick: save
772
+ }
773
+ );
774
+ }
775
+
776
+ // src/components/DeployTargetForm.tsx
777
+ var import_react4 = require("react");
778
+ var import_sanity2 = require("sanity");
779
+ var import_ui5 = require("@sanity/ui");
780
+ var import_icons4 = require("@sanity/icons");
781
+ var import_jsx_runtime5 = require("react/jsx-runtime");
782
+ var VERCEL_HOOK_RE2 = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\//;
783
+ function DeployTargetForm({ initial, onSaved, onClose }) {
784
+ const client = (0, import_sanity2.useClient)({ apiVersion: "2025-01-01" });
785
+ const isEdit = Boolean(initial);
786
+ const [name, setName] = (0, import_react4.useState)(initial?.name ?? "");
787
+ const [url, setUrl] = (0, import_react4.useState)(initial?.url ?? "");
788
+ const [teamId, setTeamId] = (0, import_react4.useState)(initial?.teamId ?? "");
789
+ const [disableDelete, setDisableDelete] = (0, import_react4.useState)(initial?.disableDeleteAction ?? false);
790
+ const [saving, setSaving] = (0, import_react4.useState)(false);
791
+ const [error, setError] = (0, import_react4.useState)(null);
792
+ const urlValid = !url || VERCEL_HOOK_RE2.test(url.trim());
793
+ const canSave = name.trim() && url.trim() && urlValid;
794
+ const save = (0, import_react4.useCallback)(async () => {
795
+ if (!canSave) return;
796
+ setSaving(true);
797
+ setError(null);
798
+ const fields = {
799
+ name: name.trim(),
800
+ url: url.trim(),
801
+ ...teamId.trim() ? { teamId: teamId.trim() } : { teamId: null },
802
+ disableDeleteAction: disableDelete
803
+ };
804
+ try {
805
+ if (isEdit && initial) {
806
+ await client.patch(initial._id).set(fields).commit();
807
+ } else {
808
+ await client.create({ _type: "vercel_deploy", ...fields });
735
809
  }
736
- )
737
- ] }) }) }) });
810
+ onSaved();
811
+ } catch (err) {
812
+ setError(err instanceof Error ? err.message : "Save failed");
813
+ } finally {
814
+ setSaving(false);
815
+ }
816
+ }, [canSave, isEdit, initial, client, name, url, teamId, disableDelete, onSaved]);
817
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
818
+ import_ui5.Dialog,
819
+ {
820
+ header: isEdit ? `Edit "${initial?.name}"` : "Add deploy target",
821
+ id: "deploy-target-form",
822
+ onClose,
823
+ width: 1,
824
+ footer: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
825
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Button, { text: "Cancel", mode: "ghost", onClick: onClose, style: { cursor: "pointer" } }),
826
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
827
+ import_ui5.Button,
828
+ {
829
+ text: isEdit ? "Save changes" : "Add target",
830
+ tone: "primary",
831
+ icon: import_icons4.CheckmarkCircleIcon,
832
+ loading: saving,
833
+ disabled: !canSave || saving,
834
+ onClick: save,
835
+ style: { cursor: "pointer" }
836
+ }
837
+ )
838
+ ] }),
839
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Box, { padding: 4, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 4, children: [
840
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 2, children: [
841
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Label, { size: 1, children: [
842
+ "Name ",
843
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "var(--card-fg-color)" }, children: "*" })
844
+ ] }),
845
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
846
+ import_ui5.TextInput,
847
+ {
848
+ value: name,
849
+ onChange: (e) => setName(e.target.value),
850
+ placeholder: "Production"
851
+ }
852
+ )
853
+ ] }),
854
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 2, children: [
855
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Label, { size: 1, children: [
856
+ "Deploy hook URL ",
857
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "var(--card-fg-color)" }, children: "*" })
858
+ ] }),
859
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
860
+ import_ui5.TextInput,
861
+ {
862
+ value: url,
863
+ onChange: (e) => setUrl(e.target.value),
864
+ placeholder: "https://api.vercel.com/v1/integrations/deploy/\u2026"
865
+ }
866
+ ),
867
+ url && !urlValid && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 1, style: { color: "var(--card-critical-fg-color, red)" }, children: "Must be a Vercel deploy hook URL (api.vercel.com/v1/integrations/deploy/\u2026)" }),
868
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 0, muted: true, children: "Vercel dashboard \u2192 Project \u2192 Settings \u2192 Git \u2192 Deploy Hooks" })
869
+ ] }),
870
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 2, children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Label, { size: 1, children: [
872
+ "Team ID ",
873
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { opacity: 0.5, fontWeight: "normal" }, children: "\u2014 optional" })
874
+ ] }),
875
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
876
+ import_ui5.TextInput,
877
+ {
878
+ value: teamId,
879
+ onChange: (e) => setTeamId(e.target.value),
880
+ placeholder: "team_xxxxxxxx"
881
+ }
882
+ ),
883
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 0, muted: true, children: "Required for team-owned Vercel projects." })
884
+ ] }),
885
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { align: "center", gap: 3, children: [
886
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
887
+ import_ui5.Switch,
888
+ {
889
+ checked: disableDelete,
890
+ onChange: (e) => setDisableDelete(e.target.checked),
891
+ id: "disable-delete"
892
+ }
893
+ ),
894
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 1, children: [
895
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Label, { size: 1, htmlFor: "disable-delete", children: "Disable delete action" }),
896
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 0, muted: true, children: "Hides the delete button for this target in the studio." })
897
+ ] })
898
+ ] }),
899
+ error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Card, { tone: "critical", padding: 3, radius: 2, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 1, children: error }) })
900
+ ] }) })
901
+ }
902
+ );
738
903
  }
739
904
 
905
+ // src/version.ts
906
+ var VERSION = "0.2.0";
907
+
740
908
  // src/components/DeployTool.tsx
741
- var import_jsx_runtime5 = require("react/jsx-runtime");
909
+ var import_jsx_runtime6 = require("react/jsx-runtime");
742
910
  var TOKEN_QUERY = `*[_id == "config.vercelDeploy"][0].accessToken`;
743
911
  var TARGETS_QUERY = `*[_type == "vercel_deploy"] | order(_createdAt asc)`;
744
912
  function DeployTool() {
745
- const client = (0, import_sanity2.useClient)({ apiVersion: "2025-01-01" });
746
- const toast = (0, import_ui5.useToast)();
747
- const [token, setToken] = (0, import_react4.useState)(null);
748
- const [targets, setTargets] = (0, import_react4.useState)([]);
749
- const [loading, setLoading] = (0, import_react4.useState)(true);
750
- const [showTokenSetup, setShowTokenSetup] = (0, import_react4.useState)(false);
751
- const [pendingDelete, setPendingDelete] = (0, import_react4.useState)(null);
752
- const [deleting, setDeleting] = (0, import_react4.useState)(false);
753
- const load = (0, import_react4.useCallback)(async () => {
913
+ const client = (0, import_sanity3.useClient)({ apiVersion: "2025-01-01" });
914
+ const toast = (0, import_ui6.useToast)();
915
+ const [token, setToken] = (0, import_react5.useState)(null);
916
+ const [targets, setTargets] = (0, import_react5.useState)([]);
917
+ const [loading, setLoading] = (0, import_react5.useState)(true);
918
+ const [showTokenSetup, setShowTokenSetup] = (0, import_react5.useState)(false);
919
+ const [showCreateForm, setShowCreateForm] = (0, import_react5.useState)(false);
920
+ const [pendingEdit, setPendingEdit] = (0, import_react5.useState)(null);
921
+ const [pendingDelete, setPendingDelete] = (0, import_react5.useState)(null);
922
+ const [deleting, setDeleting] = (0, import_react5.useState)(false);
923
+ const load = (0, import_react5.useCallback)(async () => {
754
924
  setLoading(true);
755
925
  try {
756
926
  const [fetchedToken, fetchedTargets] = await Promise.all([
@@ -765,10 +935,29 @@ function DeployTool() {
765
935
  setLoading(false);
766
936
  }
767
937
  }, [client]);
768
- (0, import_react4.useEffect)(() => {
938
+ (0, import_react5.useEffect)(() => {
769
939
  load();
770
940
  }, [load]);
771
- (0, import_react4.useEffect)(() => {
941
+ (0, import_react5.useEffect)(() => {
942
+ if (document.getElementById("dvfs-styles")) return;
943
+ const style = document.createElement("style");
944
+ style.id = "dvfs-styles";
945
+ style.textContent = `
946
+ @media (max-width: 600px) {
947
+ .dvfs-header { flex-wrap: wrap !important; row-gap: 8px !important; }
948
+ .dvfs-header-actions { width: 100% !important; flex-wrap: wrap !important; justify-content: flex-start !important; }
949
+ .dvfs-grid { grid-template-columns: 1fr !important; }
950
+ .dvfs-card-flex { flex-direction: column !important; }
951
+ .dvfs-deploy-col { width: 100% !important; align-self: auto !important; }
952
+ .dvfs-deploy-col button { border-radius: 3px !important; }
953
+ }
954
+ `;
955
+ document.head.appendChild(style);
956
+ return () => {
957
+ document.getElementById("dvfs-styles")?.remove();
958
+ };
959
+ }, []);
960
+ (0, import_react5.useEffect)(() => {
772
961
  const sub = client.listen(TARGETS_QUERY).subscribe(() => {
773
962
  client.fetch(TARGETS_QUERY).then(setTargets).catch((err) => {
774
963
  console.error("deploy-vercel-from-sanity: subscription refresh error", err);
@@ -776,7 +965,7 @@ function DeployTool() {
776
965
  });
777
966
  return () => sub.unsubscribe();
778
967
  }, [client]);
779
- const confirmDelete = (0, import_react4.useCallback)(async () => {
968
+ const confirmDelete = (0, import_react5.useCallback)(async () => {
780
969
  if (!pendingDelete) return;
781
970
  setDeleting(true);
782
971
  try {
@@ -791,96 +980,173 @@ function DeployTool() {
791
980
  }
792
981
  }, [client, pendingDelete, toast]);
793
982
  if (loading) {
794
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Card, { height: "fill", tone: "transparent", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Flex, { align: "center", justify: "center", height: "fill", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Spinner, { muted: true }) }) });
795
- }
796
- if (!token || showTokenSetup) {
797
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
798
- TokenSetup,
799
- {
800
- onSaved: () => {
801
- setShowTokenSetup(false);
802
- load();
803
- }
804
- }
805
- );
983
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Card, { height: "fill", tone: "transparent", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Flex, { align: "center", justify: "center", height: "fill", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Spinner, { muted: true }) }) });
806
984
  }
807
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Card, { height: "fill", tone: "transparent", children: [
808
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Box, { padding: 5, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 5, children: [
809
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { align: "center", justify: "space-between", children: [
810
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { align: "center", gap: 3, children: [
811
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.RocketIcon, {}),
812
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Heading, { size: 2, children: "Deploy" })
813
- ] }),
814
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { align: "center", gap: 3, children: [
815
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Badge, { tone: "positive", mode: "outline", children: "Connected" }),
816
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
817
- import_ui5.Button,
985
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Card, { height: "fill", tone: "transparent", children: [
986
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Box, { padding: 5, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Stack, { space: 5, children: [
987
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Flex, { align: "center", justify: "space-between", className: "dvfs-header", children: [
988
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Heading, { size: 2, children: "Deploy with Vercel" }),
989
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Flex, { align: "center", gap: 3, className: "dvfs-header-actions", children: [
990
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
991
+ import_ui6.Button,
992
+ {
993
+ text: token ? "Token connected" : "Connect API token",
994
+ mode: "ghost",
995
+ icon: import_icons5.TokenIcon,
996
+ fontSize: 1,
997
+ tone: token ? "positive" : "caution",
998
+ onClick: () => setShowTokenSetup(true),
999
+ style: { cursor: "pointer" }
1000
+ }
1001
+ ),
1002
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1003
+ import_ui6.Button,
818
1004
  {
819
- text: "Change Token",
1005
+ text: "Add target",
820
1006
  mode: "ghost",
821
- icon: import_icons4.TokenIcon,
1007
+ icon: import_icons5.AddIcon,
822
1008
  fontSize: 1,
823
- onClick: () => setShowTokenSetup(true)
1009
+ onClick: () => setShowCreateForm(true),
1010
+ style: { cursor: "pointer" }
824
1011
  }
825
1012
  )
826
1013
  ] })
827
1014
  ] }),
828
- targets.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Card, { padding: 5, radius: 2, tone: "transparent", shadow: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 3, style: { textAlign: "center" }, children: [
829
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 2, weight: "semibold", children: "No deploy targets configured" }),
830
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Text, { size: 1, muted: true, children: [
831
- "Create a ",
832
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "vercel_deploy" }),
833
- " document in the dataset with a Vercel deploy hook URL."
834
- ] })
1015
+ !token && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Card, { padding: 4, radius: 2, tone: "caution", shadow: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Flex, { align: "center", justify: "space-between", gap: 4, children: [
1016
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Stack, { space: 2, children: [
1017
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Text, { size: 1, weight: "semibold", children: "Deploy status is not connected" }),
1018
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Text, { size: 1, muted: true, children: "You can trigger deploys now. Connect a Vercel API token to also see deployment status, build logs, history, and commit metadata." })
1019
+ ] }),
1020
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1021
+ import_ui6.Button,
1022
+ {
1023
+ text: "Connect",
1024
+ tone: "caution",
1025
+ fontSize: 1,
1026
+ onClick: () => setShowTokenSetup(true),
1027
+ style: { cursor: "pointer", flexShrink: 0 }
1028
+ }
1029
+ )
1030
+ ] }) }),
1031
+ targets.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Card, { padding: 5, radius: 2, tone: "transparent", shadow: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Stack, { space: 4, style: { textAlign: "center" }, children: [
1032
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Text, { size: 2, weight: "semibold", children: "No deploy targets configured" }),
1033
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Text, { size: 1, muted: true, children: [
1034
+ "Add a deploy target using the button above, or create a",
1035
+ " ",
1036
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "vercel_deploy" }),
1037
+ " document directly in the dataset."
1038
+ ] }),
1039
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Flex, { justify: "center", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1040
+ import_ui6.Button,
1041
+ {
1042
+ text: "Add deploy target",
1043
+ tone: "primary",
1044
+ icon: import_icons5.AddIcon,
1045
+ onClick: () => setShowCreateForm(true),
1046
+ style: { cursor: "pointer" }
1047
+ }
1048
+ ) })
835
1049
  ] }) }),
836
- targets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1050
+ targets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dvfs-grid", style: {
837
1051
  display: "grid",
838
- gridTemplateColumns: "repeat(auto-fill, minmax(380px, 1fr))",
839
- gap: "12px"
840
- }, children: targets.map((target) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1052
+ gridTemplateColumns: "repeat(auto-fill, minmax(540px, 1fr))",
1053
+ gap: "16px",
1054
+ alignItems: "start"
1055
+ }, children: targets.map((target) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
841
1056
  DeployItem,
842
1057
  {
843
1058
  target,
844
- token,
845
- onDelete: setPendingDelete
1059
+ token: token ?? "",
1060
+ onDelete: setPendingDelete,
1061
+ onEdit: setPendingEdit
846
1062
  },
847
1063
  target._id
848
1064
  )) })
849
1065
  ] }) }),
850
- pendingDelete && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
851
- import_ui5.Dialog,
1066
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1067
+ import_ui6.Box,
1068
+ {
1069
+ style: {
1070
+ position: "fixed",
1071
+ bottom: 12,
1072
+ right: 16,
1073
+ opacity: 0.25,
1074
+ pointerEvents: "none",
1075
+ userSelect: "none"
1076
+ },
1077
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Text, { size: 0, muted: true, children: [
1078
+ "v",
1079
+ VERSION
1080
+ ] })
1081
+ }
1082
+ ),
1083
+ showTokenSetup && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1084
+ TokenSetup,
1085
+ {
1086
+ onSaved: () => {
1087
+ setShowTokenSetup(false);
1088
+ load();
1089
+ },
1090
+ onCancel: token ? () => setShowTokenSetup(false) : void 0
1091
+ }
1092
+ ),
1093
+ showCreateForm && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1094
+ DeployTargetForm,
1095
+ {
1096
+ onSaved: () => {
1097
+ setShowCreateForm(false);
1098
+ toast.push({ status: "success", title: "Deploy target added" });
1099
+ },
1100
+ onClose: () => setShowCreateForm(false)
1101
+ }
1102
+ ),
1103
+ pendingEdit && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1104
+ DeployTargetForm,
1105
+ {
1106
+ initial: pendingEdit,
1107
+ onSaved: () => {
1108
+ setPendingEdit(null);
1109
+ toast.push({ status: "success", title: "Deploy target updated" });
1110
+ },
1111
+ onClose: () => setPendingEdit(null)
1112
+ }
1113
+ ),
1114
+ pendingDelete && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1115
+ import_ui6.Dialog,
852
1116
  {
853
1117
  header: "Delete deploy target?",
854
1118
  id: "confirm-delete",
855
1119
  onClose: () => setPendingDelete(null),
856
1120
  width: 1,
857
- footer: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
858
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
859
- import_ui5.Button,
1121
+ footer: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
1122
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1123
+ import_ui6.Button,
860
1124
  {
861
1125
  text: "Cancel",
862
1126
  mode: "ghost",
863
- onClick: () => setPendingDelete(null)
1127
+ onClick: () => setPendingDelete(null),
1128
+ style: { cursor: "pointer" }
864
1129
  }
865
1130
  ),
866
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
867
- import_ui5.Button,
1131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1132
+ import_ui6.Button,
868
1133
  {
869
1134
  text: "Delete",
870
1135
  tone: "critical",
871
- icon: import_icons4.TrashIcon,
1136
+ icon: import_icons5.TrashIcon,
872
1137
  loading: deleting,
873
1138
  disabled: deleting,
874
- onClick: confirmDelete
1139
+ onClick: confirmDelete,
1140
+ style: { cursor: "pointer" }
875
1141
  }
876
1142
  )
877
1143
  ] }),
878
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Box, { padding: 4, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 3, children: [
879
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Flex, { align: "center", gap: 2, children: [
880
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons4.WarningOutlineIcon, {}),
881
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 2, weight: "semibold", children: pendingDelete.name })
1144
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Box, { padding: 4, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Stack, { space: 3, children: [
1145
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Flex, { align: "center", gap: 2, children: [
1146
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons5.WarningOutlineIcon, {}),
1147
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Text, { size: 2, weight: "semibold", children: pendingDelete.name })
882
1148
  ] }),
883
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { size: 1, muted: true, children: "This removes the deploy target from the dataset. The Vercel deploy hook itself is not affected." })
1149
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Text, { size: 1, muted: true, children: "This removes the deploy target from the dataset. The Vercel deploy hook itself is not affected." })
884
1150
  ] }) })
885
1151
  }
886
1152
  )
@@ -888,22 +1154,22 @@ function DeployTool() {
888
1154
  }
889
1155
 
890
1156
  // src/schema/vercelDeploy.ts
891
- var import_sanity3 = require("sanity");
892
- var import_icons5 = require("@sanity/icons");
893
- var vercelDeploySchema = (0, import_sanity3.defineType)({
1157
+ var import_sanity4 = require("sanity");
1158
+ var import_icons6 = require("@sanity/icons");
1159
+ var vercelDeploySchema = (0, import_sanity4.defineType)({
894
1160
  name: "vercel_deploy",
895
1161
  title: "Deploy Target",
896
1162
  type: "document",
897
- icon: import_icons5.RocketIcon,
1163
+ icon: import_icons6.RocketIcon,
898
1164
  fields: [
899
- (0, import_sanity3.defineField)({
1165
+ (0, import_sanity4.defineField)({
900
1166
  name: "name",
901
1167
  title: "Name",
902
1168
  type: "string",
903
1169
  description: 'Display label shown in the Deploy tool (e.g. "Production", "Staging")',
904
1170
  validation: (Rule) => Rule.required()
905
1171
  }),
906
- (0, import_sanity3.defineField)({
1172
+ (0, import_sanity4.defineField)({
907
1173
  name: "url",
908
1174
  title: "Deploy Hook URL",
909
1175
  type: "url",
@@ -916,13 +1182,13 @@ var vercelDeploySchema = (0, import_sanity3.defineType)({
916
1182
  return true;
917
1183
  })
918
1184
  }),
919
- (0, import_sanity3.defineField)({
1185
+ (0, import_sanity4.defineField)({
920
1186
  name: "teamId",
921
1187
  title: "Vercel Team ID",
922
1188
  type: "string",
923
1189
  description: "Required for team-owned projects \u2014 find it in Vercel Team Settings"
924
1190
  }),
925
- (0, import_sanity3.defineField)({
1191
+ (0, import_sanity4.defineField)({
926
1192
  name: "disableDeleteAction",
927
1193
  title: "Prevent deletion",
928
1194
  type: "boolean",
@@ -936,7 +1202,7 @@ var vercelDeploySchema = (0, import_sanity3.defineType)({
936
1202
  });
937
1203
 
938
1204
  // src/index.ts
939
- var vercelDeploy = (0, import_sanity4.definePlugin)((options) => {
1205
+ var vercelDeploy = (0, import_sanity5.definePlugin)((options) => {
940
1206
  const config = options ?? {};
941
1207
  return {
942
1208
  name: "deploy-vercel-from-sanity",
@@ -947,7 +1213,7 @@ var vercelDeploy = (0, import_sanity4.definePlugin)((options) => {
947
1213
  {
948
1214
  name: config.name ?? "vercel-deploy",
949
1215
  title: config.title ?? "Deploy",
950
- icon: config.icon ?? import_icons6.RocketIcon,
1216
+ icon: config.icon ?? import_icons7.RocketIcon,
951
1217
  component: DeployTool
952
1218
  }
953
1219
  ]