@liiift-studio/deploy-vercel-from-sanity 1.2.0 → 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
@@ -9,10 +9,18 @@ import * as sanityUi from "@sanity/ui";
9
9
  import * as sanityIcons from "@sanity/icons";
10
10
  var UI = sanityUi;
11
11
  var ICONS = sanityIcons;
12
- function resolveExport(ns, name) {
12
+ function resolveComponent(ns, name) {
13
13
  const value = ns[name];
14
14
  return typeof value === "function" || typeof value === "object" && value !== null ? value : void 0;
15
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
+ }
16
24
  var STACK_USES_GAP = typeof UI.Stack === "function";
17
25
 
18
26
  // src/icons.tsx
@@ -21,11 +29,11 @@ var GLYPH = { width: "1em", height: "1em", viewBox: "0 0 25 25", fill: "none" };
21
29
  var MissingIcon = forwardRef(function MissingIcon2(props, ref) {
22
30
  return /* @__PURE__ */ jsx("svg", { ...GLYPH, xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", ...props, ref });
23
31
  });
24
- var SYMBOL_MAP = resolveExport(ICONS, "icons");
32
+ var SYMBOL_MAP = resolveRecord(ICONS, "icons");
25
33
  function resolveIcon(name, symbol) {
26
- const named = resolveExport(ICONS, name);
34
+ const named = resolveComponent(ICONS, name);
27
35
  if (named) return named;
28
- const Icon = resolveExport(ICONS, "Icon");
36
+ const Icon = resolveComponent(ICONS, "Icon");
29
37
  if (!Icon) return MissingIcon;
30
38
  if (SYMBOL_MAP && !(symbol in SYMBOL_MAP)) return MissingIcon;
31
39
  const Resolved = forwardRef(function SanityIcon(props, ref) {
@@ -63,21 +71,43 @@ import { createElement, forwardRef as forwardRef2 } from "react";
63
71
  import { jsx as jsx2 } from "react/jsx-runtime";
64
72
  function domFallback(tag) {
65
73
  const Fallback = forwardRef2(function SanityUiFallback(props, ref) {
66
- const { children, style, id, className, onClick, href, title, ...rest } = props;
74
+ const { children, style, id, className, onClick, href, title, as, ...rest } = props;
75
+ const element = typeof as === "string" ? as : tag;
67
76
  const passthrough = { style, id, className, onClick, href, title, ref };
68
- for (const key of ["role", "type", "value", "checked", "placeholder", "disabled", "onChange", "onKeyDown"]) {
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
+ ]) {
69
99
  if (key in rest) passthrough[key] = rest[key];
70
100
  }
71
101
  for (const key of Object.keys(rest)) {
72
102
  if (key.startsWith("aria-") || key.startsWith("data-")) passthrough[key] = rest[key];
73
103
  }
74
- return createElement(tag, passthrough, children);
104
+ return createElement(element, passthrough, children);
75
105
  });
76
106
  Fallback.displayName = `SanityUiFallback(${tag})`;
77
107
  return Fallback;
78
108
  }
79
109
  function primitive(name, tag) {
80
- return resolveExport(UI, name) ?? domFallback(tag);
110
+ return resolveComponent(UI, name) ?? domFallback(tag);
81
111
  }
82
112
  var Box = primitive("Box", "div");
83
113
  var Card = primitive("Card", "div");
@@ -136,11 +166,19 @@ function scheduleDismiss(id, status) {
136
166
  }
137
167
  function pushLocalToast(params) {
138
168
  const toast = { ...params, id: nextToastId++ };
139
- localToasts = [...localToasts, toast].slice(-MAX_VISIBLE_TOASTS);
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);
140
178
  emitToasts();
141
179
  scheduleDismiss(toast.id, toast.status);
142
180
  }
143
- var installedUseToast = resolveExport(UI, "useToast");
181
+ var installedUseToast = resolveFunction(UI, "useToast");
144
182
  var localToaster = { push: pushLocalToast };
145
183
  function useToast() {
146
184
  const real = installedUseToast;
@@ -157,6 +195,10 @@ function ToastViewport() {
157
195
  toastListeners.delete(setToasts);
158
196
  };
159
197
  }, []);
198
+ const resume = useCallback((toast, el) => {
199
+ if (el && el.contains(document.activeElement)) return;
200
+ scheduleDismiss(toast.id, toast.status);
201
+ }, []);
160
202
  const hold = useCallback((id) => {
161
203
  const timer = dismissTimers.get(id);
162
204
  if (timer) {
@@ -168,9 +210,8 @@ function ToastViewport() {
168
210
  return /* @__PURE__ */ jsx3(
169
211
  Box,
170
212
  {
171
- role: "status",
172
- "aria-live": "polite",
173
- "aria-atomic": false,
213
+ role: "log",
214
+ "aria-label": "Deployment notifications",
174
215
  style: {
175
216
  position: "fixed",
176
217
  bottom: 16,
@@ -185,11 +226,12 @@ function ToastViewport() {
185
226
  padding: 3,
186
227
  radius: 2,
187
228
  shadow: 3,
188
- tone: LOCAL_TOAST_TONE[toast.status ?? "info"] ?? "primary",
229
+ tone: LOCAL_TOAST_TONE[toast.status ?? "info"],
189
230
  style: { pointerEvents: "auto" },
190
231
  onMouseEnter: () => hold(toast.id),
191
232
  onFocusCapture: () => hold(toast.id),
192
- onMouseLeave: () => scheduleDismiss(toast.id, toast.status),
233
+ onMouseLeave: (e) => resume(toast, e.currentTarget),
234
+ onBlurCapture: (e) => resume(toast, e.currentTarget),
193
235
  children: /* @__PURE__ */ jsxs(Flex, { align: "flex-start", gap: 3, children: [
194
236
  /* @__PURE__ */ jsxs(Stack, { space: 2, flex: 1, children: [
195
237
  toast.title && /* @__PURE__ */ jsx3(Text, { size: 1, weight: "semibold", children: toast.title }),
@@ -215,50 +257,49 @@ function ToastViewport() {
215
257
  }
216
258
 
217
259
  // src/compat/tooltip.tsx
218
- import { useId, useState as useState2 } from "react";
260
+ import { cloneElement, isValidElement, useId, useState as useState2 } from "react";
219
261
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
220
- var InstalledTooltip = resolveExport(UI, "Tooltip");
262
+ var InstalledTooltip = resolveComponent(UI, "Tooltip");
221
263
  function Tooltip({ text, children }) {
222
264
  const id = useId();
223
265
  const [visible, setVisible] = useState2(false);
224
266
  if (InstalledTooltip) {
225
267
  return /* @__PURE__ */ jsx4(InstalledTooltip, { content: /* @__PURE__ */ jsx4(Box, { padding: 2, children: /* @__PURE__ */ jsx4(Text, { size: 1, children: text }) }), portal: true, children });
226
268
  }
269
+ const described = visible && isValidElement(children) ? cloneElement(children, { "aria-describedby": id }) : children;
227
270
  return /* @__PURE__ */ jsxs2(
228
271
  "span",
229
272
  {
230
273
  style: { position: "relative", display: "inline-flex" },
231
- "aria-describedby": id,
232
274
  onMouseEnter: () => setVisible(true),
233
275
  onMouseLeave: () => setVisible(false),
234
276
  onFocusCapture: () => setVisible(true),
235
277
  onBlurCapture: () => setVisible(false),
236
278
  onKeyDown: (e) => {
237
- if (e.key === "Escape") setVisible(false);
279
+ if (e.key === "Escape" && visible) {
280
+ e.stopPropagation();
281
+ setVisible(false);
282
+ }
238
283
  },
239
284
  children: [
240
- children,
241
- /* @__PURE__ */ jsx4(
242
- Card,
285
+ described,
286
+ visible && /* @__PURE__ */ jsx4(
287
+ "span",
243
288
  {
244
289
  id,
245
290
  role: "tooltip",
246
- radius: 2,
247
- shadow: 2,
248
- padding: 2,
249
291
  style: {
250
292
  position: "absolute",
251
293
  bottom: "100%",
252
294
  left: "50%",
253
295
  transform: "translateX(-50%)",
254
- marginBottom: 4,
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,
255
299
  whiteSpace: "nowrap",
256
- pointerEvents: "none",
257
- zIndex: 1e3,
258
- // Kept in the accessibility tree when hidden so `aria-describedby` still resolves.
259
- visibility: visible ? "visible" : "hidden"
300
+ zIndex: 1e3
260
301
  },
261
- children: /* @__PURE__ */ jsx4(Text, { size: 1, children: text })
302
+ children: /* @__PURE__ */ jsx4(Card, { radius: 2, shadow: 2, padding: 2, children: /* @__PURE__ */ jsx4(Text, { size: 1, children: text }) })
262
303
  }
263
304
  )
264
305
  ]
@@ -269,9 +310,9 @@ function Tooltip({ text, children }) {
269
310
  // src/compat/menu.tsx
270
311
  import { useCallback as useCallback2, useEffect as useEffect2, useId as useId2, useRef, useState as useState3 } from "react";
271
312
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
272
- var InstalledMenuButton = resolveExport(UI, "MenuButton");
273
- var InstalledMenu = resolveExport(UI, "Menu");
274
- var InstalledMenuItem = resolveExport(UI, "MenuItem");
313
+ var InstalledMenuButton = resolveComponent(UI, "MenuButton");
314
+ var InstalledMenu = resolveComponent(UI, "Menu");
315
+ var InstalledMenuItem = resolveComponent(UI, "MenuItem");
275
316
  var INSTALLED_MENU = InstalledMenuButton && InstalledMenu && InstalledMenuItem ? { MenuButton: InstalledMenuButton, Menu: InstalledMenu, MenuItem: InstalledMenuItem } : null;
276
317
  var itemKey = (item, index) => item.key ?? `${index}-${item.text}`;
277
318
  function ActionMenu({ id, label, items, buttonIcon }) {
@@ -299,7 +340,10 @@ function ActionMenu({ id, label, items, buttonIcon }) {
299
340
  useEffect2(() => {
300
341
  if (INSTALLED_MENU || !open) return;
301
342
  const onPointerDown = (e) => {
302
- if (!wrapRef.current?.contains(e.target)) 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();
303
347
  };
304
348
  document.addEventListener("mousedown", onPointerDown);
305
349
  return () => document.removeEventListener("mousedown", onPointerDown);
@@ -337,7 +381,20 @@ function ActionMenu({ id, label, items, buttonIcon }) {
337
381
  return;
338
382
  }
339
383
  if (e.key === "Tab") {
340
- close(false);
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
+ }
341
398
  return;
342
399
  }
343
400
  if (e.key === "ArrowDown") {
@@ -412,7 +469,6 @@ function ActionMenu({ id, label, items, buttonIcon }) {
412
469
  ref: (el) => {
413
470
  itemRefs.current[i] = el;
414
471
  },
415
- onMouseEnter: () => setActiveIndex(i),
416
472
  style: {
417
473
  display: "block",
418
474
  width: "100%",
@@ -437,15 +493,17 @@ function ActionMenu({ id, label, items, buttonIcon }) {
437
493
  href: item.href,
438
494
  target: "_blank",
439
495
  rel: "noreferrer",
440
- onClick: () => close(false),
496
+ onClick: () => {
497
+ setOpen(false);
498
+ triggerRef.current?.focus();
499
+ },
441
500
  children: content
442
501
  },
443
502
  itemKey(item, i)
444
503
  ) : /* @__PURE__ */ jsx5(
445
- "button",
504
+ "div",
446
505
  {
447
506
  ...shared,
448
- type: "button",
449
507
  onClick: () => runAction(item),
450
508
  children: content
451
509
  },
@@ -459,7 +517,7 @@ function ActionMenu({ id, label, items, buttonIcon }) {
459
517
 
460
518
  // src/compat/code.tsx
461
519
  import { jsx as jsx6 } from "react/jsx-runtime";
462
- var InstalledCode = resolveExport(UI, "Code");
520
+ var InstalledCode = resolveComponent(UI, "Code");
463
521
  var FALLBACK_CODE_STYLE = {
464
522
  display: "block",
465
523
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
@@ -633,9 +691,10 @@ function StatusBadge({ state, showSpinner }) {
633
691
  }
634
692
 
635
693
  // src/components/DeployHistory.tsx
636
- import { useEffect as useEffect3, useState as useState4, useCallback as useCallback3 } from "react";
694
+ import { useId as useId3, useEffect as useEffect3, useState as useState4, useCallback as useCallback3 } from "react";
637
695
  import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
638
696
  function DeployHistory({ target, token, onClose }) {
697
+ const dialogId = useId3();
639
698
  const [deployments, setDeployments] = useState4([]);
640
699
  const [loading, setLoading] = useState4(true);
641
700
  const [error, setError] = useState4(null);
@@ -659,7 +718,7 @@ function DeployHistory({ target, token, onClose }) {
659
718
  Dialog,
660
719
  {
661
720
  header: `${target.name} \u2014 Deployment History`,
662
- id: "deploy-history",
721
+ id: dialogId,
663
722
  onClose,
664
723
  width: 2,
665
724
  footer: /* @__PURE__ */ jsx8(Box, { padding: 3, children: /* @__PURE__ */ jsx8(Button, { text: "Close", icon: CloseIcon, mode: "ghost", onClick: onClose }) }),
@@ -747,8 +806,11 @@ function DeployItem({ target, token, onDelete, onEdit }) {
747
806
  const triggeredFromUidRef = useRef2(void 0);
748
807
  const requestSeqRef = useRef2(0);
749
808
  const mountedRef = useRef2(true);
750
- useEffect4(() => () => {
751
- mountedRef.current = false;
809
+ useEffect4(() => {
810
+ mountedRef.current = true;
811
+ return () => {
812
+ mountedRef.current = false;
813
+ };
752
814
  }, []);
753
815
  const latest = deployments[0];
754
816
  const isPending = pendingSince !== null;
@@ -974,17 +1036,36 @@ function DeployItem({ target, token, onDelete, onEdit }) {
974
1036
  formatDuration(Math.floor((latest.ready - latest.created) / 1e3)),
975
1037
  " to build"
976
1038
  ] }),
977
- latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx9(Fragment, { children: /* @__PURE__ */ jsx9(Tooltip, { text: copied ? "Copied!" : "Copy URL", children: /* @__PURE__ */ jsx9(
978
- Button,
979
- {
980
- mode: "ghost",
981
- icon: copied ? CheckmarkIcon : CopyIcon,
982
- padding: 1,
983
- tone: copied ? "positive" : "default",
984
- onClick: copyUrl,
985
- style: { cursor: "pointer" }
986
- }
987
- ) }) })
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
+ ] })
988
1069
  ] }),
989
1070
  /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, wrap: "wrap", children: [
990
1071
  commitMsg && /* @__PURE__ */ jsx9(
@@ -1035,7 +1116,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1035
1116
  deployError && /* @__PURE__ */ jsx9(Card, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ jsx9(Text, { size: 1, children: deployError }) })
1036
1117
  ] })
1037
1118
  ] }),
1038
- pollError && /* @__PURE__ */ jsx9(Card, { tone: "caution", padding: 3, radius: 2, role: "status", children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, children: [
1119
+ pollError && /* @__PURE__ */ jsx9(Card, { tone: "caution", padding: 3, radius: 2, children: /* @__PURE__ */ jsxs6(Flex, { align: "center", gap: 2, children: [
1039
1120
  /* @__PURE__ */ jsx9(WarningOutlineIcon, { "aria-hidden": "true" }),
1040
1121
  /* @__PURE__ */ jsxs6(Text, { size: 1, children: [
1041
1122
  "Status updates paused \u2014 ",
@@ -1143,16 +1224,18 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1143
1224
  }
1144
1225
 
1145
1226
  // src/components/TokenSetup.tsx
1146
- import { useId as useId3, useState as useState6, useCallback as useCallback5 } from "react";
1227
+ import { useId as useId4, useState as useState6, useCallback as useCallback5 } from "react";
1147
1228
  import { useClient } from "sanity";
1148
1229
  import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1149
1230
  var TOKEN_DOC_ID = "config.vercelDeploy";
1150
- function TokenSetup({ onSaved, onCancel }) {
1151
- const tokenId = useId3();
1231
+ function TokenSetup({ onSaved, onCancel, hasToken = false }) {
1232
+ const dialogId = useId4();
1233
+ const tokenId = useId4();
1152
1234
  const client = useClient({ apiVersion: "2025-01-01" });
1153
1235
  const [token, setToken] = useState6("");
1154
1236
  const [saving, setSaving] = useState6(false);
1155
1237
  const [error, setError] = useState6(null);
1238
+ const [revoking, setRevoking] = useState6(false);
1156
1239
  const save = useCallback5(async () => {
1157
1240
  if (!token.trim()) return;
1158
1241
  setSaving(true);
@@ -1170,27 +1253,54 @@ function TokenSetup({ onSaved, onCancel }) {
1170
1253
  setSaving(false);
1171
1254
  }
1172
1255
  }, [client, token, onSaved]);
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]);
1173
1268
  return /* @__PURE__ */ jsx10(
1174
1269
  Dialog,
1175
1270
  {
1176
1271
  header: "Connect Vercel API token",
1177
- id: "token-setup",
1272
+ id: dialogId,
1178
1273
  onClose: onCancel,
1179
1274
  width: 1,
1180
- footer: /* @__PURE__ */ jsxs7(Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
1181
- onCancel && /* @__PURE__ */ jsx10(Button, { text: "Cancel", mode: "ghost", onClick: onCancel, style: { cursor: "pointer" } }),
1182
- /* @__PURE__ */ jsx10(
1275
+ footer: /* @__PURE__ */ jsxs7(Flex, { padding: 3, gap: 2, justify: hasToken ? "space-between" : "flex-end", children: [
1276
+ hasToken && /* @__PURE__ */ jsx10(
1183
1277
  Button,
1184
1278
  {
1185
- text: "Save and connect",
1186
- tone: "primary",
1187
- icon: CheckmarkCircleIcon,
1188
- loading: saving,
1189
- disabled: !token.trim() || saving,
1190
- 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,
1191
1286
  style: { cursor: "pointer" }
1192
1287
  }
1193
- )
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
+ ] })
1194
1304
  ] }),
1195
1305
  children: /* @__PURE__ */ jsxs7(Stack, { space: 4, padding: 4, children: [
1196
1306
  /* @__PURE__ */ jsxs7(Stack, { space: 3, children: [
@@ -1224,20 +1334,21 @@ function TokenSetup({ onSaved, onCancel }) {
1224
1334
  }
1225
1335
 
1226
1336
  // src/components/DeployTargetForm.tsx
1227
- import { useId as useId4, useState as useState7, useCallback as useCallback6 } from "react";
1337
+ import { useId as useId5, useState as useState7, useCallback as useCallback6 } from "react";
1228
1338
  import { useClient as useClient2 } from "sanity";
1229
1339
  import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1230
1340
  var VERCEL_HOOK_RE2 = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\//;
1231
1341
  function DeployTargetForm({ initial, onSaved, onClose }) {
1232
1342
  const client = useClient2({ apiVersion: "2025-01-01" });
1233
1343
  const isEdit = Boolean(initial);
1234
- const nameId = useId4();
1235
- const urlId = useId4();
1236
- const urlErrorId = useId4();
1237
- const urlHelpId = useId4();
1238
- const teamId_ = useId4();
1239
- const teamHelpId = useId4();
1240
- const disableId = useId4();
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();
1241
1352
  const [name, setName] = useState7(initial?.name ?? "");
1242
1353
  const [url, setUrl] = useState7(initial?.url ?? "");
1243
1354
  const [teamId, setTeamId] = useState7(initial?.teamId ?? "");
@@ -1273,7 +1384,7 @@ function DeployTargetForm({ initial, onSaved, onClose }) {
1273
1384
  Dialog,
1274
1385
  {
1275
1386
  header: isEdit ? `Edit "${initial?.name}"` : "Add deploy target",
1276
- id: "deploy-target-form",
1387
+ id: dialogId,
1277
1388
  onClose,
1278
1389
  width: 1,
1279
1390
  footer: /* @__PURE__ */ jsxs8(Flex, { padding: 3, gap: 2, justify: "flex-end", children: [
@@ -1372,7 +1483,7 @@ function DeployTargetForm({ initial, onSaved, onClose }) {
1372
1483
  }
1373
1484
 
1374
1485
  // src/version.ts
1375
- var VERSION = "1.2.0";
1486
+ var VERSION = "1.2.1";
1376
1487
 
1377
1488
  // src/components/DeployTool.tsx
1378
1489
  import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
@@ -1577,7 +1688,8 @@ function DeployTool() {
1577
1688
  setShowTokenSetup(false);
1578
1689
  load();
1579
1690
  },
1580
- onCancel: () => setShowTokenSetup(false)
1691
+ onCancel: () => setShowTokenSetup(false),
1692
+ hasToken: Boolean(token)
1581
1693
  }
1582
1694
  ),
1583
1695
  showCreateForm && /* @__PURE__ */ jsx12(
@@ -1724,37 +1836,13 @@ var vercelDeploySchema = defineType({
1724
1836
  }
1725
1837
  });
1726
1838
 
1727
- // src/schema/vercelConfig.ts
1728
- import { defineField as defineField2, defineType as defineType2 } from "sanity";
1729
- var vercelConfigSchema = defineType2({
1730
- name: "vercelDeploy.config",
1731
- title: "Vercel Deploy Configuration",
1732
- type: "document",
1733
- fields: [
1734
- defineField2({
1735
- name: "accessToken",
1736
- title: "Vercel API Token",
1737
- type: "string",
1738
- description: "Readable by anyone who can read this dataset. Delete this document to revoke the stored token."
1739
- })
1740
- ],
1741
- preview: {
1742
- select: { token: "accessToken" },
1743
- prepare: ({ token }) => ({
1744
- title: "Vercel API Token",
1745
- // Never render the secret itself in a preview.
1746
- subtitle: token ? "Connected" : "Not set"
1747
- })
1748
- }
1749
- });
1750
-
1751
1839
  // src/index.ts
1752
1840
  var vercelDeploy = definePlugin((options) => {
1753
1841
  const config = options ?? {};
1754
1842
  return {
1755
1843
  name: "deploy-vercel-from-sanity",
1756
1844
  schema: {
1757
- types: [vercelDeploySchema, vercelConfigSchema]
1845
+ types: [vercelDeploySchema]
1758
1846
  },
1759
1847
  tools: [
1760
1848
  {
@@ -1767,7 +1855,6 @@ var vercelDeploy = definePlugin((options) => {
1767
1855
  };
1768
1856
  });
1769
1857
  export {
1770
- vercelConfigSchema,
1771
1858
  vercelDeploy,
1772
1859
  vercelDeploySchema
1773
1860
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liiift-studio/deploy-vercel-from-sanity",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Sanity Studio plugin — trigger and monitor Vercel deployments with full status, history, and build logs. Supports Studio v3.30 through v6.",
5
5
  "license": "MIT",
6
6
  "author": "Liiift Studio",
@@ -22,16 +22,20 @@
22
22
  "types": "./dist/index.d.ts",
23
23
  "exports": {
24
24
  ".": {
25
- "types": "./dist/index.d.ts",
26
- "import": "./dist/index.mjs",
27
- "require": "./dist/index.js",
25
+ "import": {
26
+ "types": "./dist/index.d.mts",
27
+ "default": "./dist/index.mjs"
28
+ },
29
+ "require": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
28
33
  "default": "./dist/index.mjs"
29
34
  },
30
35
  "./package.json": "./package.json"
31
36
  },
32
37
  "files": [
33
- "dist",
34
- "src"
38
+ "dist"
35
39
  ],
36
40
  "scripts": {
37
41
  "build": "tsup",
@@ -43,7 +47,7 @@
43
47
  "@sanity/ui": ">=2 <5",
44
48
  "react": ">=18",
45
49
  "react-dom": ">=18",
46
- "sanity": ">=3.30"
50
+ "sanity": ">=3.30 <7"
47
51
  },
48
52
  "devDependencies": {
49
53
  "@sanity/icons": "^5",
@@ -62,6 +66,6 @@
62
66
  },
63
67
  "sideEffects": true,
64
68
  "engines": {
65
- "node": ">=20.19"
69
+ "node": ">=20.19 <22 || >=22.12"
66
70
  }
67
71
  }
@@ -1,29 +0,0 @@
1
- // Monospace block — Studio's Code where available, a styled <code> block otherwise
2
- import type { CSSProperties, ComponentType, ReactNode } from 'react'
3
- import { UI, resolveExport } from './resolve'
4
-
5
- /** The real Code when the installed @sanity/ui still exports it, otherwise undefined. */
6
- const InstalledCode = resolveExport<ComponentType<{
7
- size?: number
8
- style?: CSSProperties
9
- children: ReactNode
10
- }>>(UI, 'Code')
11
-
12
- /**
13
- * Styling for the fallback Code element, approximating @sanity/ui's `size={1}`.
14
- * `display: block` is included deliberately — `<code>` is inline by default while
15
- * upstream's Code renders a block, so omitting it would concatenate every line.
16
- */
17
- const FALLBACK_CODE_STYLE: CSSProperties = {
18
- display: 'block',
19
- fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
20
- fontSize: '0.8125rem',
21
- lineHeight: 1.4,
22
- margin: 0,
23
- }
24
-
25
- /** Monospace block. Uses Studio's Code where available, a plain `<code>` on @sanity/ui v4+. */
26
- export function Code({ style, children }: { style?: CSSProperties; children: ReactNode }): React.JSX.Element {
27
- if (InstalledCode) return <InstalledCode size={1} style={style}>{children}</InstalledCode>
28
- return <code style={{ ...FALLBACK_CODE_STYLE, ...style }}>{children}</code>
29
- }
@@ -1,14 +0,0 @@
1
- // Single entry point for every @sanity/ui value this plugin uses, resolved against the installed major
2
- export {
3
- Box, Card, Flex, Grid, Text, Heading, Label, Badge, Spinner,
4
- Button, TextInput, Select, Switch, Dialog, Stack,
5
- } from './primitives'
6
- export type { StackProps } from './primitives'
7
- export { useToast, ToastViewport } from './toast'
8
- export type { ToastParams, Toaster } from './toast'
9
- export { Tooltip } from './tooltip'
10
- export type { TooltipProps } from './tooltip'
11
- export { ActionMenu } from './menu'
12
- export type { ActionMenuProps, MenuAction } from './menu'
13
- export { Code } from './code'
14
- export { STACK_USES_GAP } from './resolve'