sanity-plugin-seofields 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -221,6 +221,12 @@ export declare interface SeoFieldsPluginConfig {
221
221
  icon?: string
222
222
  title?: string
223
223
  description?: string
224
+ /** Text shown while the license key is being verified. Defaults to "Verifying license…" */
225
+ loadingLicense?: string
226
+ /** Text shown while documents are being fetched. Defaults to "Loading documents…" */
227
+ loadingDocuments?: string
228
+ /** Text shown when the query returns zero results. Defaults to "No documents found" */
229
+ noDocuments?: string
224
230
  }
225
231
  display?: {
226
232
  typeColumn?: boolean
@@ -254,6 +260,54 @@ export declare interface SeoFieldsPluginConfig {
254
260
  * Obtain a license at https://sanity-plugin-seofields.thehardik.in
255
261
  */
256
262
  licenseKey?: string
263
+ /**
264
+ * Map raw `_type` values to human-readable display labels.
265
+ * Used in both the Type column and the Type filter dropdown.
266
+ * Any type without an entry falls back to the raw `_type` string.
267
+ *
268
+ * @example
269
+ * typeLabels: { productDrug: 'Products', singleCondition: 'Condition' }
270
+ */
271
+ typeLabels?: Record<string, string>
272
+ /**
273
+ * Controls how the document type is rendered in the Type column.
274
+ * - `'badge'` (default) — coloured pill
275
+ * - `'text'` — plain text, useful for dense layouts
276
+ */
277
+ typeColumnMode?: 'badge' | 'text'
278
+ /**
279
+ * The document field to use as the display title in the dashboard.
280
+ *
281
+ * - `string` — use this field for every document type (e.g. `'name'`)
282
+ * - `Record<string, string>` — per-type mapping; unmapped types fall back to `title`
283
+ *
284
+ * @example
285
+ * titleField: 'name'
286
+ *
287
+ * @example
288
+ * titleField: { post: 'title', product: 'name', category: 'label' }
289
+ */
290
+ titleField?: string | Record<string, string>
291
+ /**
292
+ * Callback function to render a custom badge next to the document title.
293
+ * Receives the full document and should return badge data or undefined.
294
+ *
295
+ * @example
296
+ * docBadge: (doc) => {
297
+ * if (doc.services === 'NHS')
298
+ * return { label: 'NHS', bgColor: '#e0f2fe', textColor: '#0369a1' }
299
+ * if (doc.services === 'Private')
300
+ * return { label: 'Private', bgColor: '#fef3c7', textColor: '#92400e' }
301
+ * }
302
+ */
303
+ docBadge?: (doc: DocumentWithSeoHealth & Record<string, unknown>) =>
304
+ | {
305
+ label: string
306
+ bgColor?: string
307
+ textColor?: string
308
+ fontSize?: string
309
+ }
310
+ | undefined
257
311
  }
258
312
  }
259
313
 
@@ -294,6 +348,71 @@ declare interface SeoHealthDashboardProps {
294
348
  * Obtain a key at https://sanity-plugin-seofields.thehardik.in
295
349
  */
296
350
  licenseKey?: string
351
+ /**
352
+ * Map raw `_type` values to human-readable display labels used in the
353
+ * Type column and the Type filter dropdown.
354
+ * Any type without an entry falls back to the raw `_type` string.
355
+ *
356
+ * @example
357
+ * typeLabels={{ productDrug: 'Products', singleCondition: 'Condition' }}
358
+ */
359
+ typeLabels?: Record<string, string>
360
+ /**
361
+ * Controls how the type is rendered in the Type column.
362
+ * - `'badge'` (default) — coloured pill, consistent with score badges
363
+ * - `'text'` — plain text, useful for dense layouts
364
+ */
365
+ typeColumnMode?: 'badge' | 'text'
366
+ /**
367
+ * The document field to use as the display title.
368
+ *
369
+ * - `string` — use this field for every document type (e.g. `'name'`)
370
+ * - `Record<string, string>` — per-type mapping; unmapped types fall back to `title`
371
+ *
372
+ * @example
373
+ * // Same field for all types
374
+ * titleField: 'name'
375
+ *
376
+ * @example
377
+ * // Different field per type
378
+ * titleField: { post: 'title', product: 'name', category: 'label' }
379
+ */
380
+ titleField?: string | Record<string, string>
381
+ /**
382
+ * Callback function to render a custom badge next to the document title.
383
+ * Receives the full document and should return badge data or undefined.
384
+ *
385
+ * @example
386
+ * docBadge: (doc) => {
387
+ * if (doc.services === 'NHS')
388
+ * return { label: 'NHS', bgColor: '#e0f2fe', textColor: '#0369a1' }
389
+ * if (doc.services === 'Private')
390
+ * return { label: 'Private', bgColor: '#fef3c7', textColor: '#92400e' }
391
+ * }
392
+ */
393
+ docBadge?: (doc: DocumentWithSeoHealth & Record<string, unknown>) =>
394
+ | {
395
+ label: string
396
+ bgColor?: string
397
+ textColor?: string
398
+ fontSize?: string
399
+ }
400
+ | undefined
401
+ /**
402
+ * Custom text shown while the license key is being verified.
403
+ * Defaults to `"Verifying license…"`.
404
+ */
405
+ loadingLicense?: React_2.ReactNode
406
+ /**
407
+ * Custom text shown while documents are being fetched.
408
+ * Defaults to `"Loading documents…"`.
409
+ */
410
+ loadingDocuments?: React_2.ReactNode
411
+ /**
412
+ * Custom text shown when the query returns zero results.
413
+ * Defaults to `"No documents found"`.
414
+ */
415
+ noDocuments?: React_2.ReactNode
297
416
  }
298
417
 
299
418
  export declare interface SeoHealthMetrics {
package/dist/index.d.ts CHANGED
@@ -221,6 +221,12 @@ export declare interface SeoFieldsPluginConfig {
221
221
  icon?: string
222
222
  title?: string
223
223
  description?: string
224
+ /** Text shown while the license key is being verified. Defaults to "Verifying license…" */
225
+ loadingLicense?: string
226
+ /** Text shown while documents are being fetched. Defaults to "Loading documents…" */
227
+ loadingDocuments?: string
228
+ /** Text shown when the query returns zero results. Defaults to "No documents found" */
229
+ noDocuments?: string
224
230
  }
225
231
  display?: {
226
232
  typeColumn?: boolean
@@ -254,6 +260,54 @@ export declare interface SeoFieldsPluginConfig {
254
260
  * Obtain a license at https://sanity-plugin-seofields.thehardik.in
255
261
  */
256
262
  licenseKey?: string
263
+ /**
264
+ * Map raw `_type` values to human-readable display labels.
265
+ * Used in both the Type column and the Type filter dropdown.
266
+ * Any type without an entry falls back to the raw `_type` string.
267
+ *
268
+ * @example
269
+ * typeLabels: { productDrug: 'Products', singleCondition: 'Condition' }
270
+ */
271
+ typeLabels?: Record<string, string>
272
+ /**
273
+ * Controls how the document type is rendered in the Type column.
274
+ * - `'badge'` (default) — coloured pill
275
+ * - `'text'` — plain text, useful for dense layouts
276
+ */
277
+ typeColumnMode?: 'badge' | 'text'
278
+ /**
279
+ * The document field to use as the display title in the dashboard.
280
+ *
281
+ * - `string` — use this field for every document type (e.g. `'name'`)
282
+ * - `Record<string, string>` — per-type mapping; unmapped types fall back to `title`
283
+ *
284
+ * @example
285
+ * titleField: 'name'
286
+ *
287
+ * @example
288
+ * titleField: { post: 'title', product: 'name', category: 'label' }
289
+ */
290
+ titleField?: string | Record<string, string>
291
+ /**
292
+ * Callback function to render a custom badge next to the document title.
293
+ * Receives the full document and should return badge data or undefined.
294
+ *
295
+ * @example
296
+ * docBadge: (doc) => {
297
+ * if (doc.services === 'NHS')
298
+ * return { label: 'NHS', bgColor: '#e0f2fe', textColor: '#0369a1' }
299
+ * if (doc.services === 'Private')
300
+ * return { label: 'Private', bgColor: '#fef3c7', textColor: '#92400e' }
301
+ * }
302
+ */
303
+ docBadge?: (doc: DocumentWithSeoHealth & Record<string, unknown>) =>
304
+ | {
305
+ label: string
306
+ bgColor?: string
307
+ textColor?: string
308
+ fontSize?: string
309
+ }
310
+ | undefined
257
311
  }
258
312
  }
259
313
 
@@ -294,6 +348,71 @@ declare interface SeoHealthDashboardProps {
294
348
  * Obtain a key at https://sanity-plugin-seofields.thehardik.in
295
349
  */
296
350
  licenseKey?: string
351
+ /**
352
+ * Map raw `_type` values to human-readable display labels used in the
353
+ * Type column and the Type filter dropdown.
354
+ * Any type without an entry falls back to the raw `_type` string.
355
+ *
356
+ * @example
357
+ * typeLabels={{ productDrug: 'Products', singleCondition: 'Condition' }}
358
+ */
359
+ typeLabels?: Record<string, string>
360
+ /**
361
+ * Controls how the type is rendered in the Type column.
362
+ * - `'badge'` (default) — coloured pill, consistent with score badges
363
+ * - `'text'` — plain text, useful for dense layouts
364
+ */
365
+ typeColumnMode?: 'badge' | 'text'
366
+ /**
367
+ * The document field to use as the display title.
368
+ *
369
+ * - `string` — use this field for every document type (e.g. `'name'`)
370
+ * - `Record<string, string>` — per-type mapping; unmapped types fall back to `title`
371
+ *
372
+ * @example
373
+ * // Same field for all types
374
+ * titleField: 'name'
375
+ *
376
+ * @example
377
+ * // Different field per type
378
+ * titleField: { post: 'title', product: 'name', category: 'label' }
379
+ */
380
+ titleField?: string | Record<string, string>
381
+ /**
382
+ * Callback function to render a custom badge next to the document title.
383
+ * Receives the full document and should return badge data or undefined.
384
+ *
385
+ * @example
386
+ * docBadge: (doc) => {
387
+ * if (doc.services === 'NHS')
388
+ * return { label: 'NHS', bgColor: '#e0f2fe', textColor: '#0369a1' }
389
+ * if (doc.services === 'Private')
390
+ * return { label: 'Private', bgColor: '#fef3c7', textColor: '#92400e' }
391
+ * }
392
+ */
393
+ docBadge?: (doc: DocumentWithSeoHealth & Record<string, unknown>) =>
394
+ | {
395
+ label: string
396
+ bgColor?: string
397
+ textColor?: string
398
+ fontSize?: string
399
+ }
400
+ | undefined
401
+ /**
402
+ * Custom text shown while the license key is being verified.
403
+ * Defaults to `"Verifying license…"`.
404
+ */
405
+ loadingLicense?: React_2.ReactNode
406
+ /**
407
+ * Custom text shown while documents are being fetched.
408
+ * Defaults to `"Loading documents…"`.
409
+ */
410
+ loadingDocuments?: React_2.ReactNode
411
+ /**
412
+ * Custom text shown when the query returns zero results.
413
+ * Defaults to `"No documents found"`.
414
+ */
415
+ noDocuments?: React_2.ReactNode
297
416
  }
298
417
 
299
418
  export declare interface SeoHealthMetrics {
package/dist/index.js CHANGED
@@ -1315,6 +1315,11 @@ const DashboardContainer = dt.div`
1315
1315
  `, ColTitle = dt.div`
1316
1316
  flex: 2;
1317
1317
  min-width: 0;
1318
+ `, TitleWrapper = dt.div`
1319
+ display: flex;
1320
+ align-items: center;
1321
+ gap: 4px;
1322
+ flex-wrap: wrap;
1318
1323
  `, ColType = dt.div`
1319
1324
  flex: 0.8;
1320
1325
  min-width: 80px;
@@ -1354,6 +1359,20 @@ const DashboardContainer = dt.div`
1354
1359
  font-weight: 500;
1355
1360
  background: #ede9fe;
1356
1361
  color: #5b21b6;
1362
+ `, TypeText = dt.span`
1363
+ font-size: 12px;
1364
+ font-weight: 500;
1365
+ color: #374151;
1366
+ `, CustomBadge = dt.span`
1367
+ display: inline-block;
1368
+ padding: 2px 6px;
1369
+ border-radius: 4px;
1370
+ font-size: ${(p) => p.$fontSize || "10px"};
1371
+ font-weight: 600;
1372
+ margin-left: 6px;
1373
+ background: ${(p) => p.$bgColor || "#e0e7ff"};
1374
+ color: ${(p) => p.$textColor || "#3730a3"};
1375
+ white-space: nowrap;
1357
1376
  `, ScoreBadge = dt.span`
1358
1377
  display: inline-block;
1359
1378
  padding: 4px 10px;
@@ -1499,6 +1518,9 @@ const DashboardContainer = dt.div`
1499
1518
  }) => {
1500
1519
  const { onClick, href } = router.useIntentLink({ intent: "edit", params: { id, type } });
1501
1520
  return /* @__PURE__ */ jsxRuntime.jsx(DocTitleLink, { href, onClick, title: "Open document", children });
1521
+ }, DocBadgeRenderer = ({ doc, docBadge }) => {
1522
+ const badge = docBadge(doc);
1523
+ return badge ? /* @__PURE__ */ jsxRuntime.jsx(CustomBadge, { $bgColor: badge.bgColor, $textColor: badge.textColor, $fontSize: badge.fontSize, children: badge.label }) : null;
1502
1524
  }, spin = mt`
1503
1525
  to { transform: rotate(360deg); }
1504
1526
  `, Spinner = dt.div`
@@ -1550,7 +1572,7 @@ const DashboardContainer = dt.div`
1550
1572
  totalScore += twitterScore.score, allIssues.push(...twitterScore.issues), robots2 && !robots2.noIndex && (totalScore += 5);
1551
1573
  const status = getStatusCategory(totalScore);
1552
1574
  return { score: totalScore, status, issues: allIssues };
1553
- }, SeoHealthDashboard = ({
1575
+ }, resolveTypeLabel = (type, typeLabels) => typeLabels?.[type] ?? type, buildTitleProjection = (titleField) => !titleField || titleField === "title" ? "title" : typeof titleField == "string" ? `"title": ${titleField}` : `"title": select(${Object.entries(titleField).map(([type, field]) => `_type == "${type}" => ${field}`).join(", ")}, title)`, SeoHealthDashboard = ({
1554
1576
  icon = "\u{1F4CA}",
1555
1577
  title = "SEO Health Dashboard",
1556
1578
  description = "Monitor and optimize SEO fields across all your documents",
@@ -1560,7 +1582,14 @@ const DashboardContainer = dt.div`
1560
1582
  queryRequireSeo = !0,
1561
1583
  customQuery,
1562
1584
  apiVersion = "2023-01-01",
1563
- licenseKey
1585
+ licenseKey,
1586
+ typeLabels,
1587
+ typeColumnMode = "badge",
1588
+ titleField,
1589
+ docBadge,
1590
+ loadingLicense,
1591
+ loadingDocuments,
1592
+ noDocuments
1564
1593
  }) => {
1565
1594
  const client = sanity.useClient({ apiVersion }), [licenseStatus, setLicenseStatus] = o.useState("loading"), [documents, setDocuments] = o.useState([]), [loading, setLoading] = o.useState(!0), [searchQuery, setSearchQuery] = o.useState(""), [filterStatus, setFilterStatus] = o.useState("all"), [filterType, setFilterType] = o.useState("all"), [sortBy, setSortBy] = o.useState("score"), [activePopover, setActivePopover] = o.useState(null), VALIDATION_ENDPOINT = "https://sanity-plugin-seofields.thehardik.in/api/validate-license", CACHE_TTL_MS = 3600 * 1e3, validateLicense = o.useCallback(
1566
1595
  async (forceRefresh = !1) => {
@@ -1619,17 +1648,23 @@ const DashboardContainer = dt.div`
1619
1648
  try {
1620
1649
  setLoading(!0);
1621
1650
  let groqQuery, params = {};
1622
- customQuery ? groqQuery = customQuery : queryTypes && queryTypes.length > 0 ? (groqQuery = `*[_type in $types${queryRequireSeo ? " && seo != null" : ""} && !(_id in path("drafts.**"))]{
1651
+ if (customQuery)
1652
+ groqQuery = customQuery;
1653
+ else if (queryTypes && queryTypes.length > 0) {
1654
+ const seoFilter = queryRequireSeo ? " && seo != null" : "", titleProj = buildTitleProjection(titleField);
1655
+ groqQuery = `*[_type in $types${seoFilter} && !(_id in path("drafts.**"))]{
1623
1656
  _id,
1624
1657
  _type,
1625
- title,
1658
+ ${titleProj},
1626
1659
  slug,
1627
1660
  seo,
1628
1661
  _updatedAt
1629
- }`, params = { types: queryTypes }) : groqQuery = `*[seo != null && !(_id in path("drafts.**"))]{
1662
+ }`, params = { types: queryTypes };
1663
+ } else
1664
+ groqQuery = `*[seo != null && !(_id in path("drafts.**"))]{
1630
1665
  _id,
1631
1666
  _type,
1632
- title,
1667
+ ${buildTitleProjection(titleField)},
1633
1668
  slug,
1634
1669
  seo,
1635
1670
  _updatedAt
@@ -1645,7 +1680,7 @@ const DashboardContainer = dt.div`
1645
1680
  setLoading(!1);
1646
1681
  }
1647
1682
  })();
1648
- }, [client, customQuery, queryRequireSeo, JSON.stringify(queryTypes)]);
1683
+ }, [client, customQuery, queryRequireSeo, JSON.stringify(queryTypes), JSON.stringify(titleField)]);
1649
1684
  const uniqueDocumentTypes = o.useMemo(() => {
1650
1685
  const types2 = new Set(documents.map((doc) => doc._type));
1651
1686
  return Array.from(types2).sort();
@@ -1663,7 +1698,7 @@ const DashboardContainer = dt.div`
1663
1698
  return /* @__PURE__ */ jsxRuntime.jsxs(DashboardContainer, { children: [
1664
1699
  licenseStatus === "loading" && /* @__PURE__ */ jsxRuntime.jsxs(LoadingState, { style: { padding: "80px 24px" }, children: [
1665
1700
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
1666
- "Verifying license\u2026"
1701
+ loadingLicense ?? "Verifying license\u2026"
1667
1702
  ] }),
1668
1703
  licenseStatus === "invalid" && /* @__PURE__ */ jsxRuntime.jsx(UpgradeContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(UpgradeBox, { children: licenseKey ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1669
1704
  /* @__PURE__ */ jsxRuntime.jsx(UpgradeLock, { children: "\u274C" }),
@@ -1790,7 +1825,7 @@ export default defineConfig({
1790
1825
  onChange: (e) => setFilterType(e.currentTarget.value),
1791
1826
  children: [
1792
1827
  /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Types" }),
1793
- uniqueDocumentTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: type, children: type }, type))
1828
+ uniqueDocumentTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: type, children: resolveTypeLabel(type, typeLabels) }, type))
1794
1829
  ]
1795
1830
  }
1796
1831
  ),
@@ -1809,9 +1844,9 @@ export default defineConfig({
1809
1844
  /* @__PURE__ */ jsxRuntime.jsxs(TableCard, { children: [
1810
1845
  loading && /* @__PURE__ */ jsxRuntime.jsxs(LoadingState, { children: [
1811
1846
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
1812
- "Loading documents\u2026"
1847
+ loadingDocuments ?? "Loading documents\u2026"
1813
1848
  ] }),
1814
- !loading && (filteredAndSortedDocs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { children: "No documents found" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1849
+ !loading && (filteredAndSortedDocs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { children: noDocuments ?? "No documents found" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1815
1850
  /* @__PURE__ */ jsxRuntime.jsxs(TableHeader, { children: [
1816
1851
  /* @__PURE__ */ jsxRuntime.jsx(ColTitle, { children: "Title" }),
1817
1852
  showTypeColumn && /* @__PURE__ */ jsxRuntime.jsx(ColType, { children: "Type" }),
@@ -1819,11 +1854,20 @@ export default defineConfig({
1819
1854
  /* @__PURE__ */ jsxRuntime.jsx(ColIssues, { children: "Top Issues" })
1820
1855
  ] }),
1821
1856
  filteredAndSortedDocs.map((doc) => /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
1822
- /* @__PURE__ */ jsxRuntime.jsxs(ColTitle, { children: [
1823
- /* @__PURE__ */ jsxRuntime.jsx(DocTitleAnchor, { id: doc._id, type: doc._type, children: doc.title || "Untitled" }),
1824
- showDocumentId && /* @__PURE__ */ jsxRuntime.jsx(DocId, { children: doc._id })
1825
- ] }),
1826
- showTypeColumn && /* @__PURE__ */ jsxRuntime.jsx(ColType, { children: /* @__PURE__ */ jsxRuntime.jsx(TypeBadge, { children: doc._type }) }),
1857
+ /* @__PURE__ */ jsxRuntime.jsx(ColTitle, { children: /* @__PURE__ */ jsxRuntime.jsxs(TitleWrapper, { children: [
1858
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1859
+ /* @__PURE__ */ jsxRuntime.jsx(DocTitleAnchor, { id: doc._id, type: doc._type, children: doc.title || "Untitled" }),
1860
+ showDocumentId && /* @__PURE__ */ jsxRuntime.jsx(DocId, { children: doc._id })
1861
+ ] }),
1862
+ docBadge && /* @__PURE__ */ jsxRuntime.jsx(
1863
+ DocBadgeRenderer,
1864
+ {
1865
+ doc,
1866
+ docBadge
1867
+ }
1868
+ )
1869
+ ] }) }),
1870
+ showTypeColumn && /* @__PURE__ */ jsxRuntime.jsx(ColType, { children: typeColumnMode === "text" ? /* @__PURE__ */ jsxRuntime.jsx(TypeText, { children: resolveTypeLabel(doc._type, typeLabels) }) : /* @__PURE__ */ jsxRuntime.jsx(TypeBadge, { children: resolveTypeLabel(doc._type, typeLabels) }) }),
1827
1871
  /* @__PURE__ */ jsxRuntime.jsx(ColScore, { children: /* @__PURE__ */ jsxRuntime.jsxs(ScoreBadge, { $score: doc.health.score, children: [
1828
1872
  doc.health.score,
1829
1873
  "%"
@@ -1918,8 +1962,8 @@ export default defineConfig({
1918
1962
  const feedback = [], charCount = description?.length || 0;
1919
1963
  if (!description?.trim())
1920
1964
  return feedback.push({ text: "Meta description is empty. Add content to improve SEO.", color: "red" }), feedback;
1921
- if (charCount < 150 ? feedback.push({
1922
- text: `Description is ${charCount} chars \u2014 below recommended 150.`,
1965
+ if (charCount < 120 ? feedback.push({
1966
+ text: `Description is ${charCount} chars \u2014 below recommended 120.`,
1923
1967
  color: "orange"
1924
1968
  }) : charCount > 160 ? feedback.push({
1925
1969
  text: `Description is ${charCount} chars \u2014 exceeds recommended 160.`,
@@ -2808,30 +2852,60 @@ function types(config = {}) {
2808
2852
  robots
2809
2853
  ];
2810
2854
  }
2811
- const seofields = sanity.definePlugin((config = {}) => {
2812
- const { healthDashboard = !0 } = config, dashboardEnabled = healthDashboard !== !1, dashboardToolTitle = typeof healthDashboard == "object" ? healthDashboard.tool?.title ?? "SEO Health" : "SEO Health", dashboardName = typeof healthDashboard == "object" ? healthDashboard.tool?.name ?? "seo-health-dashboard" : "seo-health-dashboard", dashboardPageIcon = typeof healthDashboard == "object" ? healthDashboard.content?.icon ?? void 0 : void 0, dashboardPageTitle = typeof healthDashboard == "object" ? healthDashboard.content?.title ?? void 0 : void 0, dashboardDescription = typeof healthDashboard == "object" ? healthDashboard.content?.description ?? void 0 : void 0, dashboardShowTypeColumn = typeof healthDashboard == "object" ? healthDashboard.display?.typeColumn ?? void 0 : void 0, dashboardShowDocumentId = typeof healthDashboard == "object" ? healthDashboard.display?.documentId ?? void 0 : void 0, dashboardQueryTypes = typeof healthDashboard == "object" ? healthDashboard.query?.types ?? void 0 : void 0, dashboardQueryRequireSeo = typeof healthDashboard == "object" ? healthDashboard.query?.requireSeo ?? void 0 : void 0, dashboardQueryGroq = typeof healthDashboard == "object" ? healthDashboard.query?.groq ?? void 0 : void 0, dashboardApiVersion = typeof healthDashboard == "object" ? healthDashboard.apiVersion ?? void 0 : void 0, dashboardLicenseKey = typeof healthDashboard == "object" ? healthDashboard.licenseKey ?? void 0 : void 0, BoundSeoHealthTool = () => o__default.default.createElement(SeoHealthTool, {
2813
- icon: dashboardPageIcon,
2814
- title: dashboardPageTitle,
2815
- description: dashboardDescription,
2816
- showTypeColumn: dashboardShowTypeColumn,
2817
- showDocumentId: dashboardShowDocumentId,
2818
- queryTypes: dashboardQueryTypes,
2819
- queryRequireSeo: dashboardQueryRequireSeo,
2820
- customQuery: dashboardQueryGroq,
2821
- apiVersion: dashboardApiVersion,
2822
- licenseKey: dashboardLicenseKey
2855
+ const resolveDashboardConfig = (healthDashboard) => {
2856
+ const cfg = typeof healthDashboard == "object" ? healthDashboard : void 0;
2857
+ return {
2858
+ enabled: healthDashboard !== !1,
2859
+ toolTitle: cfg?.tool?.title ?? "SEO Health",
2860
+ toolName: cfg?.tool?.name ?? "seo-health-dashboard",
2861
+ icon: cfg?.content?.icon,
2862
+ title: cfg?.content?.title,
2863
+ description: cfg?.content?.description,
2864
+ showTypeColumn: cfg?.display?.typeColumn,
2865
+ showDocumentId: cfg?.display?.documentId,
2866
+ queryTypes: cfg?.query?.types,
2867
+ queryRequireSeo: cfg?.query?.requireSeo,
2868
+ queryGroq: cfg?.query?.groq,
2869
+ apiVersion: cfg?.apiVersion,
2870
+ licenseKey: cfg?.licenseKey,
2871
+ typeLabels: cfg?.typeLabels,
2872
+ typeColumnMode: cfg?.typeColumnMode,
2873
+ titleField: cfg?.titleField,
2874
+ docBadge: cfg?.docBadge,
2875
+ loadingLicense: cfg?.content?.loadingLicense,
2876
+ loadingDocuments: cfg?.content?.loadingDocuments,
2877
+ noDocuments: cfg?.content?.noDocuments
2878
+ };
2879
+ }, seofields = sanity.definePlugin((config = {}) => {
2880
+ const { healthDashboard = !0 } = config, dash = resolveDashboardConfig(healthDashboard), BoundSeoHealthTool = () => o__default.default.createElement(SeoHealthTool, {
2881
+ icon: dash.icon,
2882
+ title: dash.title,
2883
+ description: dash.description,
2884
+ showTypeColumn: dash.showTypeColumn,
2885
+ showDocumentId: dash.showDocumentId,
2886
+ queryTypes: dash.queryTypes,
2887
+ queryRequireSeo: dash.queryRequireSeo,
2888
+ customQuery: dash.queryGroq,
2889
+ apiVersion: dash.apiVersion,
2890
+ licenseKey: dash.licenseKey,
2891
+ typeLabels: dash.typeLabels,
2892
+ typeColumnMode: dash.typeColumnMode,
2893
+ titleField: dash.titleField,
2894
+ docBadge: dash.docBadge,
2895
+ loadingLicense: dash.loadingLicense,
2896
+ loadingDocuments: dash.loadingDocuments,
2897
+ noDocuments: dash.noDocuments
2823
2898
  });
2824
2899
  return {
2825
2900
  name: "sanity-plugin-seofields",
2826
2901
  schema: {
2827
2902
  types: types(config)
2828
- // pass config down to schemas
2829
2903
  },
2830
- ...dashboardEnabled && {
2904
+ ...dash.enabled && {
2831
2905
  tools: [
2832
2906
  {
2833
- name: dashboardName,
2834
- title: dashboardToolTitle,
2907
+ name: dash.toolName,
2908
+ title: dash.toolTitle,
2835
2909
  component: BoundSeoHealthTool,
2836
2910
  icon: () => "\u{1F4CA}"
2837
2911
  }