@liiift-studio/deploy-vercel-from-sanity 1.1.1 → 1.2.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.
package/dist/index.mjs CHANGED
@@ -3,18 +3,39 @@ import { definePlugin } from "sanity";
3
3
 
4
4
  // src/icons.tsx
5
5
  import { forwardRef } from "react";
6
+
7
+ // src/compat/resolve.ts
8
+ import * as sanityUi from "@sanity/ui";
6
9
  import * as sanityIcons from "@sanity/icons";
10
+ var UI = sanityUi;
11
+ var ICONS = sanityIcons;
12
+ function resolveComponent(ns, name) {
13
+ const value = ns[name];
14
+ return typeof value === "function" || typeof value === "object" && value !== null ? value : void 0;
15
+ }
16
+ function resolveFunction(ns, name) {
17
+ const value = ns[name];
18
+ return typeof value === "function" ? value : void 0;
19
+ }
20
+ function resolveRecord(ns, name) {
21
+ const value = ns[name];
22
+ return typeof value === "object" && value !== null ? value : void 0;
23
+ }
24
+ var STACK_USES_GAP = typeof UI.Stack === "function";
25
+
26
+ // src/icons.tsx
7
27
  import { jsx } from "react/jsx-runtime";
8
- var INSTALLED = sanityIcons;
9
28
  var GLYPH = { width: "1em", height: "1em", viewBox: "0 0 25 25", fill: "none" };
10
29
  var MissingIcon = forwardRef(function MissingIcon2(props, ref) {
11
- return /* @__PURE__ */ jsx("svg", { ...GLYPH, xmlns: "http://www.w3.org/2000/svg", ...props, ref });
30
+ return /* @__PURE__ */ jsx("svg", { ...GLYPH, xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", ...props, ref });
12
31
  });
32
+ var SYMBOL_MAP = resolveRecord(ICONS, "icons");
13
33
  function resolveIcon(name, symbol) {
14
- const named = INSTALLED[name];
34
+ const named = resolveComponent(ICONS, name);
15
35
  if (named) return named;
16
- const Icon = INSTALLED.Icon;
36
+ const Icon = resolveComponent(ICONS, "Icon");
17
37
  if (!Icon) return MissingIcon;
38
+ if (SYMBOL_MAP && !(symbol in SYMBOL_MAP)) return MissingIcon;
18
39
  const Resolved = forwardRef(function SanityIcon(props, ref) {
19
40
  return /* @__PURE__ */ jsx(Icon, { symbol, ...props, ref });
20
41
  });
@@ -33,60 +54,131 @@ var EditIcon = resolveIcon("EditIcon", "edit");
33
54
  var EllipsisVerticalIcon = resolveIcon("EllipsisVerticalIcon", "ellipsis-vertical");
34
55
  var LaunchIcon = resolveIcon("LaunchIcon", "launch");
35
56
  var RocketIcon = resolveIcon("RocketIcon", "rocket");
36
- var SchemaIcon = resolveIcon("SchemaIcon", "schema");
37
57
  var TokenIcon = resolveIcon("TokenIcon", "token");
38
58
  var TrashIcon = resolveIcon("TrashIcon", "trash");
39
59
  var WarningOutlineIcon = resolveIcon("WarningOutlineIcon", "warning-outline");
40
60
 
41
61
  // src/components/DeployTool.tsx
42
- import { useState as useState6, useEffect as useEffect4, useCallback as useCallback6 } from "react";
62
+ import { useState as useState8, useEffect as useEffect5, useCallback as useCallback7 } from "react";
43
63
  import { useClient as useClient3 } from "sanity";
44
- import {
45
- Card as Card6,
46
- Box as Box5,
47
- Flex as Flex7,
48
- Text as Text6,
49
- Heading,
50
- Spinner as Spinner4,
51
- Button as Button6,
52
- Dialog as Dialog4
53
- } from "@sanity/ui";
54
64
 
55
- // src/ui.tsx
56
- import { useCallback, useEffect, useRef, useState } from "react";
57
- import * as sanityUi from "@sanity/ui";
58
- import { Box, Button, Card, Flex, Stack as SanityStack, Text } from "@sanity/ui";
59
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
60
- var INSTALLED2 = sanityUi;
61
- var IS_UI_V4_PLUS = !("useToast" in INSTALLED2);
65
+ // src/components/DeployItem.tsx
66
+ import { useState as useState5, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef2 } from "react";
67
+ import { flushSync } from "react-dom";
68
+
69
+ // src/compat/primitives.tsx
70
+ import { createElement, forwardRef as forwardRef2 } from "react";
71
+ import { jsx as jsx2 } from "react/jsx-runtime";
72
+ function domFallback(tag) {
73
+ const Fallback = forwardRef2(function SanityUiFallback(props, ref) {
74
+ const { children, style, id, className, onClick, href, title, as, ...rest } = props;
75
+ const element = typeof as === "string" ? as : tag;
76
+ const passthrough = { style, id, className, onClick, href, title, ref };
77
+ for (const key of [
78
+ "role",
79
+ "type",
80
+ "value",
81
+ "checked",
82
+ "placeholder",
83
+ "disabled",
84
+ "tabIndex",
85
+ "onChange",
86
+ "onKeyDown",
87
+ "onFocus",
88
+ "onBlur",
89
+ "onMouseEnter",
90
+ "onMouseLeave",
91
+ "htmlFor",
92
+ "target",
93
+ "rel",
94
+ "name",
95
+ "autoComplete",
96
+ "required",
97
+ "readOnly"
98
+ ]) {
99
+ if (key in rest) passthrough[key] = rest[key];
100
+ }
101
+ for (const key of Object.keys(rest)) {
102
+ if (key.startsWith("aria-") || key.startsWith("data-")) passthrough[key] = rest[key];
103
+ }
104
+ return createElement(element, passthrough, children);
105
+ });
106
+ Fallback.displayName = `SanityUiFallback(${tag})`;
107
+ return Fallback;
108
+ }
109
+ function primitive(name, tag) {
110
+ return resolveComponent(UI, name) ?? domFallback(tag);
111
+ }
112
+ var Box = primitive("Box", "div");
113
+ var Card = primitive("Card", "div");
114
+ var Flex = primitive("Flex", "div");
115
+ var Grid = primitive("Grid", "div");
116
+ var Text = primitive("Text", "span");
117
+ var Heading = primitive("Heading", "h2");
118
+ var Label = primitive("Label", "label");
119
+ var Badge = primitive("Badge", "span");
120
+ var Spinner = primitive("Spinner", "span");
121
+ var Button = primitive("Button", "button");
122
+ var TextInput = primitive("TextInput", "input");
123
+ var Select = primitive("Select", "select");
124
+ var Switch = primitive("Switch", "input");
125
+ var Dialog = primitive("Dialog", "div");
126
+ var SanityStack = primitive("Stack", "div");
62
127
  function Stack({ space, children, ...rest }) {
63
- const spacing = space === void 0 ? {} : IS_UI_V4_PLUS ? { gap: space } : { space };
64
- const Component = SanityStack;
65
- return /* @__PURE__ */ jsx2(Component, { ...rest, ...spacing, children });
128
+ const spacing = space === void 0 ? {} : STACK_USES_GAP ? { gap: space } : { space };
129
+ return /* @__PURE__ */ jsx2(SanityStack, { ...rest, ...spacing, children });
66
130
  }
67
- var LOCAL_TOAST_MS = 5e3;
131
+
132
+ // src/compat/toast.tsx
133
+ import { useCallback, useEffect, useState } from "react";
134
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
135
+ var LOCAL_TOAST_MS = 6e3;
136
+ var MAX_VISIBLE_TOASTS = 4;
137
+ var TOAST_Z_INDEX = 1e6;
68
138
  var LOCAL_TOAST_TONE = {
69
139
  success: "positive",
70
140
  error: "critical",
71
141
  warning: "caution",
72
142
  info: "primary"
73
143
  };
144
+ var PERSISTENT_STATUSES = /* @__PURE__ */ new Set(["error", "warning"]);
74
145
  var nextToastId = 0;
75
146
  var localToasts = [];
76
147
  var toastListeners = /* @__PURE__ */ new Set();
148
+ var dismissTimers = /* @__PURE__ */ new Map();
77
149
  function emitToasts() {
78
150
  for (const listener of toastListeners) listener(localToasts);
79
151
  }
152
+ function removeLocalToast(id) {
153
+ const timer = dismissTimers.get(id);
154
+ if (timer) {
155
+ clearTimeout(timer);
156
+ dismissTimers.delete(id);
157
+ }
158
+ localToasts = localToasts.filter((t) => t.id !== id);
159
+ emitToasts();
160
+ }
161
+ function scheduleDismiss(id, status) {
162
+ if (PERSISTENT_STATUSES.has(status ?? "info")) return;
163
+ const existing = dismissTimers.get(id);
164
+ if (existing) clearTimeout(existing);
165
+ dismissTimers.set(id, setTimeout(() => removeLocalToast(id), LOCAL_TOAST_MS));
166
+ }
80
167
  function pushLocalToast(params) {
81
168
  const toast = { ...params, id: nextToastId++ };
82
- localToasts = [...localToasts, toast];
169
+ const next = [...localToasts, toast];
170
+ for (const dropped of next.slice(0, Math.max(0, next.length - MAX_VISIBLE_TOASTS))) {
171
+ const timer = dismissTimers.get(dropped.id);
172
+ if (timer) {
173
+ clearTimeout(timer);
174
+ dismissTimers.delete(dropped.id);
175
+ }
176
+ }
177
+ localToasts = next.slice(-MAX_VISIBLE_TOASTS);
83
178
  emitToasts();
84
- setTimeout(() => {
85
- localToasts = localToasts.filter((t) => t.id !== toast.id);
86
- emitToasts();
87
- }, LOCAL_TOAST_MS);
179
+ scheduleDismiss(toast.id, toast.status);
88
180
  }
89
- var installedUseToast = INSTALLED2.useToast;
181
+ var installedUseToast = resolveFunction(UI, "useToast");
90
182
  var localToaster = { push: pushLocalToast };
91
183
  function useToast() {
92
184
  const real = installedUseToast;
@@ -98,164 +190,346 @@ function ToastViewport() {
98
190
  useEffect(() => {
99
191
  if (installedUseToast) return;
100
192
  toastListeners.add(setToasts);
193
+ setToasts(localToasts);
101
194
  return () => {
102
195
  toastListeners.delete(setToasts);
103
196
  };
104
197
  }, []);
105
- if (installedUseToast || toasts.length === 0) return null;
106
- return /* @__PURE__ */ jsx2(Box, { style: { position: "fixed", bottom: 16, right: 16, zIndex: 1e6, maxWidth: 360 }, children: /* @__PURE__ */ jsx2(Stack, { space: 2, children: toasts.map((toast) => /* @__PURE__ */ jsx2(
107
- Card,
198
+ const resume = useCallback((toast, el) => {
199
+ if (el && el.contains(document.activeElement)) return;
200
+ scheduleDismiss(toast.id, toast.status);
201
+ }, []);
202
+ const hold = useCallback((id) => {
203
+ const timer = dismissTimers.get(id);
204
+ if (timer) {
205
+ clearTimeout(timer);
206
+ dismissTimers.delete(id);
207
+ }
208
+ }, []);
209
+ if (installedUseToast) return null;
210
+ return /* @__PURE__ */ jsx3(
211
+ Box,
108
212
  {
109
- padding: 3,
110
- radius: 2,
111
- shadow: 3,
112
- tone: LOCAL_TOAST_TONE[toast.status ?? "info"] ?? "primary",
113
- children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
114
- toast.title && /* @__PURE__ */ jsx2(Text, { size: 1, weight: "semibold", children: toast.title }),
115
- toast.description && /* @__PURE__ */ jsx2(Text, { size: 1, muted: true, children: toast.description })
116
- ] })
117
- },
118
- toast.id
119
- )) }) });
213
+ role: "log",
214
+ "aria-label": "Deployment notifications",
215
+ style: {
216
+ position: "fixed",
217
+ bottom: 16,
218
+ right: 16,
219
+ zIndex: TOAST_Z_INDEX,
220
+ width: "min(360px, calc(100vw - 32px))",
221
+ pointerEvents: "none"
222
+ },
223
+ children: /* @__PURE__ */ jsx3(Stack, { space: 2, children: toasts.map((toast) => /* @__PURE__ */ jsx3(
224
+ Card,
225
+ {
226
+ padding: 3,
227
+ radius: 2,
228
+ shadow: 3,
229
+ tone: LOCAL_TOAST_TONE[toast.status ?? "info"],
230
+ style: { pointerEvents: "auto" },
231
+ onMouseEnter: () => hold(toast.id),
232
+ onFocusCapture: () => hold(toast.id),
233
+ onMouseLeave: (e) => resume(toast, e.currentTarget),
234
+ onBlurCapture: (e) => resume(toast, e.currentTarget),
235
+ children: /* @__PURE__ */ jsxs(Flex, { align: "flex-start", gap: 3, children: [
236
+ /* @__PURE__ */ jsxs(Stack, { space: 2, flex: 1, children: [
237
+ toast.title && /* @__PURE__ */ jsx3(Text, { size: 1, weight: "semibold", children: toast.title }),
238
+ toast.description && /* @__PURE__ */ jsx3(Text, { size: 1, muted: true, children: toast.description })
239
+ ] }),
240
+ /* @__PURE__ */ jsx3(
241
+ Button,
242
+ {
243
+ mode: "bleed",
244
+ padding: 2,
245
+ icon: CloseIcon,
246
+ text: "",
247
+ "aria-label": "Dismiss notification",
248
+ onClick: () => removeLocalToast(toast.id)
249
+ }
250
+ )
251
+ ] })
252
+ },
253
+ toast.id
254
+ )) })
255
+ }
256
+ );
120
257
  }
121
- var InstalledTooltip = INSTALLED2.Tooltip;
258
+
259
+ // src/compat/tooltip.tsx
260
+ import { cloneElement, isValidElement, useId, useState as useState2 } from "react";
261
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
262
+ var InstalledTooltip = resolveComponent(UI, "Tooltip");
122
263
  function Tooltip({ text, children }) {
264
+ const id = useId();
265
+ const [visible, setVisible] = useState2(false);
123
266
  if (InstalledTooltip) {
124
- return /* @__PURE__ */ jsx2(InstalledTooltip, { content: /* @__PURE__ */ jsx2(Box, { padding: 2, children: /* @__PURE__ */ jsx2(Text, { size: 1, children: text }) }), portal: true, children });
267
+ return /* @__PURE__ */ jsx4(InstalledTooltip, { content: /* @__PURE__ */ jsx4(Box, { padding: 2, children: /* @__PURE__ */ jsx4(Text, { size: 1, children: text }) }), portal: true, children });
125
268
  }
126
- return /* @__PURE__ */ jsx2("span", { title: text, style: { display: "inline-flex" }, children });
269
+ const described = visible && isValidElement(children) ? cloneElement(children, { "aria-describedby": id }) : children;
270
+ return /* @__PURE__ */ jsxs2(
271
+ "span",
272
+ {
273
+ style: { position: "relative", display: "inline-flex" },
274
+ onMouseEnter: () => setVisible(true),
275
+ onMouseLeave: () => setVisible(false),
276
+ onFocusCapture: () => setVisible(true),
277
+ onBlurCapture: () => setVisible(false),
278
+ onKeyDown: (e) => {
279
+ if (e.key === "Escape" && visible) {
280
+ e.stopPropagation();
281
+ setVisible(false);
282
+ }
283
+ },
284
+ children: [
285
+ described,
286
+ visible && /* @__PURE__ */ jsx4(
287
+ "span",
288
+ {
289
+ id,
290
+ role: "tooltip",
291
+ style: {
292
+ position: "absolute",
293
+ bottom: "100%",
294
+ left: "50%",
295
+ transform: "translateX(-50%)",
296
+ // No gap between trigger and tooltip, so the pointer can travel onto it
297
+ // without leaving the hover target (WCAG 1.4.13 Hoverable).
298
+ paddingBottom: 4,
299
+ whiteSpace: "nowrap",
300
+ zIndex: 1e3
301
+ },
302
+ children: /* @__PURE__ */ jsx4(Card, { radius: 2, shadow: 2, padding: 2, children: /* @__PURE__ */ jsx4(Text, { size: 1, children: text }) })
303
+ }
304
+ )
305
+ ]
306
+ }
307
+ );
127
308
  }
128
- var InstalledMenuButton = INSTALLED2.MenuButton;
129
- var InstalledMenu = INSTALLED2.Menu;
130
- var InstalledMenuItem = INSTALLED2.MenuItem;
131
- var HAS_INSTALLED_MENU = Boolean(InstalledMenuButton && InstalledMenu && InstalledMenuItem);
132
- function ActionMenu({ id, items, buttonIcon }) {
133
- const [open, setOpen] = useState(false);
309
+
310
+ // src/compat/menu.tsx
311
+ import { useCallback as useCallback2, useEffect as useEffect2, useId as useId2, useRef, useState as useState3 } from "react";
312
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
313
+ var InstalledMenuButton = resolveComponent(UI, "MenuButton");
314
+ var InstalledMenu = resolveComponent(UI, "Menu");
315
+ var InstalledMenuItem = resolveComponent(UI, "MenuItem");
316
+ var INSTALLED_MENU = InstalledMenuButton && InstalledMenu && InstalledMenuItem ? { MenuButton: InstalledMenuButton, Menu: InstalledMenu, MenuItem: InstalledMenuItem } : null;
317
+ var itemKey = (item, index) => item.key ?? `${index}-${item.text}`;
318
+ function ActionMenu({ id, label, items, buttonIcon }) {
319
+ const menuId = useId2();
320
+ const [open, setOpen] = useState3(false);
321
+ const [activeIndex, setActiveIndex] = useState3(0);
134
322
  const wrapRef = useRef(null);
135
- useEffect(() => {
136
- if (HAS_INSTALLED_MENU || !open) return;
323
+ const triggerRef = useRef(null);
324
+ const itemRefs = useRef([]);
325
+ const [frozenItems, setFrozenItems] = useState3(items);
326
+ const shownItems = open ? frozenItems : items;
327
+ const close = useCallback2((returnFocus = true) => {
328
+ setOpen(false);
329
+ if (returnFocus) triggerRef.current?.focus();
330
+ }, []);
331
+ const openMenu = useCallback2((index) => {
332
+ setFrozenItems(items);
333
+ setActiveIndex(index);
334
+ setOpen(true);
335
+ }, [items]);
336
+ useEffect2(() => {
337
+ if (!open || INSTALLED_MENU) return;
338
+ itemRefs.current[activeIndex]?.focus();
339
+ }, [open, activeIndex]);
340
+ useEffect2(() => {
341
+ if (INSTALLED_MENU || !open) return;
137
342
  const onPointerDown = (e) => {
138
- if (!wrapRef.current?.contains(e.target)) setOpen(false);
139
- };
140
- const onKeyDown = (e) => {
141
- if (e.key === "Escape") setOpen(false);
343
+ if (wrapRef.current?.contains(e.target)) return;
344
+ const hadFocus = wrapRef.current?.contains(document.activeElement);
345
+ setOpen(false);
346
+ if (hadFocus) triggerRef.current?.focus();
142
347
  };
143
348
  document.addEventListener("mousedown", onPointerDown);
144
- document.addEventListener("keydown", onKeyDown);
145
- return () => {
146
- document.removeEventListener("mousedown", onPointerDown);
147
- document.removeEventListener("keydown", onKeyDown);
148
- };
349
+ return () => document.removeEventListener("mousedown", onPointerDown);
149
350
  }, [open]);
150
- const runAction = useCallback((item) => {
151
- setOpen(false);
351
+ const runAction = useCallback2((item) => {
352
+ close();
152
353
  item.onClick?.();
153
- }, []);
154
- if (HAS_INSTALLED_MENU && InstalledMenuButton && InstalledMenu && InstalledMenuItem) {
155
- const MenuButton = InstalledMenuButton;
156
- const Menu = InstalledMenu;
157
- const MenuItem = InstalledMenuItem;
158
- return /* @__PURE__ */ jsx2(
354
+ }, [close]);
355
+ if (INSTALLED_MENU) {
356
+ const { MenuButton, Menu, MenuItem } = INSTALLED_MENU;
357
+ return /* @__PURE__ */ jsx5(
159
358
  MenuButton,
160
359
  {
161
360
  id,
162
- button: /* @__PURE__ */ jsx2(Button, { mode: "ghost", icon: buttonIcon, padding: 2 }),
361
+ button: /* @__PURE__ */ jsx5(Button, { mode: "ghost", icon: buttonIcon, padding: 2, "aria-label": label }),
163
362
  popover: { placement: "bottom-end" },
164
- menu: /* @__PURE__ */ jsx2(Menu, { children: items.map((item) => /* @__PURE__ */ jsx2(
363
+ menu: /* @__PURE__ */ jsx5(Menu, { children: items.map((item, i) => /* @__PURE__ */ jsx5(
165
364
  MenuItem,
166
365
  {
167
366
  text: item.text,
168
367
  icon: item.icon,
169
368
  tone: item.tone,
170
- ...item.href ? { as: "a", href: item.href, target: "_blank", rel: "noreferrer" } : { onClick: () => item.onClick?.() }
369
+ ...item.href ? { as: "a", href: item.href, target: "_blank", rel: "noreferrer" } : { onClick: item.onClick }
171
370
  },
172
- item.text
371
+ itemKey(item, i)
173
372
  )) })
174
373
  }
175
374
  );
176
375
  }
177
- return /* @__PURE__ */ jsxs("div", { ref: wrapRef, style: { position: "relative" }, children: [
178
- /* @__PURE__ */ jsx2(
376
+ const onMenuKeyDown = (e) => {
377
+ const last = shownItems.length - 1;
378
+ if (e.key === "Escape") {
379
+ e.stopPropagation();
380
+ close();
381
+ return;
382
+ }
383
+ if (e.key === "Tab") {
384
+ triggerRef.current?.focus();
385
+ setOpen(false);
386
+ return;
387
+ }
388
+ if (e.key === "Enter" || e.key === " ") {
389
+ e.preventDefault();
390
+ const item = shownItems[activeIndex];
391
+ if (item) {
392
+ if (item.href) {
393
+ itemRefs.current[activeIndex]?.click();
394
+ } else {
395
+ runAction(item);
396
+ }
397
+ }
398
+ return;
399
+ }
400
+ if (e.key === "ArrowDown") {
401
+ e.preventDefault();
402
+ setActiveIndex((i) => i >= last ? 0 : i + 1);
403
+ return;
404
+ }
405
+ if (e.key === "ArrowUp") {
406
+ e.preventDefault();
407
+ setActiveIndex((i) => i <= 0 ? last : i - 1);
408
+ return;
409
+ }
410
+ if (e.key === "Home") {
411
+ e.preventDefault();
412
+ setActiveIndex(0);
413
+ return;
414
+ }
415
+ if (e.key === "End") {
416
+ e.preventDefault();
417
+ setActiveIndex(last);
418
+ return;
419
+ }
420
+ };
421
+ const onTriggerKeyDown = (e) => {
422
+ if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
423
+ e.preventDefault();
424
+ openMenu(0);
425
+ } else if (e.key === "ArrowUp") {
426
+ e.preventDefault();
427
+ openMenu(items.length - 1);
428
+ }
429
+ };
430
+ return /* @__PURE__ */ jsxs3("div", { ref: wrapRef, style: { position: "relative" }, children: [
431
+ /* @__PURE__ */ jsx5(
179
432
  Button,
180
433
  {
434
+ ref: triggerRef,
181
435
  mode: "ghost",
182
436
  icon: buttonIcon,
183
437
  padding: 2,
184
438
  id,
439
+ "aria-label": label,
185
440
  "aria-haspopup": "menu",
186
441
  "aria-expanded": open,
187
- onClick: () => setOpen((o) => !o)
442
+ "aria-controls": open ? menuId : void 0,
443
+ onClick: () => open ? close() : openMenu(0),
444
+ onKeyDown: onTriggerKeyDown
188
445
  }
189
446
  ),
190
- open && /* @__PURE__ */ jsx2(
447
+ open && /* @__PURE__ */ jsx5(
191
448
  Card,
192
449
  {
450
+ id: menuId,
193
451
  radius: 2,
194
452
  shadow: 3,
195
453
  padding: 1,
196
454
  role: "menu",
197
- style: { position: "absolute", top: "100%", right: 0, marginTop: 4, zIndex: 1e3, minWidth: 180 },
198
- children: /* @__PURE__ */ jsx2(Stack, { space: 1, children: items.map((item) => {
455
+ "aria-labelledby": id,
456
+ onKeyDown: onMenuKeyDown,
457
+ style: { position: "absolute", top: "100%", right: 0, marginTop: 4, zIndex: 1e3, minWidth: 200 },
458
+ children: /* @__PURE__ */ jsx5(Stack, { space: 1, role: "none", children: shownItems.map((item, i) => {
199
459
  const Icon = item.icon;
200
- const label = /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, paddingX: 2, paddingY: 2, children: [
201
- /* @__PURE__ */ jsx2(Icon, { width: "1em", height: "1em" }),
202
- /* @__PURE__ */ jsx2(Text, { size: 1, children: item.text })
460
+ const row = /* @__PURE__ */ jsxs3(Flex, { align: "center", gap: 2, paddingX: 2, paddingY: 2, children: [
461
+ /* @__PURE__ */ jsx5(Icon, { width: "1em", height: "1em", "aria-hidden": "true" }),
462
+ /* @__PURE__ */ jsx5(Text, { size: 1, children: item.text })
203
463
  ] });
204
- return item.href ? /* @__PURE__ */ jsx2(
464
+ const content = item.tone === "critical" ? /* @__PURE__ */ jsx5(Card, { tone: "critical", radius: 1, children: row }) : row;
465
+ const shared = {
466
+ role: "menuitem",
467
+ // Roving tabindex — the menu is one tab stop, arrows move within it.
468
+ tabIndex: i === activeIndex ? 0 : -1,
469
+ ref: (el) => {
470
+ itemRefs.current[i] = el;
471
+ },
472
+ style: {
473
+ display: "block",
474
+ width: "100%",
475
+ textAlign: "left",
476
+ cursor: "pointer",
477
+ borderRadius: 3,
478
+ background: "none",
479
+ border: 0,
480
+ padding: 0,
481
+ font: "inherit",
482
+ color: "inherit",
483
+ textDecoration: "none",
484
+ // Card suppresses its own focus ring, so the active item draws one explicitly.
485
+ outline: i === activeIndex ? "2px solid var(--card-focus-ring-color, currentColor)" : "none",
486
+ outlineOffset: -2
487
+ }
488
+ };
489
+ return item.href ? /* @__PURE__ */ jsx5(
205
490
  "a",
206
491
  {
207
- role: "menuitem",
492
+ ...shared,
208
493
  href: item.href,
209
494
  target: "_blank",
210
495
  rel: "noreferrer",
211
- onClick: () => setOpen(false),
212
- style: { color: "inherit", textDecoration: "none", display: "block" },
213
- children: label
496
+ onClick: () => {
497
+ setOpen(false);
498
+ triggerRef.current?.focus();
499
+ },
500
+ children: content
214
501
  },
215
- item.text
216
- ) : /* @__PURE__ */ jsx2(
217
- Card,
502
+ itemKey(item, i)
503
+ ) : /* @__PURE__ */ jsx5(
504
+ "div",
218
505
  {
219
- as: "button",
220
- role: "menuitem",
221
- tone: item.tone === "critical" ? "critical" : "default",
222
- radius: 1,
506
+ ...shared,
223
507
  onClick: () => runAction(item),
224
- style: { display: "block", width: "100%", textAlign: "left", cursor: "pointer", border: 0, background: "none" },
225
- children: label
508
+ children: content
226
509
  },
227
- item.text
510
+ itemKey(item, i)
228
511
  );
229
512
  }) })
230
513
  }
231
514
  )
232
515
  ] });
233
516
  }
234
- var InstalledCode = INSTALLED2.Code;
517
+
518
+ // src/compat/code.tsx
519
+ import { jsx as jsx6 } from "react/jsx-runtime";
520
+ var InstalledCode = resolveComponent(UI, "Code");
235
521
  var FALLBACK_CODE_STYLE = {
522
+ display: "block",
236
523
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
237
524
  fontSize: "0.8125rem",
238
525
  lineHeight: 1.4,
239
526
  margin: 0
240
527
  };
241
528
  function Code({ style, children }) {
242
- if (InstalledCode) return /* @__PURE__ */ jsx2(InstalledCode, { size: 1, style, children });
243
- return /* @__PURE__ */ jsx2("code", { style: { ...FALLBACK_CODE_STYLE, ...style }, children });
529
+ if (InstalledCode) return /* @__PURE__ */ jsx6(InstalledCode, { size: 1, style, children });
530
+ return /* @__PURE__ */ jsx6("code", { style: { ...FALLBACK_CODE_STYLE, ...style }, children });
244
531
  }
245
532
 
246
- // src/components/DeployItem.tsx
247
- import { useState as useState3, useEffect as useEffect3, useCallback as useCallback3, useRef as useRef2 } from "react";
248
- import { flushSync } from "react-dom";
249
- import {
250
- Card as Card3,
251
- Box as Box3,
252
- Flex as Flex4,
253
- Text as Text3,
254
- Button as Button3,
255
- Badge as Badge3,
256
- Spinner as Spinner3
257
- } from "@sanity/ui";
258
-
259
533
  // src/lib/api.ts
260
534
  var BASE = "https://api.vercel.com";
261
535
  var VERCEL_HOOK_RE = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\//;
@@ -288,10 +562,14 @@ async function listDeployments(opts) {
288
562
  return data.deployments ?? [];
289
563
  }
290
564
  async function cancelDeployment(opts) {
291
- const params = opts.teamId ? `?teamId=${opts.teamId}` : "";
292
- await vercelFetch(`/v12/deployments/${opts.deploymentId}/cancel${params}`, opts.token, {
293
- method: "PATCH"
294
- });
565
+ const params = new URLSearchParams();
566
+ if (opts.teamId) params.set("teamId", opts.teamId);
567
+ const query = params.toString() ? `?${params}` : "";
568
+ await vercelFetch(
569
+ `/v12/deployments/${encodeURIComponent(opts.deploymentId)}/cancel${query}`,
570
+ opts.token,
571
+ { method: "PATCH" }
572
+ );
295
573
  }
296
574
  async function triggerDeploy(hookUrl) {
297
575
  if (!VERCEL_HOOK_RE.test(hookUrl)) {
@@ -355,6 +633,11 @@ function safeHref(url) {
355
633
  return void 0;
356
634
  }
357
635
  }
636
+ function deploymentHref(host) {
637
+ if (!host) return void 0;
638
+ if (!/^[a-z0-9.-]+$/i.test(host)) return void 0;
639
+ return safeHref(`https://${host}`);
640
+ }
358
641
  function shortSha(sha) {
359
642
  return sha ? sha.slice(0, 7) : "";
360
643
  }
@@ -397,36 +680,26 @@ function projectHref(inspectorUrl) {
397
680
  }
398
681
 
399
682
  // src/components/StatusBadge.tsx
400
- import { Badge, Spinner, Flex as Flex2 } from "@sanity/ui";
401
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
683
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
402
684
  function StatusBadge({ state, showSpinner }) {
403
685
  const { label, tone } = stateLabel(state);
404
686
  const spinning = showSpinner && (state === "QUEUED" || state === "INITIALIZING" || state === "BUILDING");
405
- return /* @__PURE__ */ jsxs2(Flex2, { align: "center", gap: 2, children: [
406
- spinning && /* @__PURE__ */ jsx3(Spinner, { muted: true }),
407
- /* @__PURE__ */ jsx3(Badge, { tone, padding: 2, children: label })
687
+ return /* @__PURE__ */ jsxs4(Flex, { align: "center", gap: 2, children: [
688
+ spinning && /* @__PURE__ */ jsx7(Spinner, { muted: true }),
689
+ /* @__PURE__ */ jsx7(Badge, { tone, padding: 2, children: label })
408
690
  ] });
409
691
  }
410
692
 
411
693
  // src/components/DeployHistory.tsx
412
- import { useEffect as useEffect2, useState as useState2, useCallback as useCallback2 } from "react";
413
- import {
414
- Dialog,
415
- Card as Card2,
416
- Box as Box2,
417
- Flex as Flex3,
418
- Text as Text2,
419
- Badge as Badge2,
420
- Spinner as Spinner2,
421
- Button as Button2
422
- } from "@sanity/ui";
423
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
694
+ import { useId as useId3, useEffect as useEffect3, useState as useState4, useCallback as useCallback3 } from "react";
695
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
424
696
  function DeployHistory({ target, token, onClose }) {
425
- const [deployments, setDeployments] = useState2([]);
426
- const [loading, setLoading] = useState2(true);
427
- const [error, setError] = useState2(null);
697
+ const dialogId = useId3();
698
+ const [deployments, setDeployments] = useState4([]);
699
+ const [loading, setLoading] = useState4(true);
700
+ const [error, setError] = useState4(null);
428
701
  const { projectId, hookId } = parseHookUrl(target.url);
429
- const load = useCallback2(async () => {
702
+ const load = useCallback3(async () => {
430
703
  setLoading(true);
431
704
  setError(null);
432
705
  try {
@@ -438,64 +711,68 @@ function DeployHistory({ target, token, onClose }) {
438
711
  setLoading(false);
439
712
  }
440
713
  }, [projectId, hookId, token, target.teamId]);
441
- useEffect2(() => {
714
+ useEffect3(() => {
442
715
  load();
443
716
  }, [load]);
444
- return /* @__PURE__ */ jsx4(
717
+ return /* @__PURE__ */ jsx8(
445
718
  Dialog,
446
719
  {
447
720
  header: `${target.name} \u2014 Deployment History`,
448
- id: "deploy-history",
721
+ id: dialogId,
449
722
  onClose,
450
723
  width: 2,
451
- footer: /* @__PURE__ */ jsx4(Box2, { padding: 3, children: /* @__PURE__ */ jsx4(Button2, { text: "Close", icon: CloseIcon, mode: "ghost", onClick: onClose }) }),
452
- children: /* @__PURE__ */ jsxs3(Box2, { padding: 4, children: [
453
- loading && /* @__PURE__ */ jsx4(Flex3, { justify: "center", padding: 6, children: /* @__PURE__ */ jsx4(Spinner2, { muted: true }) }),
454
- error && /* @__PURE__ */ jsx4(Card2, { tone: "critical", padding: 4, radius: 2, children: /* @__PURE__ */ jsx4(Text2, { size: 1, children: error }) }),
455
- !loading && !error && deployments.length === 0 && /* @__PURE__ */ jsx4(Card2, { tone: "transparent", padding: 4, children: /* @__PURE__ */ jsx4(Text2, { size: 1, muted: true, align: "center", children: "No deployments found for this hook." }) }),
456
- !loading && deployments.length > 0 && /* @__PURE__ */ jsxs3(Stack, { space: 2, children: [
457
- /* @__PURE__ */ jsx4(Card2, { padding: 3, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsxs3(Flex3, { gap: 3, children: [
458
- /* @__PURE__ */ jsx4(Box2, { flex: 2, children: /* @__PURE__ */ jsx4(Text2, { size: 0, weight: "semibold", muted: true, children: "Preview URL" }) }),
459
- /* @__PURE__ */ jsx4(Box2, { flex: 1, children: /* @__PURE__ */ jsx4(Text2, { size: 0, weight: "semibold", muted: true, children: "Status" }) }),
460
- /* @__PURE__ */ jsx4(Box2, { flex: 2, children: /* @__PURE__ */ jsx4(Text2, { size: 0, weight: "semibold", muted: true, children: "Branch \xB7 Commit" }) }),
461
- /* @__PURE__ */ jsx4(Box2, { flex: 1, children: /* @__PURE__ */ jsx4(Text2, { size: 0, weight: "semibold", muted: true, children: "Deployed" }) }),
462
- /* @__PURE__ */ jsx4(Box2, { style: { width: 64 }, children: /* @__PURE__ */ jsx4(Text2, { size: 0, weight: "semibold", muted: true, children: "Logs" }) })
724
+ footer: /* @__PURE__ */ jsx8(Box, { padding: 3, children: /* @__PURE__ */ jsx8(Button, { text: "Close", icon: CloseIcon, mode: "ghost", onClick: onClose }) }),
725
+ children: /* @__PURE__ */ jsxs5(Box, { padding: 4, children: [
726
+ loading && /* @__PURE__ */ jsx8(Flex, { justify: "center", padding: 6, children: /* @__PURE__ */ jsx8(Spinner, { muted: true }) }),
727
+ error && /* @__PURE__ */ jsx8(Card, { tone: "critical", padding: 4, radius: 2, children: /* @__PURE__ */ jsx8(Text, { size: 1, children: error }) }),
728
+ !loading && !error && deployments.length === 0 && /* @__PURE__ */ jsx8(Card, { tone: "transparent", padding: 4, children: /* @__PURE__ */ jsx8(Text, { size: 1, muted: true, align: "center", children: "No deployments found for this hook." }) }),
729
+ !loading && deployments.length > 0 && /* @__PURE__ */ jsxs5(Stack, { space: 2, children: [
730
+ /* @__PURE__ */ jsx8(Card, { padding: 3, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsxs5(Flex, { gap: 3, children: [
731
+ /* @__PURE__ */ jsx8(Box, { flex: 2, children: /* @__PURE__ */ jsx8(Text, { size: 0, weight: "semibold", muted: true, children: "Preview URL" }) }),
732
+ /* @__PURE__ */ jsx8(Box, { flex: 1, children: /* @__PURE__ */ jsx8(Text, { size: 0, weight: "semibold", muted: true, children: "Status" }) }),
733
+ /* @__PURE__ */ jsx8(Box, { flex: 2, children: /* @__PURE__ */ jsx8(Text, { size: 0, weight: "semibold", muted: true, children: "Branch \xB7 Commit" }) }),
734
+ /* @__PURE__ */ jsx8(Box, { flex: 1, children: /* @__PURE__ */ jsx8(Text, { size: 0, weight: "semibold", muted: true, children: "Deployed" }) }),
735
+ /* @__PURE__ */ jsx8(Box, { style: { width: 64 }, children: /* @__PURE__ */ jsx8(Text, { size: 0, weight: "semibold", muted: true, children: "Logs" }) })
463
736
  ] }) }),
464
737
  deployments.map((d) => {
465
738
  const { label, tone } = stateLabel(d.state);
466
739
  const branch = d.meta?.githubCommitRef ?? "\u2014";
467
740
  const sha = shortSha(d.meta?.githubCommitSha);
468
741
  const message = d.meta?.githubCommitMessage?.split("\n")[0] ?? "";
469
- return /* @__PURE__ */ jsx4(Card2, { padding: 3, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs3(Flex3, { gap: 3, align: "center", children: [
470
- /* @__PURE__ */ jsx4(Box2, { flex: 2, style: { overflow: "hidden" }, children: d.url ? /* @__PURE__ */ jsx4(
742
+ return /* @__PURE__ */ jsx8(Card, { padding: 3, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs5(Flex, { gap: 3, align: "center", children: [
743
+ /* @__PURE__ */ jsx8(Box, { flex: 2, style: { overflow: "hidden" }, children: deploymentHref(d.url) ? /* @__PURE__ */ jsx8(
471
744
  "a",
472
745
  {
473
- href: `https://${d.url}`,
746
+ href: deploymentHref(d.url),
474
747
  target: "_blank",
475
748
  rel: "noreferrer",
476
749
  style: { color: "inherit" },
477
- children: /* @__PURE__ */ jsx4(Text2, { size: 1, style: { textDecoration: "underline" }, children: d.url.length > 36 ? `${d.url.slice(0, 36)}\u2026` : d.url })
750
+ children: /* @__PURE__ */ jsx8(Text, { size: 1, style: { textDecoration: "underline" }, children: d.url.length > 36 ? `${d.url.slice(0, 36)}\u2026` : d.url })
478
751
  }
479
- ) : /* @__PURE__ */ jsx4(Text2, { size: 1, muted: true, children: "\u2014" }) }),
480
- /* @__PURE__ */ jsx4(Box2, { flex: 1, children: /* @__PURE__ */ jsx4(Badge2, { tone, children: label }) }),
481
- /* @__PURE__ */ jsx4(Box2, { flex: 2, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsxs3(Stack, { space: 1, children: [
482
- /* @__PURE__ */ jsx4(Text2, { size: 1, children: branch }),
483
- sha && /* @__PURE__ */ jsxs3(Text2, { size: 0, muted: true, children: [
752
+ ) : /* @__PURE__ */ jsx8(Text, { size: 1, muted: true, children: "\u2014" }) }),
753
+ /* @__PURE__ */ jsx8(Box, { flex: 1, children: /* @__PURE__ */ jsx8(Badge, { tone, children: label }) }),
754
+ /* @__PURE__ */ jsx8(Box, { flex: 2, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsxs5(Stack, { space: 1, children: [
755
+ /* @__PURE__ */ jsx8(Text, { size: 1, children: branch }),
756
+ sha && /* @__PURE__ */ jsxs5(Text, { size: 0, muted: true, children: [
484
757
  sha,
485
758
  message ? ` \xB7 ${message.slice(0, 40)}${message.length > 40 ? "\u2026" : ""}` : ""
486
759
  ] })
487
760
  ] }) }),
488
- /* @__PURE__ */ jsx4(Box2, { flex: 1, children: /* @__PURE__ */ jsx4(Text2, { size: 1, muted: true, children: timeAgo(d.created) }) }),
489
- /* @__PURE__ */ jsx4(Box2, { style: { width: 64 }, children: safeHref(d.inspectorUrl) ? /* @__PURE__ */ jsx4("a", { href: safeHref(d.inspectorUrl), target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsx4(
490
- Button2,
761
+ /* @__PURE__ */ jsx8(Box, { flex: 1, children: /* @__PURE__ */ jsx8(Text, { size: 1, muted: true, children: timeAgo(d.created) }) }),
762
+ /* @__PURE__ */ jsx8(Box, { style: { width: 64 }, children: safeHref(d.inspectorUrl) ? /* @__PURE__ */ jsx8(
763
+ Button,
491
764
  {
765
+ as: "a",
766
+ href: safeHref(d.inspectorUrl),
767
+ target: "_blank",
768
+ rel: "noreferrer",
492
769
  text: "Logs",
493
770
  mode: "ghost",
494
771
  tone: "default",
495
772
  icon: LaunchIcon,
496
773
  style: { fontSize: "12px" }
497
774
  }
498
- ) }) : /* @__PURE__ */ jsx4(Text2, { size: 1, muted: true, children: "\u2014" }) })
775
+ ) : /* @__PURE__ */ jsx8(Text, { size: 1, muted: true, children: "\u2014" }) })
499
776
  ] }) }, d.uid);
500
777
  })
501
778
  ] })
@@ -505,58 +782,72 @@ function DeployHistory({ target, token, onClose }) {
505
782
  }
506
783
 
507
784
  // src/components/DeployItem.tsx
508
- import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
785
+ import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
509
786
  var POLL_INTERVAL_MS = 5e3;
510
787
  var LABEL_WIDTH = 64;
511
788
  var PENDING_TIMEOUT_MS = 6e4;
512
789
  function DeployItem({ target, token, onDelete, onEdit }) {
513
790
  const { projectId, hookId } = parseHookUrl(target.url);
514
791
  const toast = useToast();
515
- const [deployments, setDeployments] = useState3([]);
516
- const [loadingInitial, setLoadingInitial] = useState3(true);
517
- const [pendingSince, setPendingSince] = useState3(null);
518
- const [canceling, setCanceling] = useState3(false);
519
- const [deployError, setDeployError] = useState3(null);
520
- const [showHistory, setShowHistory] = useState3(false);
521
- const [elapsed, setElapsed] = useState3(0);
522
- const [copied, setCopied] = useState3(false);
523
- const [showDetails, setShowDetails] = useState3(false);
524
- const [showErrorLogs, setShowErrorLogs] = useState3(false);
525
- const [errorLines, setErrorLines] = useState3([]);
526
- const [loadingLogs, setLoadingLogs] = useState3(false);
527
- const [logError, setLogError] = useState3(null);
792
+ const [deployments, setDeployments] = useState5([]);
793
+ const [loadingInitial, setLoadingInitial] = useState5(true);
794
+ const [pendingSince, setPendingSince] = useState5(null);
795
+ const [canceling, setCanceling] = useState5(false);
796
+ const [deployError, setDeployError] = useState5(null);
797
+ const [showHistory, setShowHistory] = useState5(false);
798
+ const [elapsed, setElapsed] = useState5(0);
799
+ const [copied, setCopied] = useState5(false);
800
+ const [showDetails, setShowDetails] = useState5(false);
801
+ const [showErrorLogs, setShowErrorLogs] = useState5(false);
802
+ const [errorLines, setErrorLines] = useState5([]);
803
+ const [loadingLogs, setLoadingLogs] = useState5(false);
804
+ const [logError, setLogError] = useState5(null);
805
+ const [pollError, setPollError] = useState5(null);
528
806
  const triggeredFromUidRef = useRef2(void 0);
807
+ const requestSeqRef = useRef2(0);
808
+ const mountedRef = useRef2(true);
809
+ useEffect4(() => {
810
+ mountedRef.current = true;
811
+ return () => {
812
+ mountedRef.current = false;
813
+ };
814
+ }, []);
529
815
  const latest = deployments[0];
530
816
  const isPending = pendingSince !== null;
531
817
  const isActive = isPending || isActiveState(latest?.state);
532
- const fetchDeployments = useCallback3(async () => {
818
+ const fetchDeployments = useCallback4(async () => {
533
819
  if (!projectId || !hookId || !token) return;
820
+ const seq = ++requestSeqRef.current;
534
821
  try {
535
822
  const data = await listDeployments({ projectId, hookId, token, teamId: target.teamId });
823
+ if (seq !== requestSeqRef.current || !mountedRef.current) return;
536
824
  setDeployments(data);
825
+ setPollError(null);
537
826
  } catch (err) {
538
- console.error("deploy-vercel-from-sanity: fetch error", err);
827
+ if (seq !== requestSeqRef.current || !mountedRef.current) return;
828
+ setPollError(err instanceof Error ? err.message : "Could not reach the Vercel API");
829
+ console.error("Deploy-vercel-from-sanity: fetch error", err);
539
830
  }
540
831
  }, [projectId, hookId, token, target.teamId]);
541
- useEffect3(() => {
832
+ useEffect4(() => {
542
833
  fetchDeployments().finally(() => setLoadingInitial(false));
543
834
  }, [fetchDeployments]);
544
- useEffect3(() => {
835
+ useEffect4(() => {
545
836
  if (!isActive) return;
546
837
  const id = setInterval(fetchDeployments, POLL_INTERVAL_MS);
547
838
  return () => clearInterval(id);
548
839
  }, [isActive, fetchDeployments]);
549
- useEffect3(() => {
840
+ useEffect4(() => {
550
841
  if (!isPending) return;
551
842
  if (latest?.uid && latest.uid !== triggeredFromUidRef.current) setPendingSince(null);
552
843
  }, [isPending, latest?.uid]);
553
- useEffect3(() => {
844
+ useEffect4(() => {
554
845
  if (!isPending) return;
555
846
  const id = setTimeout(() => setPendingSince(null), PENDING_TIMEOUT_MS);
556
847
  return () => clearTimeout(id);
557
848
  }, [isPending]);
558
849
  const prevStateRef = useRef2(void 0);
559
- useEffect3(() => {
850
+ useEffect4(() => {
560
851
  const current = latest?.state;
561
852
  const prev = prevStateRef.current;
562
853
  if (prev && isActiveState(prev) && current && !isActiveState(current)) {
@@ -570,13 +861,13 @@ function DeployItem({ target, token, onDelete, onEdit }) {
570
861
  }
571
862
  prevStateRef.current = current;
572
863
  }, [latest?.state, target.name, toast]);
573
- useEffect3(() => {
864
+ useEffect4(() => {
574
865
  setShowErrorLogs(false);
575
866
  setErrorLines([]);
576
867
  setLogError(null);
577
868
  }, [latest?.uid]);
578
869
  const timerRef = useRef2(null);
579
- useEffect3(() => {
870
+ useEffect4(() => {
580
871
  if (isActive) {
581
872
  const start = pendingSince ?? latest?.created ?? Date.now();
582
873
  setElapsed(Math.floor((Date.now() - start) / 1e3));
@@ -591,7 +882,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
591
882
  if (timerRef.current) clearInterval(timerRef.current);
592
883
  };
593
884
  }, [isActive, pendingSince, latest?.created]);
594
- const deploy = useCallback3(() => {
885
+ const deploy = useCallback4(() => {
595
886
  flushSync(() => {
596
887
  setDeployError(null);
597
888
  triggeredFromUidRef.current = latest?.uid;
@@ -607,7 +898,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
607
898
  }
608
899
  })();
609
900
  }, [target.url, fetchDeployments, latest?.uid]);
610
- const cancel = useCallback3(async () => {
901
+ const cancel = useCallback4(async () => {
611
902
  if (!latest?.uid) return;
612
903
  setCanceling(true);
613
904
  try {
@@ -619,9 +910,9 @@ function DeployItem({ target, token, onDelete, onEdit }) {
619
910
  setCanceling(false);
620
911
  }
621
912
  }, [latest?.uid, token, target.teamId, fetchDeployments]);
622
- const copyUrl = useCallback3(() => {
913
+ const copyUrl = useCallback4(() => {
623
914
  if (!latest?.url) return;
624
- const fullUrl = `https://${latest.url}`;
915
+ const fullUrl = deploymentHref(latest.url) ?? "";
625
916
  navigator.clipboard.writeText(fullUrl).then(() => {
626
917
  setCopied(true);
627
918
  setTimeout(() => setCopied(false), 2e3);
@@ -629,7 +920,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
629
920
  window.prompt("Copy deployment URL:", fullUrl);
630
921
  });
631
922
  }, [latest?.url]);
632
- const fetchErrorLogs = useCallback3(async () => {
923
+ const fetchErrorLogs = useCallback4(async () => {
633
924
  if (!latest?.uid) return;
634
925
  setLoadingLogs(true);
635
926
  setLogError(null);
@@ -647,7 +938,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
647
938
  setLoadingLogs(false);
648
939
  }
649
940
  }, [latest?.uid, token, target.teamId]);
650
- const toggleErrorLogs = useCallback3(() => {
941
+ const toggleErrorLogs = useCallback4(() => {
651
942
  if (!showErrorLogs && errorLines.length === 0 && !logError) fetchErrorLogs();
652
943
  setShowErrorLogs((v) => !v);
653
944
  }, [showErrorLogs, errorLines.length, logError, fetchErrorLogs]);
@@ -655,26 +946,26 @@ function DeployItem({ target, token, onDelete, onEdit }) {
655
946
  const commitMsg = latest?.meta?.githubCommitMessage?.split("\n")[0];
656
947
  const sha = shortSha(latest?.meta?.githubCommitSha);
657
948
  const fullSha = latest?.meta?.githubCommitSha;
658
- const commitHref = githubCommitHref(latest?.meta);
949
+ const commitHref = safeHref(githubCommitHref(latest?.meta) ?? void 0);
659
950
  const creator = latest?.creator?.username;
660
951
  const deployedAt = latest?.created ? timeAgo(latest.created) : null;
661
952
  const vercelProjectUrl = projectHref(latest?.inspectorUrl);
662
953
  const isError = latest?.state === "ERROR";
663
- return /* @__PURE__ */ jsxs4(Fragment, { children: [
664
- /* @__PURE__ */ jsx5(Card3, { radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs4(Flex4, { align: "stretch", className: "dvfs-card-flex", children: [
665
- /* @__PURE__ */ jsxs4(Flex4, { direction: "column", flex: 1, style: { minWidth: 0 }, children: [
666
- /* @__PURE__ */ jsxs4(Stack, { space: 3, padding: 3, style: { flex: 1 }, children: [
667
- /* @__PURE__ */ jsxs4(Flex4, { align: "center", justify: "space-between", gap: 2, children: [
668
- /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 2, style: { minWidth: 0, flexWrap: "wrap" }, children: [
669
- /* @__PURE__ */ jsx5(Text3, { size: 2, weight: "semibold", style: { flexShrink: 0 }, children: target.name }),
670
- branch && /* @__PURE__ */ jsx5(Badge3, { tone: "default", padding: 2, children: /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 1, children: [
954
+ return /* @__PURE__ */ jsxs6(Fragment, { children: [
955
+ /* @__PURE__ */ jsx9(Card, { radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs6(Flex, { align: "stretch", className: "dvfs-card-flex", children: [
956
+ /* @__PURE__ */ jsxs6(Flex, { direction: "column", flex: 1, style: { minWidth: 0 }, children: [
957
+ /* @__PURE__ */ jsxs6(Stack, { space: 3, padding: 3, style: { flex: 1 }, children: [
958
+ /* @__PURE__ */ jsxs6(Flex, { align: "center", justify: "space-between", gap: 2, children: [
959
+ /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, style: { minWidth: 0, flexWrap: "wrap" }, children: [
960
+ /* @__PURE__ */ jsx9(Text, { size: 2, weight: "semibold", style: { flexShrink: 0 }, children: target.name }),
961
+ branch && /* @__PURE__ */ jsx9(Badge, { tone: "default", padding: 2, children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 1, children: [
671
962
  branch,
672
- /* @__PURE__ */ jsx5("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", style: { marginLeft: "-0.1em", opacity: 0.5 }, children: /* @__PURE__ */ jsx5("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" }) })
963
+ /* @__PURE__ */ jsx9("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", style: { marginLeft: "-0.1em", opacity: 0.5 }, children: /* @__PURE__ */ jsx9("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" }) })
673
964
  ] }) }),
674
- token && !loadingInitial && /* @__PURE__ */ jsxs4(Fragment, { children: [
675
- isPending ? /* @__PURE__ */ jsx5(StatusBadge, { state: "QUEUED" }) : /* @__PURE__ */ jsx5(StatusBadge, { state: latest?.state }),
676
- isActiveState(latest?.state) && /* @__PURE__ */ jsx5(
677
- Button3,
965
+ token && !loadingInitial && /* @__PURE__ */ jsxs6(Fragment, { children: [
966
+ isPending ? /* @__PURE__ */ jsx9(StatusBadge, { state: "QUEUED" }) : /* @__PURE__ */ jsx9(StatusBadge, { state: latest?.state }),
967
+ isActiveState(latest?.state) && /* @__PURE__ */ jsx9(
968
+ Button,
678
969
  {
679
970
  text: "Cancel",
680
971
  mode: "ghost",
@@ -687,17 +978,18 @@ function DeployItem({ target, token, onDelete, onEdit }) {
687
978
  ),
688
979
  isPending ? (
689
980
  /* Optimistic — dimmed spinner only; no elapsed time until a real build exists */
690
- /* @__PURE__ */ jsx5(Spinner3, { muted: true, style: { marginLeft: 4, opacity: 0.5 } })
691
- ) : isActive ? /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 1, children: [
692
- /* @__PURE__ */ jsx5(Spinner3, { muted: true, style: { marginLeft: 4 } }),
693
- /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, children: formatDuration(elapsed) })
694
- ] }) : deployedAt ? /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, children: deployedAt }) : null
981
+ /* @__PURE__ */ jsx9(Spinner, { muted: true, style: { marginLeft: 4, opacity: 0.5 } })
982
+ ) : isActive ? /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 1, children: [
983
+ /* @__PURE__ */ jsx9(Spinner, { muted: true, style: { marginLeft: 4 } }),
984
+ /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, children: formatDuration(elapsed) })
985
+ ] }) : deployedAt ? /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, children: deployedAt }) : null
695
986
  ] })
696
987
  ] }),
697
- /* @__PURE__ */ jsx5(
988
+ /* @__PURE__ */ jsx9(
698
989
  ActionMenu,
699
990
  {
700
991
  id: `menu-${target._id}`,
992
+ label: `Actions for ${target.name}`,
701
993
  buttonIcon: EllipsisVerticalIcon,
702
994
  items: [
703
995
  { text: "Edit target", icon: EditIcon, onClick: () => onEdit(target) },
@@ -709,56 +1001,75 @@ function DeployItem({ target, token, onDelete, onEdit }) {
709
1001
  }
710
1002
  )
711
1003
  ] }),
712
- /* @__PURE__ */ jsx5("hr", { style: { border: "none", borderTop: "1px solid currentColor", opacity: 0.1, margin: 0 } }),
713
- !token ? /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, children: "Connect a Vercel API token to see deployment status." }) : loadingInitial ? /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 2, children: [
714
- /* @__PURE__ */ jsx5(Spinner3, { muted: true }),
715
- /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, children: "Loading\u2026" })
716
- ] }) : /* @__PURE__ */ jsxs4(Stack, { space: 2, children: [
717
- /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 2, wrap: "wrap", children: [
718
- latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx5(Fragment, { children: /* @__PURE__ */ jsx5(
1004
+ /* @__PURE__ */ jsx9("hr", { style: { border: "none", borderTop: "1px solid currentColor", opacity: 0.1, margin: 0 } }),
1005
+ !token ? /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, children: "Connect a Vercel API token to see deployment status." }) : loadingInitial ? /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, children: [
1006
+ /* @__PURE__ */ jsx9(Spinner, { muted: true }),
1007
+ /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, children: "Loading\u2026" })
1008
+ ] }) : /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1009
+ /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, wrap: "wrap", children: [
1010
+ latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx9(Fragment, { children: /* @__PURE__ */ jsx9(
719
1011
  "a",
720
1012
  {
721
- href: `https://${latest.url}`,
1013
+ href: deploymentHref(latest.url),
722
1014
  target: "_blank",
723
1015
  rel: "noreferrer",
724
1016
  style: { color: "inherit" },
725
- children: /* @__PURE__ */ jsx5(Flex4, { align: "center", gap: 1, children: /* @__PURE__ */ jsx5(Text3, { size: 1, children: latest.url }) })
1017
+ children: /* @__PURE__ */ jsx9(Flex, { align: "center", gap: 1, children: /* @__PURE__ */ jsx9(Text, { size: 1, children: latest.url }) })
726
1018
  }
727
1019
  ) }),
728
- sha && /* @__PURE__ */ jsx5(Tooltip, { text: commitMsg ?? sha, children: commitHref ? /* @__PURE__ */ jsx5(
1020
+ sha && /* @__PURE__ */ jsx9(Tooltip, { text: commitMsg ?? sha, children: commitHref ? /* @__PURE__ */ jsx9(
729
1021
  "a",
730
1022
  {
731
1023
  href: commitHref,
732
1024
  target: "_blank",
733
1025
  rel: "noreferrer",
734
1026
  style: { color: "inherit", textDecoration: "none" },
735
- children: /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, style: { cursor: "pointer", fontFamily: "monospace" }, children: sha })
1027
+ children: /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, style: { cursor: "pointer", fontFamily: "monospace" }, children: sha })
736
1028
  }
737
- ) : /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, style: { cursor: "default", fontFamily: "monospace" }, children: sha }) }),
738
- creator && /* @__PURE__ */ jsxs4(Text3, { size: 1, muted: true, children: [
1029
+ ) : /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, style: { cursor: "default", fontFamily: "monospace" }, children: sha }) }),
1030
+ creator && /* @__PURE__ */ jsxs6(Text, { size: 1, muted: true, children: [
739
1031
  "by ",
740
1032
  creator
741
1033
  ] }),
742
- latest?.state === "READY" && latest.ready && latest.created && /* @__PURE__ */ jsxs4(Text3, { size: 1, muted: true, children: [
1034
+ latest?.state === "READY" && latest.ready && latest.created && /* @__PURE__ */ jsxs6(Text, { size: 1, muted: true, children: [
743
1035
  "Took ",
744
1036
  formatDuration(Math.floor((latest.ready - latest.created) / 1e3)),
745
1037
  " to build"
746
1038
  ] }),
747
- latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx5(Fragment, { children: /* @__PURE__ */ jsx5(Tooltip, { text: copied ? "Copied!" : "Copy URL", children: /* @__PURE__ */ jsx5(
748
- Button3,
749
- {
750
- mode: "ghost",
751
- icon: copied ? CheckmarkIcon : CopyIcon,
752
- padding: 1,
753
- tone: copied ? "positive" : "default",
754
- onClick: copyUrl,
755
- style: { cursor: "pointer" }
756
- }
757
- ) }) })
1039
+ latest?.url && latest.state === "READY" && /* @__PURE__ */ jsxs6(Fragment, { children: [
1040
+ /* @__PURE__ */ jsx9(Tooltip, { text: copied ? "Copied" : "Copy deployment URL", children: /* @__PURE__ */ jsx9(
1041
+ Button,
1042
+ {
1043
+ mode: "ghost",
1044
+ icon: copied ? CheckmarkIcon : CopyIcon,
1045
+ padding: 1,
1046
+ tone: copied ? "positive" : "default",
1047
+ onClick: copyUrl,
1048
+ "aria-label": copied ? "Deployment URL copied" : "Copy deployment URL",
1049
+ style: { cursor: "pointer" }
1050
+ }
1051
+ ) }),
1052
+ /* @__PURE__ */ jsx9(
1053
+ "span",
1054
+ {
1055
+ role: "status",
1056
+ "aria-live": "polite",
1057
+ style: {
1058
+ position: "absolute",
1059
+ width: 1,
1060
+ height: 1,
1061
+ overflow: "hidden",
1062
+ clip: "rect(0 0 0 0)",
1063
+ whiteSpace: "nowrap"
1064
+ },
1065
+ children: copied ? "Deployment URL copied to clipboard" : ""
1066
+ }
1067
+ )
1068
+ ] })
758
1069
  ] }),
759
- /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 2, wrap: "wrap", children: [
760
- commitMsg && /* @__PURE__ */ jsx5(
761
- Text3,
1070
+ /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, wrap: "wrap", children: [
1071
+ commitMsg && /* @__PURE__ */ jsx9(
1072
+ Text,
762
1073
  {
763
1074
  size: 0,
764
1075
  muted: true,
@@ -766,10 +1077,11 @@ function DeployItem({ target, token, onDelete, onEdit }) {
766
1077
  children: commitMsg
767
1078
  }
768
1079
  ),
769
- isError && /* @__PURE__ */ jsxs4(Stack, { space: 2, children: [
770
- /* @__PURE__ */ jsx5(
771
- Button3,
1080
+ isError && /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1081
+ /* @__PURE__ */ jsx9(
1082
+ Button,
772
1083
  {
1084
+ "aria-expanded": showErrorLogs,
773
1085
  text: showErrorLogs ? "Hide error details" : "Show error details",
774
1086
  mode: "ghost",
775
1087
  tone: "critical",
@@ -780,37 +1092,45 @@ function DeployItem({ target, token, onDelete, onEdit }) {
780
1092
  style: { alignSelf: "flex-start", cursor: "pointer" }
781
1093
  }
782
1094
  ),
783
- showErrorLogs && /* @__PURE__ */ jsxs4(Card3, { tone: "critical", radius: 2, padding: 3, children: [
784
- loadingLogs && /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 2, children: [
785
- /* @__PURE__ */ jsx5(Spinner3, { muted: true }),
786
- /* @__PURE__ */ jsx5(Text3, { size: 1, muted: true, children: "Loading logs\u2026" })
1095
+ showErrorLogs && /* @__PURE__ */ jsxs6(Card, { tone: "critical", radius: 2, padding: 3, children: [
1096
+ loadingLogs && /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, children: [
1097
+ /* @__PURE__ */ jsx9(Spinner, { muted: true }),
1098
+ /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, children: "Loading logs\u2026" })
787
1099
  ] }),
788
- logError && /* @__PURE__ */ jsxs4(Stack, { space: 2, children: [
789
- /* @__PURE__ */ jsx5(Text3, { size: 1, children: logError }),
790
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx5("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 1, children: [
791
- /* @__PURE__ */ jsx5(LaunchIcon, {}),
792
- /* @__PURE__ */ jsx5(Text3, { size: 1, children: "View full logs in Vercel" })
1100
+ logError && /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1101
+ /* @__PURE__ */ jsx9(Text, { size: 1, children: logError }),
1102
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx9("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 1, children: [
1103
+ /* @__PURE__ */ jsx9(LaunchIcon, {}),
1104
+ /* @__PURE__ */ jsx9(Text, { size: 1, children: "View full logs in Vercel" })
793
1105
  ] }) })
794
1106
  ] }),
795
- !loadingLogs && !logError && errorLines.length > 0 && /* @__PURE__ */ jsxs4(Stack, { space: 2, children: [
796
- /* @__PURE__ */ jsx5(Box3, { style: { maxHeight: 240, overflowY: "auto", fontFamily: "monospace", fontSize: 13, lineHeight: 1.6 }, children: errorLines.map((line, i) => /* @__PURE__ */ jsx5(Code, { style: { display: "block", whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: line }, i)) }),
797
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx5("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 1, children: [
798
- /* @__PURE__ */ jsx5(LaunchIcon, {}),
799
- /* @__PURE__ */ jsx5(Text3, { size: 1, children: "View full logs in Vercel" })
1107
+ !loadingLogs && !logError && errorLines.length > 0 && /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1108
+ /* @__PURE__ */ jsx9(Box, { style: { maxHeight: 240, overflowY: "auto", fontFamily: "monospace", fontSize: 13, lineHeight: 1.6 }, children: errorLines.map((line, i) => /* @__PURE__ */ jsx9(Code, { style: { display: "block", whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: line }, i)) }),
1109
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx9("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 1, children: [
1110
+ /* @__PURE__ */ jsx9(LaunchIcon, {}),
1111
+ /* @__PURE__ */ jsx9(Text, { size: 1, children: "View full logs in Vercel" })
800
1112
  ] }) })
801
1113
  ] })
802
1114
  ] })
803
1115
  ] }),
804
- deployError && /* @__PURE__ */ jsx5(Card3, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ jsx5(Text3, { size: 1, children: deployError }) })
1116
+ deployError && /* @__PURE__ */ jsx9(Card, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ jsx9(Text, { size: 1, children: deployError }) })
805
1117
  ] })
806
- ] })
1118
+ ] }),
1119
+ pollError && /* @__PURE__ */ jsx9(Card, { tone: "caution", padding: 3, radius: 2, children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, children: [
1120
+ /* @__PURE__ */ jsx9(WarningOutlineIcon, { "aria-hidden": "true" }),
1121
+ /* @__PURE__ */ jsxs6(Text, { size: 1, children: [
1122
+ "Status updates paused \u2014 ",
1123
+ pollError
1124
+ ] })
1125
+ ] }) })
807
1126
  ] }),
808
- /* @__PURE__ */ jsxs4(Box3, { children: [
809
- /* @__PURE__ */ jsx5(
810
- Button3,
1127
+ /* @__PURE__ */ jsxs6(Box, { children: [
1128
+ /* @__PURE__ */ jsx9(
1129
+ Button,
811
1130
  {
812
1131
  mode: "ghost",
813
1132
  iconRight: showDetails ? ChevronUpIcon : ChevronDownIcon,
1133
+ "aria-expanded": showDetails,
814
1134
  text: "Details",
815
1135
  fontSize: 0,
816
1136
  padding: 3,
@@ -818,62 +1138,62 @@ function DeployItem({ target, token, onDelete, onEdit }) {
818
1138
  style: { width: "100%", justifyContent: "flex-start", borderRadius: 0, cursor: "pointer" }
819
1139
  }
820
1140
  ),
821
- showDetails && /* @__PURE__ */ jsx5(Card3, { tone: "primary", padding: 3, className: "dvfs-accordion-content", style: { borderRadius: 0, borderTop: "1px solid rgba(128,128,128,0.15)" }, children: /* @__PURE__ */ jsxs4(Stack, { space: 2, children: [
822
- /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
823
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Project" }),
824
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: projectId || "\u2014" })
1141
+ showDetails && /* @__PURE__ */ jsx9(Card, { tone: "primary", padding: 3, className: "dvfs-accordion-content", style: { borderRadius: 0, borderTop: "1px solid rgba(128,128,128,0.15)" }, children: /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1142
+ /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1143
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Project" }),
1144
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: projectId || "\u2014" })
825
1145
  ] }),
826
- /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
827
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Hook" }),
828
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: hookId || "\u2014" })
1146
+ /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1147
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Hook" }),
1148
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: hookId || "\u2014" })
829
1149
  ] }),
830
- target.teamId && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
831
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Team" }),
832
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: target.teamId })
1150
+ target.teamId && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1151
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Team" }),
1152
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: target.teamId })
833
1153
  ] }),
834
- fullSha && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "flex-start", children: [
835
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Commit" }),
836
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: fullSha })
1154
+ fullSha && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "flex-start", children: [
1155
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Commit" }),
1156
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: fullSha })
837
1157
  ] }),
838
- latest?.meta?.githubCommitAuthorName && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
839
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Author" }),
840
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, children: latest.meta.githubCommitAuthorName })
1158
+ latest?.meta?.githubCommitAuthorName && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1159
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Author" }),
1160
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, children: latest.meta.githubCommitAuthorName })
841
1161
  ] }),
842
- branch && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
843
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Branch" }),
844
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: branch })
1162
+ branch && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1163
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Branch" }),
1164
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: branch })
845
1165
  ] }),
846
- latest?.uid && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
847
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Deploy ID" }),
848
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: latest.uid })
1166
+ latest?.uid && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1167
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Deploy ID" }),
1168
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: latest.uid })
849
1169
  ] }),
850
- latest?.url && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "flex-start", children: [
851
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "URL" }),
852
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: latest.url })
1170
+ latest?.url && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "flex-start", children: [
1171
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "URL" }),
1172
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: latest.url })
853
1173
  ] }),
854
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
855
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Inspector" }),
856
- /* @__PURE__ */ jsx5("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ jsxs4(Flex4, { align: "center", gap: 1, children: [
857
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: "Open in Vercel" }),
858
- /* @__PURE__ */ jsx5(LaunchIcon, { style: { width: 10, height: 10 } })
1174
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1175
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Inspector" }),
1176
+ /* @__PURE__ */ jsx9("a", { href: safeHref(latest?.inspectorUrl), target: "_blank", rel: "noreferrer", style: { color: "inherit" }, children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 1, children: [
1177
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, style: { fontFamily: "monospace" }, children: "Open in Vercel" }),
1178
+ /* @__PURE__ */ jsx9(LaunchIcon, { style: { width: 10, height: 10 } })
859
1179
  ] }) })
860
1180
  ] }),
861
- latest?.created && /* @__PURE__ */ jsxs4(Flex4, { gap: 2, align: "center", children: [
862
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Created" }),
863
- /* @__PURE__ */ jsx5(Text3, { size: 0, muted: true, children: new Date(latest.created).toLocaleString() })
1181
+ latest?.created && /* @__PURE__ */ jsxs6(Flex, { gap: 2, align: "center", children: [
1182
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, weight: "semibold", style: { minWidth: LABEL_WIDTH }, children: "Created" }),
1183
+ /* @__PURE__ */ jsx9(Text, { size: 0, muted: true, children: new Date(latest.created).toLocaleString() })
864
1184
  ] })
865
1185
  ] }) })
866
1186
  ] })
867
1187
  ] }),
868
- /* @__PURE__ */ jsx5(
869
- Flex4,
1188
+ /* @__PURE__ */ jsx9(
1189
+ Flex,
870
1190
  {
871
1191
  direction: "column",
872
1192
  gap: 2,
873
1193
  className: "dvfs-deploy-col",
874
1194
  style: { flexShrink: 0, alignSelf: "stretch" },
875
- children: /* @__PURE__ */ jsx5(
876
- Button3,
1195
+ children: /* @__PURE__ */ jsx9(
1196
+ Button,
877
1197
  {
878
1198
  text: "Deploy",
879
1199
  tone: "primary",
@@ -892,7 +1212,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
892
1212
  }
893
1213
  )
894
1214
  ] }) }),
895
- showHistory && /* @__PURE__ */ jsx5(
1215
+ showHistory && /* @__PURE__ */ jsx9(
896
1216
  DeployHistory,
897
1217
  {
898
1218
  target,
@@ -904,24 +1224,19 @@ function DeployItem({ target, token, onDelete, onEdit }) {
904
1224
  }
905
1225
 
906
1226
  // src/components/TokenSetup.tsx
907
- import { useState as useState4, useCallback as useCallback4 } from "react";
1227
+ import { useId as useId4, useState as useState6, useCallback as useCallback5 } from "react";
908
1228
  import { useClient } from "sanity";
909
- import {
910
- Text as Text4,
911
- TextInput,
912
- Button as Button4,
913
- Card as Card4,
914
- Dialog as Dialog2,
915
- Flex as Flex5
916
- } from "@sanity/ui";
917
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1229
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
918
1230
  var TOKEN_DOC_ID = "config.vercelDeploy";
919
- function TokenSetup({ onSaved, onCancel }) {
1231
+ function TokenSetup({ onSaved, onCancel, hasToken = false }) {
1232
+ const dialogId = useId4();
1233
+ const tokenId = useId4();
920
1234
  const client = useClient({ apiVersion: "2025-01-01" });
921
- const [token, setToken] = useState4("");
922
- const [saving, setSaving] = useState4(false);
923
- const [error, setError] = useState4(null);
924
- const save = useCallback4(async () => {
1235
+ const [token, setToken] = useState6("");
1236
+ const [saving, setSaving] = useState6(false);
1237
+ const [error, setError] = useState6(null);
1238
+ const [revoking, setRevoking] = useState6(false);
1239
+ const save = useCallback5(async () => {
925
1240
  if (!token.trim()) return;
926
1241
  setSaving(true);
927
1242
  setError(null);
@@ -938,45 +1253,73 @@ function TokenSetup({ onSaved, onCancel }) {
938
1253
  setSaving(false);
939
1254
  }
940
1255
  }, [client, token, onSaved]);
941
- return /* @__PURE__ */ jsx6(
942
- Dialog2,
1256
+ const revoke = useCallback5(async () => {
1257
+ setRevoking(true);
1258
+ setError(null);
1259
+ try {
1260
+ await client.delete(TOKEN_DOC_ID);
1261
+ onSaved();
1262
+ } catch (err) {
1263
+ setError(err instanceof Error ? err.message : "Failed to remove token");
1264
+ } finally {
1265
+ setRevoking(false);
1266
+ }
1267
+ }, [client, onSaved]);
1268
+ return /* @__PURE__ */ jsx10(
1269
+ Dialog,
943
1270
  {
944
1271
  header: "Connect Vercel API token",
945
- id: "token-setup",
1272
+ id: dialogId,
946
1273
  onClose: onCancel,
947
1274
  width: 1,
948
- footer: /* @__PURE__ */ jsxs5(Flex5, { padding: 3, gap: 2, justify: "flex-end", children: [
949
- onCancel && /* @__PURE__ */ jsx6(Button4, { text: "Cancel", mode: "ghost", onClick: onCancel, style: { cursor: "pointer" } }),
950
- /* @__PURE__ */ jsx6(
951
- Button4,
1275
+ footer: /* @__PURE__ */ jsxs7(Flex, { padding: 3, gap: 2, justify: hasToken ? "space-between" : "flex-end", children: [
1276
+ hasToken && /* @__PURE__ */ jsx10(
1277
+ Button,
952
1278
  {
953
- text: "Save and connect",
954
- tone: "primary",
955
- icon: CheckmarkCircleIcon,
956
- loading: saving,
957
- disabled: !token.trim() || saving,
958
- onClick: save,
1279
+ text: "Remove token",
1280
+ mode: "ghost",
1281
+ tone: "critical",
1282
+ icon: TrashIcon,
1283
+ loading: revoking,
1284
+ disabled: revoking || saving,
1285
+ onClick: revoke,
959
1286
  style: { cursor: "pointer" }
960
1287
  }
961
- )
1288
+ ),
1289
+ /* @__PURE__ */ jsxs7(Flex, { gap: 2, children: [
1290
+ onCancel && /* @__PURE__ */ jsx10(Button, { text: "Cancel", mode: "ghost", onClick: onCancel, style: { cursor: "pointer" } }),
1291
+ /* @__PURE__ */ jsx10(
1292
+ Button,
1293
+ {
1294
+ text: "Save and connect",
1295
+ tone: "primary",
1296
+ icon: CheckmarkCircleIcon,
1297
+ loading: saving,
1298
+ disabled: !token.trim() || saving,
1299
+ onClick: save,
1300
+ style: { cursor: "pointer" }
1301
+ }
1302
+ )
1303
+ ] })
962
1304
  ] }),
963
- children: /* @__PURE__ */ jsxs5(Stack, { space: 4, padding: 4, children: [
964
- /* @__PURE__ */ jsxs5(Stack, { space: 3, children: [
965
- /* @__PURE__ */ jsx6(Text4, { 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." }),
966
- /* @__PURE__ */ jsxs5(Text4, { size: 1, muted: true, children: [
1305
+ children: /* @__PURE__ */ jsxs7(Stack, { space: 4, padding: 4, children: [
1306
+ /* @__PURE__ */ jsxs7(Stack, { space: 3, children: [
1307
+ /* @__PURE__ */ jsx10(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." }),
1308
+ /* @__PURE__ */ jsxs7(Text, { size: 1, muted: true, children: [
967
1309
  "Create one at ",
968
- /* @__PURE__ */ jsx6("strong", { children: "vercel.com \u2192 Settings \u2192 Tokens" }),
1310
+ /* @__PURE__ */ jsx10("strong", { children: "vercel.com \u2192 Settings \u2192 Tokens" }),
969
1311
  " with",
970
1312
  " ",
971
- /* @__PURE__ */ jsx6("strong", { children: "Full Account" }),
1313
+ /* @__PURE__ */ jsx10("strong", { children: "Full Account" }),
972
1314
  " scope. The token is stored in your Sanity dataset and shared across all authenticated studio users."
973
1315
  ] })
974
1316
  ] }),
975
- /* @__PURE__ */ jsxs5(Stack, { space: 2, children: [
976
- /* @__PURE__ */ jsx6(Text4, { size: 1, weight: "semibold", children: "Vercel API Token" }),
977
- /* @__PURE__ */ jsx6(
1317
+ /* @__PURE__ */ jsxs7(Stack, { space: 2, children: [
1318
+ /* @__PURE__ */ jsx10(Label, { as: "label", size: 1, htmlFor: tokenId, children: "Vercel API Token" }),
1319
+ /* @__PURE__ */ jsx10(
978
1320
  TextInput,
979
1321
  {
1322
+ id: tokenId,
980
1323
  value: token,
981
1324
  onChange: (e) => setToken(e.target.value),
982
1325
  placeholder: "xxxxxxxxxxxxxxxxxxxxxxxx",
@@ -984,40 +1327,37 @@ function TokenSetup({ onSaved, onCancel }) {
984
1327
  }
985
1328
  )
986
1329
  ] }),
987
- error && /* @__PURE__ */ jsx6(Card4, { tone: "critical", padding: 3, radius: 2, children: /* @__PURE__ */ jsx6(Text4, { size: 1, children: error }) })
1330
+ error && /* @__PURE__ */ jsx10(Card, { tone: "critical", padding: 3, radius: 2, role: "alert", children: /* @__PURE__ */ jsx10(Text, { size: 1, children: error }) })
988
1331
  ] })
989
1332
  }
990
1333
  );
991
1334
  }
992
1335
 
993
1336
  // src/components/DeployTargetForm.tsx
994
- import { useState as useState5, useCallback as useCallback5 } from "react";
1337
+ import { useId as useId5, useState as useState7, useCallback as useCallback6 } from "react";
995
1338
  import { useClient as useClient2 } from "sanity";
996
- import {
997
- Dialog as Dialog3,
998
- Box as Box4,
999
- Flex as Flex6,
1000
- Text as Text5,
1001
- TextInput as TextInput2,
1002
- Button as Button5,
1003
- Switch,
1004
- Label,
1005
- Card as Card5
1006
- } from "@sanity/ui";
1007
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1339
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1008
1340
  var VERCEL_HOOK_RE2 = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\//;
1009
1341
  function DeployTargetForm({ initial, onSaved, onClose }) {
1010
1342
  const client = useClient2({ apiVersion: "2025-01-01" });
1011
1343
  const isEdit = Boolean(initial);
1012
- const [name, setName] = useState5(initial?.name ?? "");
1013
- const [url, setUrl] = useState5(initial?.url ?? "");
1014
- const [teamId, setTeamId] = useState5(initial?.teamId ?? "");
1015
- const [disableDelete, setDisableDelete] = useState5(initial?.disableDeleteAction ?? false);
1016
- const [saving, setSaving] = useState5(false);
1017
- const [error, setError] = useState5(null);
1344
+ const dialogId = useId5();
1345
+ const nameId = useId5();
1346
+ const urlId = useId5();
1347
+ const urlErrorId = useId5();
1348
+ const urlHelpId = useId5();
1349
+ const teamId_ = useId5();
1350
+ const teamHelpId = useId5();
1351
+ const disableId = useId5();
1352
+ const [name, setName] = useState7(initial?.name ?? "");
1353
+ const [url, setUrl] = useState7(initial?.url ?? "");
1354
+ const [teamId, setTeamId] = useState7(initial?.teamId ?? "");
1355
+ const [disableDelete, setDisableDelete] = useState7(initial?.disableDeleteAction ?? false);
1356
+ const [saving, setSaving] = useState7(false);
1357
+ const [error, setError] = useState7(null);
1018
1358
  const urlValid = !url || VERCEL_HOOK_RE2.test(url.trim());
1019
1359
  const canSave = name.trim() && url.trim() && urlValid;
1020
- const save = useCallback5(async () => {
1360
+ const save = useCallback6(async () => {
1021
1361
  if (!canSave) return;
1022
1362
  setSaving(true);
1023
1363
  setError(null);
@@ -1040,17 +1380,17 @@ function DeployTargetForm({ initial, onSaved, onClose }) {
1040
1380
  setSaving(false);
1041
1381
  }
1042
1382
  }, [canSave, isEdit, initial, client, name, url, teamId, disableDelete, onSaved]);
1043
- return /* @__PURE__ */ jsx7(
1044
- Dialog3,
1383
+ return /* @__PURE__ */ jsx11(
1384
+ Dialog,
1045
1385
  {
1046
1386
  header: isEdit ? `Edit "${initial?.name}"` : "Add deploy target",
1047
- id: "deploy-target-form",
1387
+ id: dialogId,
1048
1388
  onClose,
1049
1389
  width: 1,
1050
- footer: /* @__PURE__ */ jsxs6(Flex6, { padding: 3, gap: 2, justify: "flex-end", children: [
1051
- /* @__PURE__ */ jsx7(Button5, { text: "Cancel", mode: "ghost", onClick: onClose, style: { cursor: "pointer" } }),
1052
- /* @__PURE__ */ jsx7(
1053
- Button5,
1390
+ footer: /* @__PURE__ */ jsxs8(Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
1391
+ /* @__PURE__ */ jsx11(Button, { text: "Cancel", mode: "ghost", onClick: onClose, style: { cursor: "pointer" } }),
1392
+ /* @__PURE__ */ jsx11(
1393
+ Button,
1054
1394
  {
1055
1395
  text: isEdit ? "Save changes" : "Add target",
1056
1396
  tone: "primary",
@@ -1062,95 +1402,105 @@ function DeployTargetForm({ initial, onSaved, onClose }) {
1062
1402
  }
1063
1403
  )
1064
1404
  ] }),
1065
- children: /* @__PURE__ */ jsx7(Box4, { padding: 4, children: /* @__PURE__ */ jsxs6(Stack, { space: 4, children: [
1066
- /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1067
- /* @__PURE__ */ jsxs6(Label, { size: 1, children: [
1405
+ children: /* @__PURE__ */ jsx11(Box, { padding: 4, children: /* @__PURE__ */ jsxs8(Stack, { space: 4, children: [
1406
+ /* @__PURE__ */ jsxs8(Stack, { space: 2, children: [
1407
+ /* @__PURE__ */ jsxs8(Label, { as: "label", size: 1, htmlFor: nameId, children: [
1068
1408
  "Name ",
1069
- /* @__PURE__ */ jsx7("span", { style: { color: "var(--card-fg-color)" }, children: "*" })
1409
+ /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: "*" })
1070
1410
  ] }),
1071
- /* @__PURE__ */ jsx7(
1072
- TextInput2,
1411
+ /* @__PURE__ */ jsx11(
1412
+ TextInput,
1073
1413
  {
1414
+ id: nameId,
1415
+ required: true,
1416
+ "aria-required": "true",
1074
1417
  value: name,
1075
1418
  onChange: (e) => setName(e.target.value),
1076
1419
  placeholder: "Production"
1077
1420
  }
1078
1421
  )
1079
1422
  ] }),
1080
- /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1081
- /* @__PURE__ */ jsxs6(Label, { size: 1, children: [
1423
+ /* @__PURE__ */ jsxs8(Stack, { space: 2, children: [
1424
+ /* @__PURE__ */ jsxs8(Label, { as: "label", size: 1, htmlFor: urlId, children: [
1082
1425
  "Deploy hook URL ",
1083
- /* @__PURE__ */ jsx7("span", { style: { color: "var(--card-fg-color)" }, children: "*" })
1426
+ /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: "*" })
1084
1427
  ] }),
1085
- /* @__PURE__ */ jsx7(
1086
- TextInput2,
1428
+ /* @__PURE__ */ jsx11(
1429
+ TextInput,
1087
1430
  {
1431
+ id: urlId,
1432
+ required: true,
1433
+ "aria-required": "true",
1434
+ "aria-invalid": Boolean(url) && !urlValid,
1435
+ "aria-describedby": `${urlHelpId}${url && !urlValid ? ` ${urlErrorId}` : ""}`,
1088
1436
  value: url,
1089
1437
  onChange: (e) => setUrl(e.target.value),
1090
1438
  placeholder: "https://api.vercel.com/v1/integrations/deploy/\u2026"
1091
1439
  }
1092
1440
  ),
1093
- url && !urlValid && /* @__PURE__ */ jsx7(Text5, { 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)" }),
1094
- /* @__PURE__ */ jsx7(Text5, { size: 0, muted: true, children: "Vercel dashboard \u2192 Project \u2192 Settings \u2192 Git \u2192 Deploy Hooks" })
1441
+ url && !urlValid && /* @__PURE__ */ jsx11(Card, { tone: "critical", padding: 2, radius: 2, role: "alert", children: /* @__PURE__ */ jsx11(Text, { id: urlErrorId, size: 1, children: "Must be a Vercel deploy hook URL (api.vercel.com/v1/integrations/deploy/\u2026)" }) }),
1442
+ /* @__PURE__ */ jsx11(Text, { id: urlHelpId, size: 0, muted: true, children: "Vercel dashboard \u2192 Project \u2192 Settings \u2192 Git \u2192 Deploy Hooks" })
1095
1443
  ] }),
1096
- /* @__PURE__ */ jsxs6(Stack, { space: 2, children: [
1097
- /* @__PURE__ */ jsxs6(Label, { size: 1, children: [
1444
+ /* @__PURE__ */ jsxs8(Stack, { space: 2, children: [
1445
+ /* @__PURE__ */ jsxs8(Label, { as: "label", size: 1, htmlFor: teamId_, children: [
1098
1446
  "Team ID ",
1099
- /* @__PURE__ */ jsx7("span", { style: { opacity: 0.5, fontWeight: "normal" }, children: "\u2014 optional" })
1447
+ /* @__PURE__ */ jsx11("span", { style: { opacity: 0.5, fontWeight: "normal" }, children: "\u2014 optional" })
1100
1448
  ] }),
1101
- /* @__PURE__ */ jsx7(
1102
- TextInput2,
1449
+ /* @__PURE__ */ jsx11(
1450
+ TextInput,
1103
1451
  {
1452
+ id: teamId_,
1453
+ "aria-describedby": teamHelpId,
1104
1454
  value: teamId,
1105
1455
  onChange: (e) => setTeamId(e.target.value),
1106
1456
  placeholder: "team_xxxxxxxx"
1107
1457
  }
1108
1458
  ),
1109
- /* @__PURE__ */ jsxs6(Text5, { size: 0, muted: true, children: [
1459
+ /* @__PURE__ */ jsxs8(Text, { id: teamHelpId, size: 0, muted: true, children: [
1110
1460
  "Required for team-owned Vercel projects. Find it at Vercel \u2192 Settings \u2192 General \u2192 Team ID (starts with ",
1111
- /* @__PURE__ */ jsx7("code", { children: "team_" }),
1461
+ /* @__PURE__ */ jsx11("code", { children: "team_" }),
1112
1462
  ")."
1113
1463
  ] })
1114
1464
  ] }),
1115
- /* @__PURE__ */ jsxs6(Flex6, { align: "center", gap: 3, children: [
1116
- /* @__PURE__ */ jsx7(
1465
+ /* @__PURE__ */ jsxs8(Flex, { align: "center", gap: 3, children: [
1466
+ /* @__PURE__ */ jsx11(
1117
1467
  Switch,
1118
1468
  {
1119
1469
  checked: disableDelete,
1120
1470
  onChange: (e) => setDisableDelete(e.target.checked),
1121
- id: "disable-delete"
1471
+ id: disableId
1122
1472
  }
1123
1473
  ),
1124
- /* @__PURE__ */ jsxs6(Stack, { space: 1, children: [
1125
- /* @__PURE__ */ jsx7(Label, { as: "label", size: 1, htmlFor: "disable-delete", children: "Disable delete action" }),
1126
- /* @__PURE__ */ jsx7(Text5, { size: 0, muted: true, children: "Hides the delete button for this target in the studio." })
1474
+ /* @__PURE__ */ jsxs8(Stack, { space: 1, children: [
1475
+ /* @__PURE__ */ jsx11(Label, { as: "label", size: 1, htmlFor: disableId, children: "Disable delete action" }),
1476
+ /* @__PURE__ */ jsx11(Text, { size: 0, muted: true, children: "Hides the delete button for this target in the studio." })
1127
1477
  ] })
1128
1478
  ] }),
1129
- error && /* @__PURE__ */ jsx7(Card5, { tone: "critical", padding: 3, radius: 2, children: /* @__PURE__ */ jsx7(Text5, { size: 1, children: error }) })
1479
+ error && /* @__PURE__ */ jsx11(Card, { tone: "critical", padding: 3, radius: 2, children: /* @__PURE__ */ jsx11(Text, { size: 1, children: error }) })
1130
1480
  ] }) })
1131
1481
  }
1132
1482
  );
1133
1483
  }
1134
1484
 
1135
1485
  // src/version.ts
1136
- var VERSION = "1.1.1";
1486
+ var VERSION = "1.2.1";
1137
1487
 
1138
1488
  // src/components/DeployTool.tsx
1139
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1489
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1140
1490
  var TOKEN_QUERY = `*[_id == "config.vercelDeploy"][0].accessToken`;
1141
- var TARGETS_QUERY = `*[_type == "vercel_deploy"] | order(_createdAt asc)`;
1491
+ var TARGETS_QUERY = `*[_type == "vercel_deploy" && !(_id in path("drafts.**"))] | order(_createdAt asc)`;
1142
1492
  function DeployTool() {
1143
1493
  const client = useClient3({ apiVersion: "2025-01-01" });
1144
1494
  const toast = useToast();
1145
- const [token, setToken] = useState6(null);
1146
- const [targets, setTargets] = useState6([]);
1147
- const [loading, setLoading] = useState6(true);
1148
- const [showTokenSetup, setShowTokenSetup] = useState6(false);
1149
- const [showCreateForm, setShowCreateForm] = useState6(false);
1150
- const [pendingEdit, setPendingEdit] = useState6(null);
1151
- const [pendingDelete, setPendingDelete] = useState6(null);
1152
- const [deleting, setDeleting] = useState6(false);
1153
- const load = useCallback6(async () => {
1495
+ const [token, setToken] = useState8(null);
1496
+ const [targets, setTargets] = useState8([]);
1497
+ const [loading, setLoading] = useState8(true);
1498
+ const [showTokenSetup, setShowTokenSetup] = useState8(false);
1499
+ const [showCreateForm, setShowCreateForm] = useState8(false);
1500
+ const [pendingEdit, setPendingEdit] = useState8(null);
1501
+ const [pendingDelete, setPendingDelete] = useState8(null);
1502
+ const [deleting, setDeleting] = useState8(false);
1503
+ const load = useCallback7(async () => {
1154
1504
  setLoading(true);
1155
1505
  try {
1156
1506
  const [fetchedToken, fetchedTargets] = await Promise.all([
@@ -1165,11 +1515,20 @@ function DeployTool() {
1165
1515
  setLoading(false);
1166
1516
  }
1167
1517
  }, [client]);
1168
- useEffect4(() => {
1518
+ useEffect5(() => {
1169
1519
  load();
1170
1520
  }, [load]);
1171
- useEffect4(() => {
1172
- if (document.getElementById("dvfs-styles")) return;
1521
+ useEffect5(() => {
1522
+ const existing = document.getElementById("dvfs-styles");
1523
+ if (existing) {
1524
+ const n = Number(existing.dataset.refs ?? "1") + 1;
1525
+ existing.dataset.refs = String(n);
1526
+ return () => {
1527
+ const left = Number(existing.dataset.refs ?? "1") - 1;
1528
+ existing.dataset.refs = String(left);
1529
+ if (left <= 0) existing.remove();
1530
+ };
1531
+ }
1173
1532
  const style = document.createElement("style");
1174
1533
  style.id = "dvfs-styles";
1175
1534
  style.textContent = `
@@ -1190,11 +1549,14 @@ function DeployTool() {
1190
1549
  }
1191
1550
  `;
1192
1551
  document.head.appendChild(style);
1552
+ style.dataset.refs = "1";
1193
1553
  return () => {
1194
- document.getElementById("dvfs-styles")?.remove();
1554
+ const left = Number(style.dataset.refs ?? "1") - 1;
1555
+ style.dataset.refs = String(left);
1556
+ if (left <= 0) style.remove();
1195
1557
  };
1196
1558
  }, []);
1197
- useEffect4(() => {
1559
+ useEffect5(() => {
1198
1560
  const sub = client.listen(TARGETS_QUERY).subscribe(() => {
1199
1561
  client.fetch(TARGETS_QUERY).then(setTargets).catch((err) => {
1200
1562
  console.error("deploy-vercel-from-sanity: subscription refresh error", err);
@@ -1202,11 +1564,13 @@ function DeployTool() {
1202
1564
  });
1203
1565
  return () => sub.unsubscribe();
1204
1566
  }, [client]);
1205
- const confirmDelete = useCallback6(async () => {
1567
+ const confirmDelete = useCallback7(async () => {
1206
1568
  if (!pendingDelete) return;
1207
1569
  setDeleting(true);
1208
1570
  try {
1209
1571
  await client.delete(pendingDelete._id);
1572
+ await client.delete(`drafts.${pendingDelete._id}`).catch(() => {
1573
+ });
1210
1574
  setTargets((prev) => prev.filter((t) => t._id !== pendingDelete._id));
1211
1575
  toast.push({ status: "success", title: `Deleted "${pendingDelete.name}"` });
1212
1576
  } catch (err) {
@@ -1217,15 +1581,15 @@ function DeployTool() {
1217
1581
  }
1218
1582
  }, [client, pendingDelete, toast]);
1219
1583
  if (loading) {
1220
- return /* @__PURE__ */ jsx8(Card6, { height: "fill", tone: "transparent", children: /* @__PURE__ */ jsx8(Flex7, { align: "center", justify: "center", height: "fill", children: /* @__PURE__ */ jsx8(Spinner4, { muted: true }) }) });
1584
+ return /* @__PURE__ */ jsx12(Card, { height: "fill", tone: "transparent", children: /* @__PURE__ */ jsx12(Flex, { align: "center", justify: "center", height: "fill", children: /* @__PURE__ */ jsx12(Spinner, { muted: true }) }) });
1221
1585
  }
1222
- return /* @__PURE__ */ jsxs7(Card6, { height: "fill", tone: "transparent", children: [
1223
- /* @__PURE__ */ jsx8(Box5, { padding: 5, children: /* @__PURE__ */ jsxs7(Stack, { space: 5, children: [
1224
- /* @__PURE__ */ jsxs7(Flex7, { align: "center", justify: "space-between", className: "dvfs-header", children: [
1225
- /* @__PURE__ */ jsx8(Heading, { size: 2, children: "Deploy with Vercel" }),
1226
- /* @__PURE__ */ jsxs7(Flex7, { align: "center", gap: 3, className: "dvfs-header-actions", children: [
1227
- /* @__PURE__ */ jsx8(
1228
- Button6,
1586
+ return /* @__PURE__ */ jsxs9(Card, { height: "fill", tone: "transparent", children: [
1587
+ /* @__PURE__ */ jsx12(Box, { padding: 5, children: /* @__PURE__ */ jsxs9(Stack, { space: 5, children: [
1588
+ /* @__PURE__ */ jsxs9(Flex, { align: "center", justify: "space-between", className: "dvfs-header", children: [
1589
+ /* @__PURE__ */ jsx12(Heading, { size: 2, children: "Deploy with Vercel" }),
1590
+ /* @__PURE__ */ jsxs9(Flex, { align: "center", gap: 3, className: "dvfs-header-actions", children: [
1591
+ /* @__PURE__ */ jsx12(
1592
+ Button,
1229
1593
  {
1230
1594
  text: token ? "Token connected" : "Connect API token",
1231
1595
  mode: "ghost",
@@ -1236,8 +1600,8 @@ function DeployTool() {
1236
1600
  style: { cursor: "pointer" }
1237
1601
  }
1238
1602
  ),
1239
- /* @__PURE__ */ jsx8(
1240
- Button6,
1603
+ /* @__PURE__ */ jsx12(
1604
+ Button,
1241
1605
  {
1242
1606
  text: "Add target",
1243
1607
  mode: "ghost",
@@ -1249,13 +1613,13 @@ function DeployTool() {
1249
1613
  )
1250
1614
  ] })
1251
1615
  ] }),
1252
- !token && /* @__PURE__ */ jsx8(Card6, { padding: 4, radius: 2, tone: "caution", shadow: 1, children: /* @__PURE__ */ jsxs7(Flex7, { align: "center", justify: "space-between", gap: 4, children: [
1253
- /* @__PURE__ */ jsxs7(Stack, { space: 2, children: [
1254
- /* @__PURE__ */ jsx8(Text6, { size: 1, weight: "semibold", children: "Deploy status is not connected" }),
1255
- /* @__PURE__ */ jsx8(Text6, { 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." })
1616
+ !token && /* @__PURE__ */ jsx12(Card, { padding: 4, radius: 2, tone: "caution", shadow: 1, children: /* @__PURE__ */ jsxs9(Flex, { align: "center", justify: "space-between", gap: 4, children: [
1617
+ /* @__PURE__ */ jsxs9(Stack, { space: 2, children: [
1618
+ /* @__PURE__ */ jsx12(Text, { size: 1, weight: "semibold", children: "Deploy status is not connected" }),
1619
+ /* @__PURE__ */ jsx12(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." })
1256
1620
  ] }),
1257
- /* @__PURE__ */ jsx8(
1258
- Button6,
1621
+ /* @__PURE__ */ jsx12(
1622
+ Button,
1259
1623
  {
1260
1624
  text: "Connect",
1261
1625
  tone: "caution",
@@ -1265,16 +1629,16 @@ function DeployTool() {
1265
1629
  }
1266
1630
  )
1267
1631
  ] }) }),
1268
- targets.length === 0 && /* @__PURE__ */ jsx8(Card6, { padding: 5, radius: 2, tone: "transparent", shadow: 1, children: /* @__PURE__ */ jsxs7(Stack, { space: 4, style: { textAlign: "center" }, children: [
1269
- /* @__PURE__ */ jsx8(Text6, { size: 2, weight: "semibold", children: "No deploy targets configured" }),
1270
- /* @__PURE__ */ jsxs7(Text6, { size: 1, muted: true, children: [
1632
+ targets.length === 0 && /* @__PURE__ */ jsx12(Card, { padding: 5, radius: 2, tone: "transparent", shadow: 1, children: /* @__PURE__ */ jsxs9(Stack, { space: 4, style: { textAlign: "center" }, children: [
1633
+ /* @__PURE__ */ jsx12(Text, { size: 2, weight: "semibold", children: "No deploy targets configured" }),
1634
+ /* @__PURE__ */ jsxs9(Text, { size: 1, muted: true, children: [
1271
1635
  "Add a deploy target using the button above, or create a",
1272
1636
  " ",
1273
- /* @__PURE__ */ jsx8("code", { children: "vercel_deploy" }),
1637
+ /* @__PURE__ */ jsx12("code", { children: "vercel_deploy" }),
1274
1638
  " document directly in the dataset."
1275
1639
  ] }),
1276
- /* @__PURE__ */ jsx8(Flex7, { justify: "center", children: /* @__PURE__ */ jsx8(
1277
- Button6,
1640
+ /* @__PURE__ */ jsx12(Flex, { justify: "center", children: /* @__PURE__ */ jsx12(
1641
+ Button,
1278
1642
  {
1279
1643
  text: "Add deploy target",
1280
1644
  tone: "primary",
@@ -1284,12 +1648,12 @@ function DeployTool() {
1284
1648
  }
1285
1649
  ) })
1286
1650
  ] }) }),
1287
- targets.length > 0 && /* @__PURE__ */ jsx8("div", { className: "dvfs-grid", style: {
1651
+ targets.length > 0 && /* @__PURE__ */ jsx12("div", { className: "dvfs-grid", style: {
1288
1652
  display: "grid",
1289
1653
  gridTemplateColumns: "repeat(auto-fill, minmax(min(540px, 100%), 1fr))",
1290
1654
  gap: "16px",
1291
1655
  alignItems: "start"
1292
- }, children: targets.map((target) => /* @__PURE__ */ jsx8(
1656
+ }, children: targets.map((target) => /* @__PURE__ */ jsx12(
1293
1657
  DeployItem,
1294
1658
  {
1295
1659
  target,
@@ -1300,8 +1664,8 @@ function DeployTool() {
1300
1664
  target._id
1301
1665
  )) })
1302
1666
  ] }) }),
1303
- /* @__PURE__ */ jsx8(
1304
- Box5,
1667
+ /* @__PURE__ */ jsx12(
1668
+ Box,
1305
1669
  {
1306
1670
  style: {
1307
1671
  position: "fixed",
@@ -1311,23 +1675,24 @@ function DeployTool() {
1311
1675
  pointerEvents: "none",
1312
1676
  userSelect: "none"
1313
1677
  },
1314
- children: /* @__PURE__ */ jsxs7(Text6, { size: 0, muted: true, children: [
1678
+ children: /* @__PURE__ */ jsxs9(Text, { size: 0, muted: true, children: [
1315
1679
  "v",
1316
1680
  VERSION
1317
1681
  ] })
1318
1682
  }
1319
1683
  ),
1320
- showTokenSetup && /* @__PURE__ */ jsx8(
1684
+ showTokenSetup && /* @__PURE__ */ jsx12(
1321
1685
  TokenSetup,
1322
1686
  {
1323
1687
  onSaved: () => {
1324
1688
  setShowTokenSetup(false);
1325
1689
  load();
1326
1690
  },
1327
- onCancel: token ? () => setShowTokenSetup(false) : void 0
1691
+ onCancel: () => setShowTokenSetup(false),
1692
+ hasToken: Boolean(token)
1328
1693
  }
1329
1694
  ),
1330
- showCreateForm && /* @__PURE__ */ jsx8(
1695
+ showCreateForm && /* @__PURE__ */ jsx12(
1331
1696
  DeployTargetForm,
1332
1697
  {
1333
1698
  onSaved: () => {
@@ -1337,7 +1702,7 @@ function DeployTool() {
1337
1702
  onClose: () => setShowCreateForm(false)
1338
1703
  }
1339
1704
  ),
1340
- pendingEdit && /* @__PURE__ */ jsx8(
1705
+ pendingEdit && /* @__PURE__ */ jsx12(
1341
1706
  DeployTargetForm,
1342
1707
  {
1343
1708
  initial: pendingEdit,
@@ -1348,16 +1713,16 @@ function DeployTool() {
1348
1713
  onClose: () => setPendingEdit(null)
1349
1714
  }
1350
1715
  ),
1351
- pendingDelete && /* @__PURE__ */ jsx8(
1352
- Dialog4,
1716
+ pendingDelete && /* @__PURE__ */ jsx12(
1717
+ Dialog,
1353
1718
  {
1354
1719
  header: "Delete deploy target?",
1355
1720
  id: "confirm-delete",
1356
1721
  onClose: () => setPendingDelete(null),
1357
1722
  width: 1,
1358
- footer: /* @__PURE__ */ jsxs7(Flex7, { padding: 3, gap: 2, justify: "flex-end", children: [
1359
- /* @__PURE__ */ jsx8(
1360
- Button6,
1723
+ footer: /* @__PURE__ */ jsxs9(Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
1724
+ /* @__PURE__ */ jsx12(
1725
+ Button,
1361
1726
  {
1362
1727
  text: "Cancel",
1363
1728
  mode: "ghost",
@@ -1365,8 +1730,8 @@ function DeployTool() {
1365
1730
  style: { cursor: "pointer" }
1366
1731
  }
1367
1732
  ),
1368
- /* @__PURE__ */ jsx8(
1369
- Button6,
1733
+ /* @__PURE__ */ jsx12(
1734
+ Button,
1370
1735
  {
1371
1736
  text: "Delete",
1372
1737
  tone: "critical",
@@ -1378,26 +1743,59 @@ function DeployTool() {
1378
1743
  }
1379
1744
  )
1380
1745
  ] }),
1381
- children: /* @__PURE__ */ jsx8(Box5, { padding: 4, children: /* @__PURE__ */ jsxs7(Stack, { space: 3, children: [
1382
- /* @__PURE__ */ jsxs7(Flex7, { align: "center", gap: 2, children: [
1383
- /* @__PURE__ */ jsx8(WarningOutlineIcon, {}),
1384
- /* @__PURE__ */ jsx8(Text6, { size: 2, weight: "semibold", children: pendingDelete.name })
1746
+ children: /* @__PURE__ */ jsx12(Box, { padding: 4, children: /* @__PURE__ */ jsxs9(Stack, { space: 3, children: [
1747
+ /* @__PURE__ */ jsxs9(Flex, { align: "center", gap: 2, children: [
1748
+ /* @__PURE__ */ jsx12(WarningOutlineIcon, {}),
1749
+ /* @__PURE__ */ jsx12(Text, { size: 2, weight: "semibold", children: pendingDelete.name })
1385
1750
  ] }),
1386
- /* @__PURE__ */ jsx8(Text6, { size: 1, muted: true, children: "This removes the deploy target from the dataset. The Vercel deploy hook itself is not affected." })
1751
+ /* @__PURE__ */ jsx12(Text, { size: 1, muted: true, children: "This removes the deploy target from the dataset. The Vercel deploy hook itself is not affected." })
1387
1752
  ] }) })
1388
1753
  }
1389
1754
  ),
1390
- /* @__PURE__ */ jsx8(ToastViewport, {})
1755
+ /* @__PURE__ */ jsx12(ToastViewport, {})
1391
1756
  ] });
1392
1757
  }
1393
1758
 
1394
1759
  // src/schema/vercelDeploy.ts
1395
1760
  import { defineField, defineType } from "sanity";
1761
+
1762
+ // src/schema/schemaIcon.tsx
1763
+ import { forwardRef as forwardRef3 } from "react";
1764
+ import { jsx as jsx13 } from "react/jsx-runtime";
1765
+ var SchemaRocketIcon = forwardRef3(
1766
+ function SchemaRocketIcon2(props, ref) {
1767
+ return /* @__PURE__ */ jsx13(
1768
+ "svg",
1769
+ {
1770
+ width: "1em",
1771
+ height: "1em",
1772
+ viewBox: "0 0 25 25",
1773
+ fill: "none",
1774
+ xmlns: "http://www.w3.org/2000/svg",
1775
+ "aria-hidden": "true",
1776
+ focusable: "false",
1777
+ ...props,
1778
+ ref,
1779
+ children: /* @__PURE__ */ jsx13(
1780
+ "path",
1781
+ {
1782
+ d: "M12.5 20.5L15.5 14M11 9.49999L4.5 12.5M9 14C9 14 7.54688 14.9531 6.5 16C5.5 17 4.5 20.5 4.5 20.5C4.5 20.5 8 19.5 9 18.5C10 17.5 11 16 11 16M9 14C9 14 10.1 9.9 12.5 7.5C15.5 4.5 20.5 4.5 20.5 4.5C20.5 4.5 20.5 9.5 17.5 12.5C15.7492 14.2508 11 16 11 16L9 14ZM16.5 9.99999C16.5 10.8284 15.8284 11.5 15 11.5C14.1716 11.5 13.5 10.8284 13.5 9.99999C13.5 9.17157 14.1716 8.49999 15 8.49999C15.8284 8.49999 16.5 9.17157 16.5 9.99999Z",
1783
+ stroke: "currentColor",
1784
+ strokeWidth: 1.2,
1785
+ strokeLinejoin: "round"
1786
+ }
1787
+ )
1788
+ }
1789
+ );
1790
+ }
1791
+ );
1792
+
1793
+ // src/schema/vercelDeploy.ts
1396
1794
  var vercelDeploySchema = defineType({
1397
1795
  name: "vercel_deploy",
1398
1796
  title: "Deploy Target",
1399
1797
  type: "document",
1400
- icon: RocketIcon,
1798
+ icon: SchemaRocketIcon,
1401
1799
  fields: [
1402
1800
  defineField({
1403
1801
  name: "name",