@liiift-studio/sanity-font-manager 2.5.0 → 2.5.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.
@@ -3460,8 +3460,8 @@ var require_unbrotli = __commonJS({
3460
3460
  });
3461
3461
 
3462
3462
  // src/components/UploadModal.jsx
3463
- import React9, { useReducer as useReducer2, useCallback as useCallback5, useState as useState6, useMemo as useMemo6, useRef as useRef3, useEffect as useEffect4 } from "react";
3464
- import { Dialog, Box as Box8, Flex as Flex9, Text as Text9, Badge as Badge7, Button as Button7 } from "@sanity/ui";
3463
+ import React10, { useReducer as useReducer2, useCallback as useCallback6, useState as useState7, useMemo as useMemo7, useRef as useRef3, useEffect as useEffect5 } from "react";
3464
+ import { Dialog, Box as Box9, Flex as Flex10, Text as Text10, Badge as Badge8, Button as Button8 } from "@sanity/ui";
3465
3465
 
3466
3466
  // src/utils/planTypes.js
3467
3467
  var FONT_STATUS = {
@@ -4488,14 +4488,14 @@ var extractFontMetadata = (font, title, weightKeywordList, italicKeywordList, pr
4488
4488
  weightName = expandAbbreviations(weightName);
4489
4489
  }
4490
4490
  const fullName = getNameString(font, 4) || (ttfFallbackMeta == null ? void 0 : ttfFallbackMeta.fullName) || "";
4491
- if ((weightName === "" || weightName.toLowerCase() === "roman") && fullName) {
4491
+ const axes = getVariationAxes(font);
4492
+ const variableFont = axes !== null;
4493
+ if (!variableFont && (weightName === "" || weightName.toLowerCase() === "roman") && fullName) {
4492
4494
  weightName = extractWeightFromFullName(font, title, ttfFallbackMeta);
4493
4495
  if (!preserveShortenedNames) {
4494
4496
  weightName = expandAbbreviations(weightName);
4495
4497
  }
4496
4498
  }
4497
- const axes = getVariationAxes(font);
4498
- const variableFont = axes !== null;
4499
4499
  const trimmedTitle = title.trim();
4500
4500
  const nameId4Remainder = fullName ? fullName.replace(trimmedTitle, "").trim() : "";
4501
4501
  const nameId1 = getNameString(font, 1) || (ttfFallbackMeta == null ? void 0 : ttfFallbackMeta.familyName) || "";
@@ -4779,6 +4779,7 @@ async function buildUploadPlan({
4779
4779
  onProgress
4780
4780
  }) {
4781
4781
  const plan = createEmptyPlan(settings);
4782
+ plan.settings.typefaceTitle = typefaceTitle;
4782
4783
  plan.phase = PLAN_PHASE.PROCESSING;
4783
4784
  plan.processingProgress.total = files.length;
4784
4785
  for (let i = 0; i < files.length; i++) {
@@ -5302,10 +5303,11 @@ function ExistingDocumentResolver({ decision, tempId, dispatch }) {
5302
5303
  // src/components/FontReviewCard.jsx
5303
5304
  var STANDARD_TYPES = ["ttf", "otf", "woff", "woff2"];
5304
5305
  var EXTENDED_TYPES = ["eot", "svg", "css", "woff2_subset", "woff2_web"];
5305
- var FontReviewCard = memo(function FontReviewCard2({ entry, dispatch, allExpanded }) {
5306
+ var FontReviewCard = memo(function FontReviewCard2({ entry, dispatch, allExpanded, typefaceTitle, price }) {
5306
5307
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
5307
5308
  const [expanded, setExpanded] = useState2(false);
5308
5309
  const [showAllFileTypes, setShowAllFileTypes] = useState2(false);
5310
+ const [showDocPreview, setShowDocPreview] = useState2(false);
5309
5311
  useEffect(() => {
5310
5312
  setExpanded(allExpanded);
5311
5313
  }, [allExpanded]);
@@ -5513,7 +5515,32 @@ var FontReviewCard = memo(function FontReviewCard2({ entry, dispatch, allExpande
5513
5515
  tempId: entry.tempId,
5514
5516
  dispatch
5515
5517
  }
5516
- ), /* @__PURE__ */ React3.createElement(Flex3, { justify: "flex-end", gap: 2 }, hasUserOverrides && /* @__PURE__ */ React3.createElement(
5518
+ ), /* @__PURE__ */ React3.createElement(Stack3, { space: 2 }, /* @__PURE__ */ React3.createElement(
5519
+ Button3,
5520
+ {
5521
+ mode: "bleed",
5522
+ fontSize: 0,
5523
+ padding: 1,
5524
+ text: showDocPreview ? "Hide document preview" : "Show document preview",
5525
+ onClick: () => setShowDocPreview((v) => !v),
5526
+ style: { cursor: "pointer", alignSelf: "flex-start" }
5527
+ }
5528
+ ), showDocPreview && /* @__PURE__ */ React3.createElement(Card3, { border: true, padding: 3, radius: 1, style: { fontFamily: "monospace", fontSize: 12 } }, /* @__PURE__ */ React3.createElement(Stack3, { space: 2 }, [
5529
+ ["_id", entry.documentId],
5530
+ ["_type", "font"],
5531
+ ["title", entry.title],
5532
+ ["slug", entry.documentId],
5533
+ ["typefaceName", typefaceTitle || "\u2014"],
5534
+ ["weightName", entry.weightName || "\u2014"],
5535
+ ["weight", entry.weight],
5536
+ ["style", entry.style],
5537
+ ["subfamily", entry.subfamily || "\u2014"],
5538
+ ["variableFont", String(entry.variableFont)],
5539
+ ["price", price ?? "\u2014"],
5540
+ ["sell", price > 0 ? "true" : "false"],
5541
+ ["normalWeight", "true"],
5542
+ ["files", (entry.files || []).map((f) => f.name).join(", ") || "\u2014"]
5543
+ ].map(([key, value]) => /* @__PURE__ */ React3.createElement(Flex3, { key, gap: 2 }, /* @__PURE__ */ React3.createElement(Text3, { size: 0, muted: true, style: { width: 120, flexShrink: 0 } }, key), /* @__PURE__ */ React3.createElement(Text3, { size: 0, style: { wordBreak: "break-all" } }, String(value))))))), /* @__PURE__ */ React3.createElement(Flex3, { justify: "flex-end", gap: 2 }, hasUserOverrides && /* @__PURE__ */ React3.createElement(
5517
5544
  Button3,
5518
5545
  {
5519
5546
  mode: "ghost",
@@ -5922,15 +5949,20 @@ function UploadStep2Review({
5922
5949
  " ",
5923
5950
  sortBy === col.key ? sortDir === "asc" ? "\u2191" : "\u2193" : ""
5924
5951
  ))
5925
- ), Object.entries(groupedEntries).map(([subfamily, entries]) => /* @__PURE__ */ React6.createElement(Stack4, { key: subfamily, space: 1 }, /* @__PURE__ */ React6.createElement(Card4, { padding: 2, radius: 1, style: { background: "var(--card-muted-bg-color)" } }, /* @__PURE__ */ React6.createElement(Flex6, { align: "center", gap: 2 }, /* @__PURE__ */ React6.createElement(Text6, { size: 1, weight: "semibold" }, subfamily), /* @__PURE__ */ React6.createElement(Badge4, { mode: "outline", fontSize: 0 }, entries.length))), /* @__PURE__ */ React6.createElement(Stack4, { space: 0 }, entries.map((entry) => /* @__PURE__ */ React6.createElement(
5926
- FontReviewCard_default,
5927
- {
5928
- key: entry.tempId,
5929
- entry,
5930
- dispatch,
5931
- allExpanded
5932
- }
5933
- ))))), visibleEntries.length === 0 && fontEntries.length > 0 && /* @__PURE__ */ React6.createElement(Card4, { border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React6.createElement(Text6, { size: 1, muted: true, align: "center" }, "No fonts match the current filter")), isReviewing && validationErrors.length > 0 && /* @__PURE__ */ React6.createElement(Card4, { tone: "caution", border: true, padding: 2, radius: 2 }, /* @__PURE__ */ React6.createElement(Stack4, { space: 1 }, validationErrors.map((err, i) => /* @__PURE__ */ React6.createElement(Text6, { key: i, size: 0, tone: "caution" }, "\u2022 ", err)))), isReviewing && processedCount > 0 && /* @__PURE__ */ React6.createElement(Flex6, { justify: "flex-end", gap: 2, style: { position: "sticky", bottom: 0, background: "var(--card-bg-color)", paddingTop: 8, paddingBottom: 4 } }, /* @__PURE__ */ React6.createElement(
5952
+ ), Object.entries(groupedEntries).map(([subfamily, entries]) => /* @__PURE__ */ React6.createElement(Stack4, { key: subfamily, space: 1 }, /* @__PURE__ */ React6.createElement(Card4, { padding: 2, radius: 1, style: { background: "var(--card-muted-bg-color)" } }, /* @__PURE__ */ React6.createElement(Flex6, { align: "center", gap: 2 }, /* @__PURE__ */ React6.createElement(Text6, { size: 1, weight: "semibold" }, subfamily), /* @__PURE__ */ React6.createElement(Badge4, { mode: "outline", fontSize: 0 }, entries.length))), /* @__PURE__ */ React6.createElement(Stack4, { space: 0 }, entries.map((entry) => {
5953
+ var _a2, _b2;
5954
+ return /* @__PURE__ */ React6.createElement(
5955
+ FontReviewCard_default,
5956
+ {
5957
+ key: entry.tempId,
5958
+ entry,
5959
+ dispatch,
5960
+ allExpanded,
5961
+ typefaceTitle: (_a2 = plan.settings) == null ? void 0 : _a2.typefaceTitle,
5962
+ price: (_b2 = plan.settings) == null ? void 0 : _b2.price
5963
+ }
5964
+ );
5965
+ })))), visibleEntries.length === 0 && fontEntries.length > 0 && /* @__PURE__ */ React6.createElement(Card4, { border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React6.createElement(Text6, { size: 1, muted: true, align: "center" }, "No fonts match the current filter")), isReviewing && validationErrors.length > 0 && /* @__PURE__ */ React6.createElement(Card4, { tone: "caution", border: true, padding: 2, radius: 2 }, /* @__PURE__ */ React6.createElement(Stack4, { space: 1 }, validationErrors.map((err, i) => /* @__PURE__ */ React6.createElement(Text6, { key: i, size: 0, tone: "caution" }, "\u2022 ", err)))), isReviewing && processedCount > 0 && /* @__PURE__ */ React6.createElement(Flex6, { justify: "flex-end", gap: 2, style: { position: "sticky", bottom: 0, background: "var(--card-bg-color)", paddingTop: 8, paddingBottom: 4 } }, /* @__PURE__ */ React6.createElement(
5934
5966
  Button5,
5935
5967
  {
5936
5968
  mode: "default",
@@ -6168,6 +6200,169 @@ async function generateFontData({ fileInput, url, fontKit, fontId, client, commi
6168
6200
 
6169
6201
  // src/utils/parseVariableFontInstances.js
6170
6202
  import { nanoid as nanoid3 } from "nanoid";
6203
+ var WIDTH_PREFIXES = [
6204
+ "XXXWide",
6205
+ "XXWide",
6206
+ "XWide",
6207
+ "Wide",
6208
+ "XXXNarrow",
6209
+ "XXNarrow",
6210
+ "XNarrow",
6211
+ "Narrow"
6212
+ ];
6213
+ function parseInstanceName(instanceName) {
6214
+ let subfamily = "";
6215
+ let remaining = instanceName.trim();
6216
+ for (const prefix of WIDTH_PREFIXES) {
6217
+ if (remaining.toLowerCase().startsWith(prefix.toLowerCase() + " ") || remaining.toLowerCase() === prefix.toLowerCase()) {
6218
+ subfamily = prefix;
6219
+ remaining = remaining.substring(prefix.length).trim();
6220
+ break;
6221
+ }
6222
+ }
6223
+ let style = "";
6224
+ for (const suffix of ["Backslant", "Slant", "Italic", "Oblique"]) {
6225
+ if (remaining.toLowerCase().endsWith(" " + suffix.toLowerCase()) || remaining.toLowerCase() === suffix.toLowerCase()) {
6226
+ style = suffix;
6227
+ remaining = remaining.substring(0, remaining.length - suffix.length).trim();
6228
+ break;
6229
+ }
6230
+ }
6231
+ return { subfamily, weight: remaining || "Regular", style };
6232
+ }
6233
+ function filterBySubfamily(staticFonts, instanceSubfamily, typefaceName) {
6234
+ if (!instanceSubfamily) {
6235
+ return staticFonts.filter((sf) => {
6236
+ const sub = (sf.subfamily || "").toLowerCase();
6237
+ if (sub === "" || sub === "regular") return true;
6238
+ const afterTypeface = (sf.title || "").replace(typefaceName, "").trim();
6239
+ return !WIDTH_PREFIXES.some((p) => afterTypeface.toLowerCase().startsWith(p.toLowerCase()));
6240
+ });
6241
+ }
6242
+ const lowerSf = instanceSubfamily.toLowerCase();
6243
+ const expanded = (expandAbbreviations(instanceSubfamily) || "").toLowerCase();
6244
+ return staticFonts.filter((sf) => {
6245
+ const sub = (sf.subfamily || "").toLowerCase();
6246
+ if (sub === lowerSf || expanded && sub === expanded) return true;
6247
+ const afterTypeface = (sf.title || "").replace(typefaceName, "").trim().toLowerCase();
6248
+ if (afterTypeface.startsWith(lowerSf)) return true;
6249
+ if (expanded && afterTypeface.startsWith(expanded)) return true;
6250
+ return false;
6251
+ });
6252
+ }
6253
+ var WEIGHT_MAP = [
6254
+ { term: "ultra", weight: 950 },
6255
+ { term: "xxlight", weight: 200 },
6256
+ { term: "xlight", weight: 250 },
6257
+ { term: "extralight", weight: 200 },
6258
+ { term: "extra light", weight: 200 },
6259
+ { term: "thin", weight: 100 },
6260
+ { term: "hairline", weight: 100 },
6261
+ { term: "light", weight: 300 },
6262
+ { term: "regular", weight: 400 },
6263
+ { term: "normal", weight: 400 },
6264
+ { term: "medium", weight: 500 },
6265
+ { term: "semibold", weight: 600 },
6266
+ { term: "semi bold", weight: 600 },
6267
+ { term: "extrabold", weight: 800 },
6268
+ { term: "extra bold", weight: 800 },
6269
+ { term: "xbold", weight: 800 },
6270
+ { term: "bold", weight: 700 },
6271
+ { term: "black", weight: 900 },
6272
+ { term: "heavy", weight: 900 }
6273
+ ];
6274
+ function weightFromName(name) {
6275
+ const lower = name.toLowerCase();
6276
+ for (const { term, weight } of WEIGHT_MAP) {
6277
+ if (lower === term || lower.includes(term)) return weight;
6278
+ }
6279
+ return 400;
6280
+ }
6281
+ var STRATEGIES = [
6282
+ // Pass 1: Exact title match (with typeface prefix)
6283
+ {
6284
+ name: "exact-title",
6285
+ match: (instanceName, parsed, candidates, typefaceName) => {
6286
+ const withPrefix = `${typefaceName} ${instanceName}`;
6287
+ return candidates.find((sf) => sf.title === instanceName || sf.title === withPrefix) || null;
6288
+ }
6289
+ },
6290
+ // Pass 2: Title normalisation — strip typeface name and compare remainder
6291
+ {
6292
+ name: "title-normalised",
6293
+ match: (instanceName, parsed, candidates, typefaceName) => {
6294
+ return candidates.find((sf) => {
6295
+ const sfName = (sf.title || "").replace(typefaceName, "").trim();
6296
+ if (sfName.toLowerCase() === instanceName.toLowerCase()) return true;
6297
+ if (parsed.weight === "Regular" && !parsed.style) {
6298
+ if (sfName.toLowerCase() === parsed.subfamily.toLowerCase()) return true;
6299
+ }
6300
+ return false;
6301
+ }) || null;
6302
+ }
6303
+ },
6304
+ // Pass 3: Abbreviation expansion (XLight → ExtraLight, XBold → ExtraBold)
6305
+ {
6306
+ name: "abbreviation",
6307
+ match: (instanceName, parsed, candidates, typefaceName) => {
6308
+ const expandedFull = instanceName.split(" ").map((w) => expandAbbreviations(w) || w).join(" ");
6309
+ let found = candidates.find((sf) => {
6310
+ const sfName = (sf.title || "").replace(typefaceName, "").trim();
6311
+ return sfName.toLowerCase() === expandedFull.toLowerCase();
6312
+ });
6313
+ if (found) return found;
6314
+ const expandedWeight = expandAbbreviations(parsed.weight) || parsed.weight;
6315
+ const target = [parsed.subfamily, expandedWeight, parsed.style].filter(Boolean).join(" ");
6316
+ return candidates.find((sf) => {
6317
+ const sfName = (sf.title || "").replace(typefaceName, "").trim();
6318
+ return sfName.toLowerCase() === target.toLowerCase();
6319
+ }) || null;
6320
+ }
6321
+ },
6322
+ // Pass 4: fullName metadata comparison
6323
+ {
6324
+ name: "metadata-fullName",
6325
+ match: (instanceName, parsed, candidates, typefaceName) => {
6326
+ return candidates.find((sf) => {
6327
+ var _a;
6328
+ if (!((_a = sf.metaData) == null ? void 0 : _a.fullName)) return false;
6329
+ const typefacePattern = new RegExp(`^${typefaceName}\\s+`, "i");
6330
+ const stylePart = sf.metaData.fullName.replace(typefacePattern, "").trim();
6331
+ return instanceName.toLowerCase() === stylePart.toLowerCase();
6332
+ }) || null;
6333
+ }
6334
+ },
6335
+ // Pass 5: Weight + style matching (numeric, within subfamily)
6336
+ {
6337
+ name: "weight-style",
6338
+ match: (instanceName, parsed, candidates) => {
6339
+ const instanceWeight = weightFromName(parsed.weight);
6340
+ const isBackslant = parsed.style.toLowerCase() === "backslant";
6341
+ const isSlant = parsed.style.toLowerCase() === "slant";
6342
+ const isItalic = parsed.style.toLowerCase() === "italic";
6343
+ return candidates.find((sf) => {
6344
+ var _a, _b;
6345
+ if (Number(sf.weight) !== instanceWeight) return false;
6346
+ if (isBackslant) return sf.style === "Italic" && ((_a = sf.title) == null ? void 0 : _a.toLowerCase().includes("backslant"));
6347
+ if (isSlant) return sf.style === "Italic" && !((_b = sf.title) == null ? void 0 : _b.toLowerCase().includes("backslant"));
6348
+ if (isItalic) return sf.style === "Italic";
6349
+ return sf.style === "Regular";
6350
+ }) || null;
6351
+ }
6352
+ },
6353
+ // Pass 6: weightName string comparison
6354
+ {
6355
+ name: "weightName",
6356
+ match: (instanceName, parsed, candidates) => {
6357
+ const cleanInstance = parsed.weight.toLowerCase().trim();
6358
+ return candidates.find((sf) => {
6359
+ if (!sf.weightName) return false;
6360
+ const cleanWeight = sf.weightName.toLowerCase().replace(/italic|slant|backslant/gi, "").trim();
6361
+ return cleanInstance === cleanWeight;
6362
+ }) || null;
6363
+ }
6364
+ }
6365
+ ];
6171
6366
  var parseVariableFontInstances = async (font, client) => {
6172
6367
  if (!font.variableFont || !font.variableInstances) return [];
6173
6368
  let variableInstances;
@@ -6182,14 +6377,7 @@ var parseVariableFontInstances = async (font, client) => {
6182
6377
  const typeface = await client.fetch(
6183
6378
  `*[_type == 'typeface' && title == $typefaceName][0]{
6184
6379
  'fonts': styles.fonts[]-> {
6185
- _id,
6186
- title,
6187
- subfamily,
6188
- style,
6189
- weight,
6190
- weightName,
6191
- metaData,
6192
- variableFont
6380
+ _id, title, subfamily, style, weight, weightName, metaData, variableFont
6193
6381
  }
6194
6382
  }`,
6195
6383
  { typefaceName: font.typefaceName }
@@ -6201,127 +6389,49 @@ var parseVariableFontInstances = async (font, client) => {
6201
6389
  console.warn("Typeface not found or no fonts in curated list, falling back to all fonts query");
6202
6390
  staticFonts = await client.fetch(
6203
6391
  `*[_type == 'font' && typefaceName == $typefaceName && variableFont != true]{
6204
- _id,
6205
- title,
6206
- subfamily,
6207
- style,
6208
- weight,
6209
- weightName,
6210
- metaData
6392
+ _id, title, subfamily, style, weight, weightName, metaData
6211
6393
  }`,
6212
6394
  { typefaceName: font.typefaceName }
6213
6395
  );
6214
6396
  }
6215
- console.log("Variable font instances:", Object.keys(variableInstances));
6216
- console.log("Available static fonts:", staticFonts.map((sf) => sf.title));
6217
- const instanceMappings = [];
6218
- Object.keys(variableInstances).forEach((instanceName) => {
6219
- let matchingFont = null;
6220
- matchingFont = staticFonts.find((sf) => sf.title === instanceName);
6221
- if (!matchingFont && staticFonts.some((sf) => {
6222
- var _a;
6223
- return (_a = sf.metaData) == null ? void 0 : _a.fullName;
6224
- })) {
6225
- matchingFont = staticFonts.find((sf) => {
6226
- var _a, _b, _c, _d;
6227
- if (!((_a = sf.metaData) == null ? void 0 : _a.fullName)) return false;
6228
- let fullName = sf.metaData.fullName;
6229
- const WORDS_TO_REMOVE = ["VF", "var", "variable", "VAR", "vf"];
6230
- const variableName = (_c = (_b = font.metaData) == null ? void 0 : _b.familyName) == null ? void 0 : _c.replace(new RegExp(`\\b(${WORDS_TO_REMOVE.join("|")})\\b`, "gi"), "").replace(/\s{2,}/g, " ").trim();
6231
- if (variableName && fullName.startsWith(variableName)) {
6232
- fullName = fullName.substring(variableName.length).trim();
6233
- }
6234
- if (variableName) {
6235
- const words = variableName.split(/\s+/).map((w) => w.trim()).filter(Boolean);
6236
- if (words.length > 0) {
6237
- const regex = new RegExp(`\\b(${words.join("|")})\\b`, "gi");
6238
- const stripped = fullName.replace(regex, "").replace(/\s{2,}/g, " ").trim();
6239
- if (stripped !== "") fullName = stripped;
6240
- }
6241
- }
6242
- if (fullName.startsWith(font.typefaceName)) {
6243
- fullName = fullName.substring(font.typefaceName.length).trim();
6244
- }
6245
- if (((_d = sf.style) == null ? void 0 : _d.toLowerCase()) === "italic" && !fullName.toLowerCase().endsWith("italic") && !fullName.toLowerCase().endsWith("slanted")) {
6246
- fullName = fullName + " Italic";
6247
- }
6248
- if (fullName.trim().toLowerCase().endsWith("regular")) {
6249
- if (instanceName.trim().toLowerCase() + " regular" === fullName.trim().toLowerCase()) return true;
6250
- }
6251
- if (fullName.trim().toLowerCase().startsWith("regular")) {
6252
- if ("regular " + instanceName.trim().toLowerCase() === fullName.trim().toLowerCase()) return true;
6253
- }
6254
- if (fullName.trim().toLowerCase().endsWith("italic")) {
6255
- if (instanceName.trim().toLowerCase().endsWith("italic")) {
6256
- const k = instanceName.trim().toLowerCase().slice(0, -6).trim() + " regular italic";
6257
- if (k === fullName.trim().toLowerCase()) return true;
6258
- }
6259
- }
6260
- return fullName.trim().toLowerCase() === instanceName.trim().toLowerCase();
6261
- });
6262
- }
6263
- if (!matchingFont) {
6264
- const expandedName = instanceName.split(" ").map((word) => expandAbbreviations(word)).join(" ");
6265
- matchingFont = staticFonts.find((sf) => {
6266
- const nameWithoutTypeface = sf.title.replace(font.typefaceName, "").trim();
6267
- return nameWithoutTypeface === expandedName;
6268
- });
6269
- }
6270
- if (!matchingFont) {
6271
- const isItalic = instanceName.toLowerCase().includes("italic");
6272
- const weightTerms = [
6273
- { term: "thin", weight: "100" },
6274
- { term: "extralight", weight: "200" },
6275
- { term: "extra light", weight: "200" },
6276
- { term: "light", weight: "300" },
6277
- { term: "regular", weight: "400" },
6278
- { term: "normal", weight: "400" },
6279
- { term: "medium", weight: "500" },
6280
- { term: "semibold", weight: "600" },
6281
- { term: "semi bold", weight: "600" },
6282
- { term: "bold", weight: "700" },
6283
- { term: "extrabold", weight: "800" },
6284
- { term: "extra bold", weight: "800" },
6285
- { term: "black", weight: "900" },
6286
- { term: "heavy", weight: "900" }
6287
- ];
6288
- let instanceWeight = "400";
6289
- for (const { term, weight } of weightTerms) {
6290
- if (instanceName.toLowerCase().includes(term)) {
6291
- instanceWeight = weight;
6292
- break;
6293
- }
6397
+ const instanceNames = Object.keys(variableInstances);
6398
+ console.log("Variable font instances:", instanceNames.length);
6399
+ console.log("Available static fonts:", staticFonts.length);
6400
+ const parsedInstances = instanceNames.map((name) => ({
6401
+ name,
6402
+ parsed: parseInstanceName(name)
6403
+ }));
6404
+ const results = /* @__PURE__ */ new Map();
6405
+ const claimedFontIds = /* @__PURE__ */ new Set();
6406
+ for (const strategy of STRATEGIES) {
6407
+ const unmatched = parsedInstances.filter((inst) => !results.has(inst.name));
6408
+ if (unmatched.length === 0) break;
6409
+ const passMatches = [];
6410
+ for (const inst of unmatched) {
6411
+ const subfamilyCandidates = filterBySubfamily(staticFonts, inst.parsed.subfamily, font.typefaceName).filter((sf) => !claimedFontIds.has(sf._id));
6412
+ const match = strategy.match(inst.name, inst.parsed, subfamilyCandidates, font.typefaceName, font);
6413
+ if (match) {
6414
+ passMatches.push({ instanceName: inst.name, font: match, strategy: strategy.name });
6294
6415
  }
6295
- matchingFont = staticFonts.find(
6296
- (sf) => sf.weight === instanceWeight && (isItalic && sf.style === "Italic" || !isItalic && sf.style === "Regular")
6297
- );
6298
- }
6299
- if (!matchingFont) {
6300
- matchingFont = staticFonts.find((sf) => {
6301
- if (!sf.weightName) return false;
6302
- const cleanInstance = instanceName.toLowerCase().replace(/italic/i, "").trim();
6303
- const cleanWeight = sf.weightName.toLowerCase().replace(/italic/i, "").trim();
6304
- return cleanInstance === cleanWeight;
6305
- });
6306
6416
  }
6307
- if (!matchingFont && staticFonts.some((sf) => {
6308
- var _a;
6309
- return (_a = sf.metaData) == null ? void 0 : _a.fullName;
6310
- })) {
6311
- matchingFont = staticFonts.find((sf) => {
6312
- var _a;
6313
- if (!((_a = sf.metaData) == null ? void 0 : _a.fullName)) return false;
6314
- const typefacePattern = new RegExp(`^${font.typefaceName}\\s+`, "i");
6315
- const stylePart = sf.metaData.fullName.replace(typefacePattern, "").trim();
6316
- return instanceName.toLowerCase() === stylePart.toLowerCase();
6317
- });
6417
+ for (const m of passMatches) {
6418
+ if (!claimedFontIds.has(m.font._id) && !results.has(m.instanceName)) {
6419
+ results.set(m.instanceName, { fontId: m.font._id, strategy: m.strategy });
6420
+ claimedFontIds.add(m.font._id);
6421
+ }
6318
6422
  }
6319
- console.log(`Instance "${instanceName}" matched with:`, matchingFont ? matchingFont.title : "No match found");
6320
- instanceMappings.push({
6423
+ }
6424
+ const matched = [...results.values()].length;
6425
+ console.log(`[parseVariableFontInstances] Matched ${matched}/${instanceNames.length} instances across ${STRATEGIES.length} passes`);
6426
+ const instanceMappings = instanceNames.map((instanceName) => {
6427
+ const result = results.get(instanceName);
6428
+ const matchedFont = result ? staticFonts.find((sf) => sf._id === result.fontId) : null;
6429
+ console.log(`Instance "${instanceName}" \u2192 ${matchedFont ? `${matchedFont.title} (${result.strategy})` : "No match"}`);
6430
+ return {
6321
6431
  key: instanceName,
6322
- value: matchingFont ? { _type: "reference", _ref: matchingFont._id, _weak: true } : null,
6432
+ value: matchedFont ? { _type: "reference", _ref: matchedFont._id, _weak: true } : null,
6323
6433
  _key: nanoid3()
6324
- });
6434
+ };
6325
6435
  });
6326
6436
  return instanceMappings;
6327
6437
  };
@@ -6332,9 +6442,20 @@ import { nanoid as nanoid4 } from "nanoid";
6332
6442
  var updateTypefaceDocument = async (doc_id, fontRefs, variableRefs, subfamilies, uniqueSubfamilies, subfamiliesArray, preferredStyleRef, newPreferredStyle, stylesObject, client, setStatus, setError) => {
6333
6443
  console.log("Updating typeface document with new fonts:", { fontRefs, variableRefs, subfamilies, uniqueSubfamilies });
6334
6444
  setStatus("Updating typeface references...");
6445
+ const dedupeRefs = (existing, incoming) => {
6446
+ const merged = [...existing || []];
6447
+ const existingRefs = new Set(merged.map((r) => r._ref).filter(Boolean));
6448
+ incoming.forEach((ref) => {
6449
+ if (ref._ref && !existingRefs.has(ref._ref)) {
6450
+ merged.push(ref);
6451
+ existingRefs.add(ref._ref);
6452
+ }
6453
+ });
6454
+ return merged;
6455
+ };
6335
6456
  let patch = {
6336
- "styles.fonts": stylesObject.fonts ? [...stylesObject.fonts, ...fontRefs] : [...fontRefs],
6337
- "styles.variableFont": (stylesObject == null ? void 0 : stylesObject.variableFont) ? [...stylesObject.variableFont, ...variableRefs] : [...variableRefs]
6457
+ "styles.fonts": dedupeRefs(stylesObject.fonts, fontRefs),
6458
+ "styles.variableFont": dedupeRefs(stylesObject == null ? void 0 : stylesObject.variableFont, variableRefs)
6338
6459
  };
6339
6460
  setStatus("Organising font subfamilies...");
6340
6461
  subfamiliesArray = subfamiliesArray || [];
@@ -6539,7 +6660,7 @@ async function executeUploadPlan({
6539
6660
  return result;
6540
6661
  }
6541
6662
  async function executeSingleFont({ entry, plan, client, progress, onProgress }) {
6542
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6663
+ var _a, _b, _c, _d;
6543
6664
  const fontProgress = progress[entry.tempId];
6544
6665
  fontProgress.status = EXECUTION_STATUS.UPLOADING_ASSETS;
6545
6666
  if (onProgress) {
@@ -6656,7 +6777,7 @@ async function executeSingleFont({ entry, plan, client, progress, onProgress })
6656
6777
  _key: nanoid5(),
6657
6778
  title: entry.title,
6658
6779
  slug: { _type: "slug", current: fontDocId },
6659
- typefaceName: ((_g = (_f = (_e = plan.fonts[entry.tempId]) == null ? void 0 : _e.decisions) == null ? void 0 : _f.title) == null ? void 0 : _g.original) ? entry.title.split(" ").slice(0, -1).join(" ") || entry.title : entry.title,
6780
+ typefaceName: plan.settings.typefaceTitle || entry.title,
6660
6781
  style: entry.style,
6661
6782
  variableFont: entry.variableFont,
6662
6783
  weightName: entry.weightName,
@@ -6667,7 +6788,6 @@ async function executeSingleFont({ entry, plan, client, progress, onProgress })
6667
6788
  normalWeight: true,
6668
6789
  fileInput
6669
6790
  };
6670
- fontDoc.typefaceName = ((_j = (_i = (_h = Object.values(plan.fonts)[0]) == null ? void 0 : _h.decisions) == null ? void 0 : _i.title) == null ? void 0 : _j.original) ? plan.settings.typefaceTitle || fontDoc.typefaceName : fontDoc.typefaceName;
6671
6791
  if (entry.metaData) fontDoc.metaData = entry.metaData;
6672
6792
  if (entry.metrics) fontDoc.metrics = entry.metrics;
6673
6793
  if (entry.variableAxes) fontDoc.variableAxes = entry.variableAxes;
@@ -6900,10 +7020,295 @@ function UploadStep3Execute({
6900
7020
  }))), execState.error && /* @__PURE__ */ React7.createElement(Card5, { tone: "critical", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React7.createElement(Text7, { size: 1 }, execState.error)));
6901
7021
  }
6902
7022
 
7023
+ // src/components/UploadStep3bInstances.jsx
7024
+ import React8, { useState as useState5, useEffect as useEffect4, useCallback as useCallback4, useMemo as useMemo6 } from "react";
7025
+ import { Box as Box7, Stack as Stack6, Flex as Flex8, Text as Text8, Card as Card6, Badge as Badge6, Button as Button6, Spinner as Spinner3, Autocomplete } from "@sanity/ui";
7026
+ import { CheckmarkCircleIcon as CheckmarkCircleIcon2, CloseCircleIcon, SearchIcon as SearchIcon2 } from "@sanity/icons";
7027
+ import { nanoid as nanoid6 } from "nanoid";
7028
+ function UploadStep3bInstances({
7029
+ plan,
7030
+ executionResult,
7031
+ client,
7032
+ typefaceTitle,
7033
+ onComplete
7034
+ }) {
7035
+ const [loading, setLoading] = useState5(true);
7036
+ const [saving, setSaving] = useState5(false);
7037
+ const [vfMappings, setVfMappings] = useState5({});
7038
+ const [allStaticFonts, setAllStaticFonts] = useState5([]);
7039
+ const [filterUnmatched, setFilterUnmatched] = useState5(false);
7040
+ const vfEntries = useMemo6(
7041
+ () => Object.values(plan.fonts).filter((f) => f.variableFont && f.status !== "error"),
7042
+ [plan.fonts]
7043
+ );
7044
+ const runMatching = useCallback4(async () => {
7045
+ var _a;
7046
+ setLoading(true);
7047
+ const mappings = {};
7048
+ let staticFonts = [];
7049
+ try {
7050
+ const typeface = await client.fetch(
7051
+ `*[_type == 'typeface' && title == $typefaceTitle][0]{
7052
+ 'fonts': styles.fonts[]-> {
7053
+ _id, title, subfamily, style, weight, weightName, metaData, variableFont
7054
+ }
7055
+ }`,
7056
+ { typefaceTitle }
7057
+ );
7058
+ if (((_a = typeface == null ? void 0 : typeface.fonts) == null ? void 0 : _a.length) > 0) {
7059
+ staticFonts = typeface.fonts.filter((f) => !f.variableFont);
7060
+ }
7061
+ if (staticFonts.length === 0) {
7062
+ staticFonts = await client.fetch(
7063
+ `*[_type == 'font' && typefaceName == $typefaceTitle && variableFont != true]{
7064
+ _id, title, subfamily, style, weight, weightName, metaData
7065
+ }`,
7066
+ { typefaceTitle }
7067
+ );
7068
+ }
7069
+ } catch (err) {
7070
+ console.error("[InstanceMapper] Failed to fetch static fonts:", err);
7071
+ }
7072
+ const deduped = /* @__PURE__ */ new Map();
7073
+ staticFonts.forEach((f) => {
7074
+ if (f._id && !deduped.has(f._id)) deduped.set(f._id, f);
7075
+ });
7076
+ staticFonts = [...deduped.values()];
7077
+ console.log(`[InstanceMapper] Found ${staticFonts.length} static fonts for "${typefaceTitle}"`);
7078
+ setAllStaticFonts(staticFonts);
7079
+ for (const vf of vfEntries) {
7080
+ try {
7081
+ const vfDoc = await client.fetch(
7082
+ `*[_id == $id][0]{
7083
+ _id, title, typefaceName, variableFont, variableInstances, metaData
7084
+ }`,
7085
+ { id: vf.documentId }
7086
+ );
7087
+ if (!vfDoc) {
7088
+ console.warn(`[InstanceMapper] VF document not found: ${vf.documentId}`);
7089
+ mappings[vf.tempId] = [];
7090
+ continue;
7091
+ }
7092
+ console.log(`[InstanceMapper] Running matcher for VF: ${vfDoc.title}, variableInstances: ${vfDoc.variableInstances ? "present" : "missing"}`);
7093
+ const instanceMappings = await parseVariableFontInstances(vfDoc, client);
7094
+ console.log(`[InstanceMapper] Matched ${instanceMappings.filter((m) => m.value).length}/${instanceMappings.length} instances for ${vfDoc.title}`);
7095
+ mappings[vf.tempId] = instanceMappings.map((m) => {
7096
+ var _a2;
7097
+ return {
7098
+ instanceName: m.key,
7099
+ matchedFontId: ((_a2 = m.value) == null ? void 0 : _a2._ref) || "",
7100
+ matchedFontTitle: "",
7101
+ _key: m._key || nanoid6()
7102
+ };
7103
+ });
7104
+ } catch (err) {
7105
+ console.error(`[InstanceMapper] Error matching VF ${vf.documentId}:`, err);
7106
+ mappings[vf.tempId] = [];
7107
+ }
7108
+ }
7109
+ const allMatchedIds = /* @__PURE__ */ new Set();
7110
+ Object.values(mappings).forEach((m) => m.forEach((i) => {
7111
+ if (i.matchedFontId) allMatchedIds.add(i.matchedFontId);
7112
+ }));
7113
+ if (allMatchedIds.size > 0) {
7114
+ try {
7115
+ const titles = await client.fetch(`*[_id in $ids]{ _id, title }`, { ids: [...allMatchedIds] });
7116
+ const titleMap = {};
7117
+ titles.forEach((t) => {
7118
+ titleMap[t._id] = t.title;
7119
+ });
7120
+ Object.values(mappings).forEach((m) => {
7121
+ m.forEach((i) => {
7122
+ if (i.matchedFontId) i.matchedFontTitle = titleMap[i.matchedFontId] || i.matchedFontId;
7123
+ });
7124
+ });
7125
+ } catch (err) {
7126
+ console.warn("[InstanceMapper] Failed to resolve font titles:", err);
7127
+ }
7128
+ }
7129
+ setVfMappings(mappings);
7130
+ setLoading(false);
7131
+ }, [vfEntries, client, typefaceTitle]);
7132
+ useEffect4(() => {
7133
+ runMatching();
7134
+ }, [runMatching]);
7135
+ const claimedFontIds = useMemo6(() => {
7136
+ const claimed = /* @__PURE__ */ new Set();
7137
+ Object.values(vfMappings).forEach((mappings) => {
7138
+ mappings.forEach((m) => {
7139
+ if (m.matchedFontId) claimed.add(m.matchedFontId);
7140
+ });
7141
+ });
7142
+ return claimed;
7143
+ }, [vfMappings]);
7144
+ const handleMappingChange = useCallback4((vfTempId, instanceKey, fontId) => {
7145
+ const font = allStaticFonts.find((sf) => sf._id === fontId);
7146
+ setVfMappings((prev) => ({
7147
+ ...prev,
7148
+ [vfTempId]: prev[vfTempId].map(
7149
+ (m) => m._key === instanceKey ? { ...m, matchedFontId: fontId, matchedFontTitle: (font == null ? void 0 : font.title) || fontId } : m
7150
+ )
7151
+ }));
7152
+ }, [allStaticFonts]);
7153
+ const handleSave = useCallback4(async () => {
7154
+ setSaving(true);
7155
+ const errors = [];
7156
+ for (const vf of vfEntries) {
7157
+ const mappings = vfMappings[vf.tempId] || [];
7158
+ const references = mappings.filter((m) => m.matchedFontId).map((m) => ({
7159
+ _key: nanoid6(),
7160
+ _type: "object",
7161
+ key: m.instanceName,
7162
+ value: {
7163
+ _type: "reference",
7164
+ _ref: m.matchedFontId,
7165
+ _weak: true
7166
+ }
7167
+ }));
7168
+ try {
7169
+ await client.patch(vf.documentId).set({
7170
+ variableInstanceReferences: references
7171
+ }).commit();
7172
+ console.log(`Patched VF instance mappings: ${vf.documentId} (${references.length} instances)`);
7173
+ } catch (err) {
7174
+ console.error(`Failed to patch VF ${vf.documentId}:`, err);
7175
+ errors.push({ vfTitle: vf.title, error: err.message });
7176
+ }
7177
+ }
7178
+ setSaving(false);
7179
+ onComplete({ success: errors.length === 0, errors });
7180
+ }, [vfEntries, vfMappings, client, onComplete]);
7181
+ const totalInstances = Object.values(vfMappings).reduce((sum, m) => sum + m.length, 0);
7182
+ const matchedInstances = Object.values(vfMappings).reduce(
7183
+ (sum, m) => sum + m.filter((i) => i.matchedFontId).length,
7184
+ 0
7185
+ );
7186
+ const unmatchedInstances = totalInstances - matchedInstances;
7187
+ const getAutocompleteOptions = useCallback4((currentFontId) => {
7188
+ return allStaticFonts.filter((sf) => !claimedFontIds.has(sf._id) || sf._id === currentFontId).map((sf) => ({
7189
+ value: sf._id,
7190
+ payload: sf
7191
+ }));
7192
+ }, [allStaticFonts, claimedFontIds]);
7193
+ if (loading) {
7194
+ return /* @__PURE__ */ React8.createElement(Card6, { border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 3, justify: "center" }, /* @__PURE__ */ React8.createElement(Spinner3, null), /* @__PURE__ */ React8.createElement(Text8, { size: 1 }, "Matching variable font instances to static fonts...")));
7195
+ }
7196
+ if (vfEntries.length === 0) {
7197
+ onComplete({ success: true, errors: [] });
7198
+ return null;
7199
+ }
7200
+ return /* @__PURE__ */ React8.createElement(Stack6, { space: 4 }, /* @__PURE__ */ React8.createElement(Stack6, { space: 2 }, /* @__PURE__ */ React8.createElement(Text8, { size: 2, weight: "semibold" }, "Map Variable Font Instances"), /* @__PURE__ */ React8.createElement(Text8, { size: 1, muted: true }, "Review the auto-matched instances below. Each named instance should map to its corresponding static font document.")), /* @__PURE__ */ React8.createElement(Flex8, { gap: 2, align: "center" }, /* @__PURE__ */ React8.createElement(
7201
+ Button6,
7202
+ {
7203
+ mode: "ghost",
7204
+ tone: "primary",
7205
+ icon: SearchIcon2,
7206
+ text: "Re-run Matching",
7207
+ fontSize: 0,
7208
+ padding: 2,
7209
+ onClick: runMatching,
7210
+ disabled: loading,
7211
+ style: { cursor: "pointer" }
7212
+ }
7213
+ ), /* @__PURE__ */ React8.createElement(Badge6, { tone: "positive", fontSize: 0 }, matchedInstances, " matched"), unmatchedInstances > 0 && /* @__PURE__ */ React8.createElement(
7214
+ Badge6,
7215
+ {
7216
+ tone: "critical",
7217
+ fontSize: 0,
7218
+ style: { cursor: "pointer" },
7219
+ onClick: () => setFilterUnmatched((v) => !v)
7220
+ },
7221
+ unmatchedInstances,
7222
+ " unmatched ",
7223
+ filterUnmatched ? "(showing)" : ""
7224
+ ), filterUnmatched && /* @__PURE__ */ React8.createElement(
7225
+ Badge6,
7226
+ {
7227
+ mode: "outline",
7228
+ fontSize: 0,
7229
+ style: { cursor: "pointer" },
7230
+ onClick: () => setFilterUnmatched(false)
7231
+ },
7232
+ "Clear filter"
7233
+ ), /* @__PURE__ */ React8.createElement(Badge6, { mode: "outline", fontSize: 0 }, allStaticFonts.length, " fonts available")), vfEntries.map((vf) => {
7234
+ const mappings = vfMappings[vf.tempId] || [];
7235
+ const displayMappings = filterUnmatched ? mappings.filter((m) => !m.matchedFontId) : mappings;
7236
+ const vfMatched = mappings.filter((m) => m.matchedFontId).length;
7237
+ return /* @__PURE__ */ React8.createElement(Card6, { key: vf.tempId, border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React8.createElement(Stack6, { space: 3 }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 2 }, /* @__PURE__ */ React8.createElement(Badge6, { tone: "primary", fontSize: 0 }, "VF"), /* @__PURE__ */ React8.createElement(Text8, { size: 1, weight: "semibold" }, vf.title), /* @__PURE__ */ React8.createElement(Text8, { size: 0, muted: true, style: { marginLeft: "auto" } }, vfMatched, "/", mappings.length, " matched")), /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 2, paddingY: 1, style: { borderBottom: "1px solid var(--card-border-color)" } }, /* @__PURE__ */ React8.createElement(Box7, { style: { width: 20 } }), /* @__PURE__ */ React8.createElement(Text8, { size: 0, weight: "semibold", muted: true, style: { flex: 1 } }, "Instance"), /* @__PURE__ */ React8.createElement(Text8, { size: 0, weight: "semibold", muted: true, style: { flex: 2 } }, "Static Font Document")), /* @__PURE__ */ React8.createElement(Stack6, { space: 1 }, displayMappings.map((mapping) => {
7238
+ const isMatched = !!mapping.matchedFontId;
7239
+ const options = getAutocompleteOptions(mapping.matchedFontId);
7240
+ return /* @__PURE__ */ React8.createElement(
7241
+ Flex8,
7242
+ {
7243
+ key: mapping._key,
7244
+ align: "center",
7245
+ gap: 2,
7246
+ paddingY: 2,
7247
+ style: { borderBottom: "1px solid var(--card-border-color)" }
7248
+ },
7249
+ /* @__PURE__ */ React8.createElement(Box7, { style: { width: 20, flexShrink: 0 } }, isMatched ? /* @__PURE__ */ React8.createElement(CheckmarkCircleIcon2, { style: { color: "#43b649", fontSize: 16 } }) : /* @__PURE__ */ React8.createElement(CloseCircleIcon, { style: { color: "#f03e2f", fontSize: 16 } })),
7250
+ /* @__PURE__ */ React8.createElement(Text8, { size: 1, style: { flex: 1, whiteSpace: "nowrap" } }, mapping.instanceName),
7251
+ /* @__PURE__ */ React8.createElement(Box7, { style: { flex: 2 } }, /* @__PURE__ */ React8.createElement(
7252
+ Autocomplete,
7253
+ {
7254
+ id: `instance-${mapping._key}`,
7255
+ options,
7256
+ value: mapping.matchedFontId,
7257
+ placeholder: "Search for a font...",
7258
+ icon: SearchIcon2,
7259
+ fontSize: 1,
7260
+ filterOption: (query, option) => {
7261
+ var _a, _b, _c, _d;
7262
+ const sf = option.payload;
7263
+ const q = query.toLowerCase();
7264
+ return ((_a = sf.title) == null ? void 0 : _a.toLowerCase().includes(q)) || ((_b = sf._id) == null ? void 0 : _b.toLowerCase().includes(q)) || ((_c = sf.weightName) == null ? void 0 : _c.toLowerCase().includes(q)) || String(sf.weight).includes(q) || ((_d = sf.subfamily) == null ? void 0 : _d.toLowerCase().includes(q));
7265
+ },
7266
+ renderOption: (option) => {
7267
+ const sf = option.payload;
7268
+ const isClaimed = claimedFontIds.has(sf._id) && sf._id !== mapping.matchedFontId;
7269
+ return /* @__PURE__ */ React8.createElement(Card6, { as: "button", padding: 2, style: { opacity: isClaimed ? 0.4 : 1 } }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 2 }, /* @__PURE__ */ React8.createElement(Text8, { size: 1 }, sf.title), /* @__PURE__ */ React8.createElement(Text8, { size: 0, muted: true }, sf.weight, " ", sf.style), sf.subfamily && sf.subfamily !== "Regular" && /* @__PURE__ */ React8.createElement(Badge6, { mode: "outline", fontSize: 0 }, sf.subfamily)));
7270
+ },
7271
+ renderValue: (value, option) => {
7272
+ if (option == null ? void 0 : option.payload) return option.payload.title;
7273
+ if (mapping.matchedFontTitle) return mapping.matchedFontTitle;
7274
+ const font = allStaticFonts.find((sf) => sf._id === value);
7275
+ return (font == null ? void 0 : font.title) || value;
7276
+ },
7277
+ onSelect: (value) => handleMappingChange(vf.tempId, mapping._key, value),
7278
+ openButton: true
7279
+ }
7280
+ ))
7281
+ );
7282
+ })), mappings.length === 0 && /* @__PURE__ */ React8.createElement(Text8, { size: 1, muted: true }, "No named instances found in this variable font.")));
7283
+ }), /* @__PURE__ */ React8.createElement(Flex8, { justify: "flex-end", gap: 2, style: { position: "sticky", bottom: 0, background: "var(--card-bg-color)", paddingTop: 8, paddingBottom: 4 } }, /* @__PURE__ */ React8.createElement(
7284
+ Button6,
7285
+ {
7286
+ mode: "ghost",
7287
+ text: "Skip \u2014 I'll map instances later",
7288
+ fontSize: 1,
7289
+ padding: 3,
7290
+ onClick: () => onComplete({ success: true, errors: [], skipped: true }),
7291
+ style: { cursor: "pointer" }
7292
+ }
7293
+ ), /* @__PURE__ */ React8.createElement(
7294
+ Button6,
7295
+ {
7296
+ mode: "default",
7297
+ tone: "positive",
7298
+ text: saving ? "Saving..." : `Save Mappings (${matchedInstances}/${totalInstances})`,
7299
+ fontSize: 1,
7300
+ padding: 3,
7301
+ disabled: saving,
7302
+ onClick: handleSave,
7303
+ style: { cursor: "pointer" }
7304
+ }
7305
+ )));
7306
+ }
7307
+
6903
7308
  // src/components/UploadSummary.jsx
6904
- import React8, { useState as useState5, useCallback as useCallback4 } from "react";
6905
- import { Stack as Stack6, Flex as Flex8, Text as Text8, Card as Card6, Badge as Badge6, Button as Button6, Box as Box7, Spinner as Spinner3 } from "@sanity/ui";
6906
- import { CheckmarkCircleIcon as CheckmarkCircleIcon2, WarningOutlineIcon as WarningOutlineIcon2, ResetIcon as ResetIcon2 } from "@sanity/icons";
7309
+ import React9, { useState as useState6, useCallback as useCallback5 } from "react";
7310
+ import { Stack as Stack7, Flex as Flex9, Text as Text9, Card as Card7, Badge as Badge7, Button as Button7, Box as Box8, Spinner as Spinner4 } from "@sanity/ui";
7311
+ import { CheckmarkCircleIcon as CheckmarkCircleIcon3, WarningOutlineIcon as WarningOutlineIcon2, ResetIcon as ResetIcon2 } from "@sanity/icons";
6907
7312
  function UploadSummary({
6908
7313
  plan,
6909
7314
  result,
@@ -6915,12 +7320,12 @@ function UploadSummary({
6915
7320
  preferredStyleRef
6916
7321
  }) {
6917
7322
  var _a;
6918
- const [retryingPatch, setRetryingPatch] = useState5(false);
6919
- const [patchRetryResult, setPatchRetryResult] = useState5(null);
7323
+ const [retryingPatch, setRetryingPatch] = useState6(false);
7324
+ const [patchRetryResult, setPatchRetryResult] = useState6(null);
6920
7325
  const hasFailedFonts = ((_a = result == null ? void 0 : result.failedFonts) == null ? void 0 : _a.length) > 0;
6921
7326
  const hasTypefacePatchError = (result == null ? void 0 : result.typefacePatchError) && !(patchRetryResult == null ? void 0 : patchRetryResult.success);
6922
7327
  const allSuccess = (result == null ? void 0 : result.success) && !hasTypefacePatchError;
6923
- const handleRetryTypefacePatch = useCallback4(async () => {
7328
+ const handleRetryTypefacePatch = useCallback5(async () => {
6924
7329
  var _a2, _b;
6925
7330
  if (!result || !client || !docId) return;
6926
7331
  setRetryingPatch(true);
@@ -6956,11 +7361,11 @@ function UploadSummary({
6956
7361
  }
6957
7362
  setRetryingPatch(false);
6958
7363
  }, [result, client, docId, plan, stylesObject, preferredStyleRef]);
6959
- return /* @__PURE__ */ React8.createElement(Stack6, { space: 4 }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 3, ref: (el) => {
7364
+ return /* @__PURE__ */ React9.createElement(Stack7, { space: 4 }, /* @__PURE__ */ React9.createElement(Flex9, { align: "center", gap: 3, ref: (el) => {
6960
7365
  var _a2;
6961
7366
  return (_a2 = el == null ? void 0 : el.focus) == null ? void 0 : _a2.call(el);
6962
- }, tabIndex: -1 }, allSuccess ? /* @__PURE__ */ React8.createElement(CheckmarkCircleIcon2, { style: { color: "#43b649", fontSize: 28 } }) : /* @__PURE__ */ React8.createElement(WarningOutlineIcon2, { style: { color: "#f03e2f", fontSize: 28 } }), /* @__PURE__ */ React8.createElement(Text8, { size: 2, weight: "semibold" }, allSuccess ? "Upload Complete" : "Upload Completed with Issues")), result && /* @__PURE__ */ React8.createElement(Card6, { border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React8.createElement(Stack6, { space: 3 }, /* @__PURE__ */ React8.createElement(Flex8, { gap: 2, wrap: "wrap" }, result.created > 0 && /* @__PURE__ */ React8.createElement(Badge6, { tone: "positive", fontSize: 1 }, result.created, " created"), result.updated > 0 && /* @__PURE__ */ React8.createElement(Badge6, { tone: "caution", fontSize: 1 }, result.updated, " updated"), result.failed > 0 && /* @__PURE__ */ React8.createElement(Badge6, { tone: "critical", fontSize: 1 }, result.failed, " failed"), result.skipped > 0 && /* @__PURE__ */ React8.createElement(Badge6, { mode: "outline", fontSize: 1 }, result.skipped, " skipped")))), hasFailedFonts && /* @__PURE__ */ React8.createElement(Stack6, { space: 3 }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", justify: "space-between" }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 2 }, /* @__PURE__ */ React8.createElement(Text8, { size: 1, weight: "semibold" }, "Failed Fonts"), /* @__PURE__ */ React8.createElement(Badge6, { tone: "critical", fontSize: 0 }, result.failedFonts.length)), /* @__PURE__ */ React8.createElement(
6963
- Button6,
7367
+ }, tabIndex: -1 }, allSuccess ? /* @__PURE__ */ React9.createElement(CheckmarkCircleIcon3, { style: { color: "#43b649", fontSize: 28 } }) : /* @__PURE__ */ React9.createElement(WarningOutlineIcon2, { style: { color: "#f03e2f", fontSize: 28 } }), /* @__PURE__ */ React9.createElement(Text9, { size: 2, weight: "semibold" }, allSuccess ? "Upload Complete" : "Upload Completed with Issues")), result && /* @__PURE__ */ React9.createElement(Card7, { border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React9.createElement(Stack7, { space: 3 }, /* @__PURE__ */ React9.createElement(Flex9, { gap: 2, wrap: "wrap" }, result.created > 0 && /* @__PURE__ */ React9.createElement(Badge7, { tone: "positive", fontSize: 1 }, result.created, " created"), result.updated > 0 && /* @__PURE__ */ React9.createElement(Badge7, { tone: "caution", fontSize: 1 }, result.updated, " updated"), result.failed > 0 && /* @__PURE__ */ React9.createElement(Badge7, { tone: "critical", fontSize: 1 }, result.failed, " failed"), result.skipped > 0 && /* @__PURE__ */ React9.createElement(Badge7, { mode: "outline", fontSize: 1 }, result.skipped, " skipped")))), hasFailedFonts && /* @__PURE__ */ React9.createElement(Stack7, { space: 3 }, /* @__PURE__ */ React9.createElement(Flex9, { align: "center", justify: "space-between" }, /* @__PURE__ */ React9.createElement(Flex9, { align: "center", gap: 2 }, /* @__PURE__ */ React9.createElement(Text9, { size: 1, weight: "semibold" }, "Failed Fonts"), /* @__PURE__ */ React9.createElement(Badge7, { tone: "critical", fontSize: 0 }, result.failedFonts.length)), /* @__PURE__ */ React9.createElement(
7368
+ Button7,
6964
7369
  {
6965
7370
  mode: "ghost",
6966
7371
  tone: "primary",
@@ -6970,8 +7375,8 @@ function UploadSummary({
6970
7375
  padding: 2,
6971
7376
  onClick: () => onRetry(result.failedFonts.map((f) => f.tempId).filter(Boolean))
6972
7377
  }
6973
- )), /* @__PURE__ */ React8.createElement(Stack6, { space: 2 }, result.failedFonts.map((f, i) => /* @__PURE__ */ React8.createElement(Card6, { key: i, tone: "critical", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React8.createElement(Stack6, { space: 2 }, /* @__PURE__ */ React8.createElement(Flex8, { align: "center", gap: 2 }, /* @__PURE__ */ React8.createElement(Text8, { size: 1, weight: "semibold" }, f.title), f.failedAt && f.failedAt !== "unknown" && /* @__PURE__ */ React8.createElement(Badge6, { tone: "critical", fontSize: 0, mode: "outline" }, "Failed at: ", f.failedAt)), /* @__PURE__ */ React8.createElement(Text8, { size: 1 }, f.error)))))), hasTypefacePatchError && /* @__PURE__ */ React8.createElement(Card6, { tone: "caution", border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React8.createElement(Stack6, { space: 3 }, /* @__PURE__ */ React8.createElement(Text8, { size: 1, weight: "semibold" }, "Typeface Document Not Updated"), /* @__PURE__ */ React8.createElement(Text8, { size: 1 }, result.created + result.updated, " font document", result.created + result.updated === 1 ? "" : "s", " created/updated successfully, but the typeface document could not be patched to reference them."), /* @__PURE__ */ React8.createElement(Text8, { size: 1, muted: true }, result.typefacePatchError), /* @__PURE__ */ React8.createElement(Flex8, { gap: 2 }, /* @__PURE__ */ React8.createElement(
6974
- Button6,
7378
+ )), /* @__PURE__ */ React9.createElement(Stack7, { space: 2 }, result.failedFonts.map((f, i) => /* @__PURE__ */ React9.createElement(Card7, { key: i, tone: "critical", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React9.createElement(Stack7, { space: 2 }, /* @__PURE__ */ React9.createElement(Flex9, { align: "center", gap: 2 }, /* @__PURE__ */ React9.createElement(Text9, { size: 1, weight: "semibold" }, f.title), f.failedAt && f.failedAt !== "unknown" && /* @__PURE__ */ React9.createElement(Badge7, { tone: "critical", fontSize: 0, mode: "outline" }, "Failed at: ", f.failedAt)), /* @__PURE__ */ React9.createElement(Text9, { size: 1 }, f.error)))))), hasTypefacePatchError && /* @__PURE__ */ React9.createElement(Card7, { tone: "caution", border: true, padding: 4, radius: 2 }, /* @__PURE__ */ React9.createElement(Stack7, { space: 3 }, /* @__PURE__ */ React9.createElement(Text9, { size: 1, weight: "semibold" }, "Typeface Document Not Updated"), /* @__PURE__ */ React9.createElement(Text9, { size: 1 }, result.created + result.updated, " font document", result.created + result.updated === 1 ? "" : "s", " created/updated successfully, but the typeface document could not be patched to reference them."), /* @__PURE__ */ React9.createElement(Text9, { size: 1, muted: true }, result.typefacePatchError), /* @__PURE__ */ React9.createElement(Flex9, { gap: 2 }, /* @__PURE__ */ React9.createElement(
7379
+ Button7,
6975
7380
  {
6976
7381
  mode: "default",
6977
7382
  tone: "primary",
@@ -6980,8 +7385,8 @@ function UploadSummary({
6980
7385
  disabled: retryingPatch,
6981
7386
  onClick: handleRetryTypefacePatch
6982
7387
  }
6983
- ), retryingPatch && /* @__PURE__ */ React8.createElement(Spinner3, null)))), (patchRetryResult == null ? void 0 : patchRetryResult.success) && /* @__PURE__ */ React8.createElement(Card6, { tone: "positive", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React8.createElement(Text8, { size: 1 }, "Typeface document updated successfully on retry.")), patchRetryResult && !patchRetryResult.success && /* @__PURE__ */ React8.createElement(Card6, { tone: "critical", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React8.createElement(Text8, { size: 1 }, "Retry failed: ", patchRetryResult.error)), /* @__PURE__ */ React8.createElement(Flex8, { justify: "flex-end" }, /* @__PURE__ */ React8.createElement(
6984
- Button6,
7388
+ ), retryingPatch && /* @__PURE__ */ React9.createElement(Spinner4, null)))), (patchRetryResult == null ? void 0 : patchRetryResult.success) && /* @__PURE__ */ React9.createElement(Card7, { tone: "positive", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React9.createElement(Text9, { size: 1 }, "Typeface document updated successfully on retry.")), patchRetryResult && !patchRetryResult.success && /* @__PURE__ */ React9.createElement(Card7, { tone: "critical", border: true, padding: 3, radius: 2 }, /* @__PURE__ */ React9.createElement(Text9, { size: 1 }, "Retry failed: ", patchRetryResult.error)), /* @__PURE__ */ React9.createElement(Flex9, { justify: "flex-end" }, /* @__PURE__ */ React9.createElement(
7389
+ Button7,
6985
7390
  {
6986
7391
  mode: "default",
6987
7392
  tone: "primary",
@@ -6995,7 +7400,8 @@ function UploadSummary({
6995
7400
  var STEPS = [
6996
7401
  { key: 1, label: "Upload Files" },
6997
7402
  { key: 2, label: "Review" },
6998
- { key: 3, label: "Upload" }
7403
+ { key: 3, label: "Upload" },
7404
+ { key: 4, label: "Map Instances" }
6999
7405
  ];
7000
7406
  function phaseToStep(phase) {
7001
7407
  switch (phase) {
@@ -7028,15 +7434,22 @@ function UploadModal({
7028
7434
  slug
7029
7435
  }) {
7030
7436
  const [plan, dispatch] = useReducer2(planReducer, null, () => createEmptyPlan());
7031
- const [processingCancelled, setProcessingCancelled] = useState6(false);
7032
- const [executionResult, setExecutionResult] = useState6(null);
7033
- const [retryTempIds, setRetryTempIds] = useState6(null);
7437
+ const [processingCancelled, setProcessingCancelled] = useState7(false);
7438
+ const [executionResult, setExecutionResult] = useState7(null);
7439
+ const [retryTempIds, setRetryTempIds] = useState7(null);
7440
+ const [instanceMappingPhase, setInstanceMappingPhase] = useState7(false);
7441
+ const [instanceMappingResult, setInstanceMappingResult] = useState7(null);
7034
7442
  const cancelRef = useRef3(false);
7035
7443
  const focusRef = useRef3(null);
7036
- const { weightKeywordList, italicKeywordList } = useMemo6(() => generateStyleKeywords(), []);
7037
- const currentStep = phaseToStep(plan.phase);
7444
+ const { weightKeywordList, italicKeywordList } = useMemo7(() => generateStyleKeywords(), []);
7445
+ const hasVFs = useMemo7(
7446
+ () => Object.values(plan.fonts).some((f) => f.variableFont && f.status !== "error"),
7447
+ [plan.fonts]
7448
+ );
7449
+ const baseStep = phaseToStep(plan.phase);
7450
+ const currentStep = instanceMappingPhase ? 4 : plan.phase === PLAN_PHASE.COMPLETE && !instanceMappingResult ? baseStep : baseStep;
7038
7451
  const isExecuting = plan.phase === PLAN_PHASE.EXECUTING;
7039
- useEffect4(() => {
7452
+ useEffect5(() => {
7040
7453
  if (!open || !isExecuting) return;
7041
7454
  const handler = (e) => {
7042
7455
  e.preventDefault();
@@ -7045,12 +7458,12 @@ function UploadModal({
7045
7458
  window.addEventListener("beforeunload", handler);
7046
7459
  return () => window.removeEventListener("beforeunload", handler);
7047
7460
  }, [open, isExecuting]);
7048
- useEffect4(() => {
7461
+ useEffect5(() => {
7049
7462
  if (focusRef.current) {
7050
7463
  focusRef.current.focus();
7051
7464
  }
7052
7465
  }, [currentStep]);
7053
- const handleClose = useCallback5(() => {
7466
+ const handleClose = useCallback6(() => {
7054
7467
  if (isExecuting) return;
7055
7468
  const hasFonts = Object.keys(plan.fonts).length > 0;
7056
7469
  if (hasFonts && plan.phase !== PLAN_PHASE.COMPLETE) {
@@ -7060,8 +7473,8 @@ function UploadModal({
7060
7473
  setExecutionResult(null);
7061
7474
  onClose();
7062
7475
  }, [plan, isExecuting, onClose]);
7063
- const handleStartProcessing = useCallback5(async (files, settings) => {
7064
- dispatch({ type: "SET_SETTINGS", settings });
7476
+ const handleStartProcessing = useCallback6(async (files, settings) => {
7477
+ dispatch({ type: "SET_SETTINGS", settings: { ...settings, typefaceTitle } });
7065
7478
  dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.PROCESSING, totalFiles: files.length });
7066
7479
  cancelRef.current = false;
7067
7480
  setProcessingCancelled(false);
@@ -7094,20 +7507,29 @@ function UploadModal({
7094
7507
  dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.REVIEWING });
7095
7508
  }
7096
7509
  }, [typefaceTitle, docId, client, stylesObject, weightKeywordList, italicKeywordList]);
7097
- const handleCancelProcessing = useCallback5(() => {
7510
+ const handleCancelProcessing = useCallback6(() => {
7098
7511
  cancelRef.current = true;
7099
7512
  setProcessingCancelled(true);
7100
7513
  dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.IDLE });
7101
7514
  }, []);
7102
- const handleStartExecution = useCallback5(() => {
7515
+ const handleStartExecution = useCallback6(() => {
7103
7516
  dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.EXECUTING });
7104
7517
  }, []);
7105
- const handleExecutionComplete = useCallback5((result) => {
7518
+ const handleExecutionComplete = useCallback6((result) => {
7106
7519
  setExecutionResult(result);
7107
- dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.COMPLETE });
7520
+ if (hasVFs && result.success !== false) {
7521
+ setInstanceMappingPhase(true);
7522
+ dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.COMPLETE });
7523
+ } else {
7524
+ dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.COMPLETE });
7525
+ }
7526
+ }, [hasVFs]);
7527
+ const handleInstanceMappingComplete = useCallback6((result) => {
7528
+ setInstanceMappingResult(result);
7529
+ setInstanceMappingPhase(false);
7108
7530
  }, []);
7109
7531
  if (!open) return null;
7110
- const handleStepClick = useCallback5((stepKey) => {
7532
+ const handleStepClick = useCallback6((stepKey) => {
7111
7533
  if (isExecuting) return;
7112
7534
  if (stepKey === currentStep) return;
7113
7535
  if (stepKey === 1 && currentStep > 1) {
@@ -7117,16 +7539,16 @@ function UploadModal({
7117
7539
  dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.IDLE });
7118
7540
  }
7119
7541
  }, [currentStep, isExecuting, plan.fonts, dispatch]);
7120
- return /* @__PURE__ */ React9.createElement(
7542
+ return /* @__PURE__ */ React10.createElement(
7121
7543
  Dialog,
7122
7544
  {
7123
7545
  id: "upload-modal",
7124
- header: /* @__PURE__ */ React9.createElement(Flex9, { direction: "column", gap: 3, style: { width: "100%" } }, /* @__PURE__ */ React9.createElement(Text9, { weight: "semibold", size: 2 }, "Upload Fonts"), /* @__PURE__ */ React9.createElement(Flex9, { gap: 1, style: { width: "100%" } }, STEPS.map((step, i) => {
7546
+ header: /* @__PURE__ */ React10.createElement(Flex10, { direction: "column", gap: 3, style: { width: "100%" } }, /* @__PURE__ */ React10.createElement(Text10, { weight: "semibold", size: 2 }, "Upload Fonts"), /* @__PURE__ */ React10.createElement(Flex10, { gap: 1, style: { width: "100%" } }, STEPS.filter((step) => step.key !== 4 || hasVFs).map((step, i) => {
7125
7547
  const isActive = currentStep === step.key;
7126
7548
  const isCompleted = currentStep > step.key;
7127
7549
  const isClickable = !isExecuting && step.key < currentStep;
7128
- return /* @__PURE__ */ React9.createElement(
7129
- Box8,
7550
+ return /* @__PURE__ */ React10.createElement(
7551
+ Box9,
7130
7552
  {
7131
7553
  key: step.key,
7132
7554
  as: isClickable ? "button" : "div",
@@ -7144,8 +7566,8 @@ function UploadModal({
7144
7566
  opacity: !isActive && !isCompleted ? 0.6 : 1
7145
7567
  }
7146
7568
  },
7147
- /* @__PURE__ */ React9.createElement(
7148
- Text9,
7569
+ /* @__PURE__ */ React10.createElement(
7570
+ Text10,
7149
7571
  {
7150
7572
  size: 1,
7151
7573
  weight: isActive ? "bold" : "medium",
@@ -7162,13 +7584,13 @@ function UploadModal({
7162
7584
  onClickOutside: () => {
7163
7585
  }
7164
7586
  },
7165
- /* @__PURE__ */ React9.createElement(Box8, { padding: 4 }, currentStep === 1 && /* @__PURE__ */ React9.createElement(
7587
+ /* @__PURE__ */ React10.createElement(Box9, { padding: 4 }, currentStep === 1 && /* @__PURE__ */ React10.createElement(
7166
7588
  UploadStep1Settings,
7167
7589
  {
7168
7590
  settings: plan.settings,
7169
7591
  onStartProcessing: handleStartProcessing
7170
7592
  }
7171
- ), currentStep === 2 && /* @__PURE__ */ React9.createElement(
7593
+ ), currentStep === 2 && /* @__PURE__ */ React10.createElement(
7172
7594
  UploadStep2Review,
7173
7595
  {
7174
7596
  plan,
@@ -7177,7 +7599,7 @@ function UploadModal({
7177
7599
  onStartExecution: handleStartExecution,
7178
7600
  processingCancelled
7179
7601
  }
7180
- ), currentStep === 3 && plan.phase !== PLAN_PHASE.COMPLETE && /* @__PURE__ */ React9.createElement(
7602
+ ), currentStep === 3 && plan.phase !== PLAN_PHASE.COMPLETE && /* @__PURE__ */ React10.createElement(
7181
7603
  UploadStep3Execute,
7182
7604
  {
7183
7605
  key: retryTempIds ? "retry" : "initial",
@@ -7192,15 +7614,27 @@ function UploadModal({
7192
7614
  handleExecutionComplete(result);
7193
7615
  }
7194
7616
  }
7195
- ), plan.phase === PLAN_PHASE.COMPLETE && /* @__PURE__ */ React9.createElement(
7617
+ ), plan.phase === PLAN_PHASE.COMPLETE && instanceMappingPhase && /* @__PURE__ */ React10.createElement(
7618
+ UploadStep3bInstances,
7619
+ {
7620
+ plan,
7621
+ executionResult,
7622
+ client,
7623
+ typefaceTitle,
7624
+ onComplete: handleInstanceMappingComplete
7625
+ }
7626
+ ), plan.phase === PLAN_PHASE.COMPLETE && !instanceMappingPhase && /* @__PURE__ */ React10.createElement(
7196
7627
  UploadSummary,
7197
7628
  {
7198
7629
  plan,
7199
7630
  result: executionResult,
7631
+ instanceMappingResult,
7200
7632
  onClose: handleClose,
7201
7633
  onRetry: (failedTempIds) => {
7202
7634
  setRetryTempIds(failedTempIds || null);
7203
7635
  setExecutionResult(null);
7636
+ setInstanceMappingPhase(false);
7637
+ setInstanceMappingResult(null);
7204
7638
  dispatch({ type: "SET_PHASE", phase: PLAN_PHASE.EXECUTING });
7205
7639
  },
7206
7640
  client,
@@ -7271,6 +7705,7 @@ export {
7271
7705
  createInitialExecutionState,
7272
7706
  executionReducer,
7273
7707
  UploadStep3Execute,
7708
+ UploadStep3bInstances,
7274
7709
  UploadSummary,
7275
7710
  UploadModal
7276
7711
  };