sanity-plugin-seofields 1.4.1 → 1.5.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.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/dist/SeoHealthDashboard-3VBITMWT.cjs +10 -0
  3. package/dist/SeoHealthDashboard-3VBITMWT.cjs.map +1 -0
  4. package/dist/SeoHealthDashboard-BNJBRQVN.js +4 -0
  5. package/dist/SeoHealthDashboard-BNJBRQVN.js.map +1 -0
  6. package/dist/SeoHealthTool-4P6JST5S.cjs +14 -0
  7. package/dist/SeoHealthTool-4P6JST5S.cjs.map +1 -0
  8. package/dist/SeoHealthTool-MQBE5YGN.js +12 -0
  9. package/dist/SeoHealthTool-MQBE5YGN.js.map +1 -0
  10. package/dist/SeoPreview-G3LPA7GV.js +148 -0
  11. package/dist/SeoPreview-G3LPA7GV.js.map +1 -0
  12. package/dist/SeoPreview-Y3CFDVBR.cjs +154 -0
  13. package/dist/SeoPreview-Y3CFDVBR.cjs.map +1 -0
  14. package/dist/chunk-25JLWVEU.js +472 -0
  15. package/dist/chunk-25JLWVEU.js.map +1 -0
  16. package/dist/chunk-2NMEKWO5.js +35 -0
  17. package/dist/chunk-2NMEKWO5.js.map +1 -0
  18. package/dist/chunk-527WXITP.js +428 -0
  19. package/dist/chunk-527WXITP.js.map +1 -0
  20. package/dist/chunk-6CYMVS3O.js +1245 -0
  21. package/dist/chunk-6CYMVS3O.js.map +1 -0
  22. package/dist/chunk-D2GWRRK5.cjs +1293 -0
  23. package/dist/chunk-D2GWRRK5.cjs.map +1 -0
  24. package/dist/chunk-DYVCCQHT.cjs +1400 -0
  25. package/dist/chunk-DYVCCQHT.cjs.map +1 -0
  26. package/dist/chunk-IFDLKZET.cjs +485 -0
  27. package/dist/chunk-IFDLKZET.cjs.map +1 -0
  28. package/dist/chunk-L3L3FSPJ.cjs +478 -0
  29. package/dist/chunk-L3L3FSPJ.cjs.map +1 -0
  30. package/dist/chunk-S367Y35J.cjs +39 -0
  31. package/dist/chunk-S367Y35J.cjs.map +1 -0
  32. package/dist/chunk-WUIZN7VI.js +1394 -0
  33. package/dist/chunk-WUIZN7VI.js.map +1 -0
  34. package/dist/cli.js +67 -0
  35. package/dist/define-cli.cjs +12 -0
  36. package/dist/define-cli.cjs.map +1 -0
  37. package/dist/define-cli.d.cts +42 -0
  38. package/dist/define-cli.d.ts +42 -0
  39. package/dist/define-cli.js +10 -0
  40. package/dist/define-cli.js.map +1 -0
  41. package/dist/index.cjs +154 -2365
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.js +109 -2303
  44. package/dist/index.js.map +1 -1
  45. package/dist/next.cjs +235 -1591
  46. package/dist/next.cjs.map +1 -1
  47. package/dist/next.js +7 -1482
  48. package/dist/next.js.map +1 -1
  49. package/dist/schema/next.cjs +200 -1542
  50. package/dist/schema/next.cjs.map +1 -1
  51. package/dist/schema/next.js +4 -1475
  52. package/dist/schema/next.js.map +1 -1
  53. package/dist/schema.cjs +252 -1514
  54. package/dist/schema.cjs.map +1 -1
  55. package/dist/schema.js +58 -1391
  56. package/dist/schema.js.map +1 -1
  57. package/package.json +21 -5
package/dist/index.cjs CHANGED
@@ -1,2182 +1,53 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
- var __getProtoOf = Object.getPrototypeOf;
10
- var __hasOwnProp = Object.prototype.hasOwnProperty;
11
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
- var __spreadValues = (a, b) => {
14
- for (var prop in b || (b = {}))
15
- if (__hasOwnProp.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- if (__getOwnPropSymbols)
18
- for (var prop of __getOwnPropSymbols(b)) {
19
- if (__propIsEnum.call(b, prop))
20
- __defNormalProp(a, prop, b[prop]);
21
- }
22
- return a;
23
- };
24
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
- var __objRest = (source, exclude) => {
26
- var target = {};
27
- for (var prop in source)
28
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
- target[prop] = source[prop];
30
- if (source != null && __getOwnPropSymbols)
31
- for (var prop of __getOwnPropSymbols(source)) {
32
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
- target[prop] = source[prop];
34
- }
35
- return target;
36
- };
37
- var __esm = (fn, res) => function __init() {
38
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
39
- };
40
- var __export = (target, all) => {
41
- for (var name in all)
42
- __defProp(target, name, { get: all[name], enumerable: true });
43
- };
44
- var __copyProps = (to, from, except, desc) => {
45
- if (from && typeof from === "object" || typeof from === "function") {
46
- for (let key of __getOwnPropNames(from))
47
- if (!__hasOwnProp.call(to, key) && key !== except)
48
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
49
- }
50
- return to;
51
- };
52
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
53
- // If the importer is in node compatibility mode or this is not an ESM
54
- // file that has been converted to a CommonJS file using a Babel-
55
- // compatible transform (i.e. "__esModule" has not been set), then set
56
- // "default" to the CommonJS "module.exports" for node compatibility.
57
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
58
- mod
59
- ));
60
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
61
-
62
- // src/utils/seoUtils.ts
63
- var stopWords, hasMatchingKeyword, hasKeywordOveruse, startsWithStopWord, truncate, hasExcessivePunctuation, getMetaTitleValidationMessages, getMetaDescriptionValidationMessages, getOgTitleValidation, getOgDescriptionValidation, getTwitterTitleValidation, getTwitterDescriptionValidation, isSubImageSet, isMetaImageSet, getMetaImageValidation, getOgImageValidation, getOgImageUrlValidation, getTwitterImageValidation, getTwitterImageUrlValidation;
64
- var init_seoUtils = __esm({
65
- "src/utils/seoUtils.ts"() {
66
- "use strict";
67
- stopWords = ["the", "a", "an", "and", "or", "but"];
68
- hasMatchingKeyword = (title, keywordList) => {
69
- if (!title || keywordList.length === 0) return false;
70
- const lowerTitle = title.toLowerCase();
71
- return keywordList.some((keyword) => keyword && lowerTitle.includes(keyword.toLowerCase()));
72
- };
73
- hasKeywordOveruse = (title, keywordList, maxOccurrences = 3) => {
74
- if (!title || keywordList.length === 0) return false;
75
- const lowerTitle = title.toLowerCase();
76
- return keywordList.some((keyword) => {
77
- if (!keyword) return false;
78
- const matches = lowerTitle.match(new RegExp(keyword.toLowerCase(), "g"));
79
- return matches ? matches.length > maxOccurrences : false;
80
- });
81
- };
82
- startsWithStopWord = (title) => {
83
- if (!title) return false;
84
- const firstWord = title.trim().split(" ")[0].toLowerCase();
85
- return stopWords.includes(firstWord);
86
- };
87
- truncate = (text, maxLength) => text.length > maxLength ? `${text.slice(0, maxLength)}\u2026` : text;
88
- hasExcessivePunctuation = (title) => /[!@#$%^&*]{2,}/.test(title);
89
- getMetaTitleValidationMessages = (title, keywords, isParentseoField) => {
90
- const feedback = [];
91
- const minChar = 50;
92
- const maxChar = 60;
93
- const charCount = (title == null ? void 0 : title.length) || 0;
94
- if (!(title == null ? void 0 : title.trim())) {
95
- feedback.push({ text: "Meta Title is empty. Add content to improve SEO.", color: "red" });
96
- return feedback;
97
- }
98
- if (charCount < minChar)
99
- feedback.push({
100
- text: `Title is ${charCount} characters \u2014 below recommended ${minChar}.`,
101
- color: "orange"
102
- });
103
- else if (charCount > maxChar)
104
- feedback.push({
105
- text: `Title is ${charCount} characters \u2014 exceeds recommended ${maxChar}.`,
106
- color: "red"
107
- });
108
- else feedback.push({ text: `Title length (${charCount}) looks good for SEO.`, color: "green" });
109
- if (isParentseoField) {
110
- if (keywords.length > 0) {
111
- const hasKeyword = hasMatchingKeyword(title, keywords);
112
- feedback.push({
113
- text: hasKeyword ? "Keyword found in title \u2014 good job!" : "Keywords defined but missing in title.",
114
- color: hasKeyword ? "green" : "red"
115
- });
116
- if (hasKeywordOveruse(title, keywords)) {
117
- feedback.push({
118
- text: "Keyword appears too many times \u2014 avoid keyword stuffing.",
119
- color: "orange"
120
- });
121
- }
122
- } else {
123
- feedback.push({
124
- text: "No keywords defined. Consider adding relevant keywords.",
125
- color: "orange"
126
- });
127
- }
128
- }
129
- if (startsWithStopWord(title))
130
- feedback.push({ text: "Title starts with a stop word \u2014 consider rephrasing.", color: "orange" });
131
- if (hasExcessivePunctuation(title))
132
- feedback.push({ text: "Title contains excessive punctuation \u2014 simplify it.", color: "orange" });
133
- return feedback;
134
- };
135
- getMetaDescriptionValidationMessages = (description, keywords, isParentseoField) => {
136
- const feedback = [];
137
- const minChar = 120;
138
- const maxChar = 160;
139
- const charCount = (description == null ? void 0 : description.length) || 0;
140
- if (!(description == null ? void 0 : description.trim())) {
141
- feedback.push({ text: "Meta description is empty. Add content to improve SEO.", color: "red" });
142
- return feedback;
143
- }
144
- if (charCount < minChar)
145
- feedback.push({
146
- text: `Description is ${charCount} chars \u2014 below recommended ${minChar}.`,
147
- color: "orange"
148
- });
149
- else if (charCount > maxChar)
150
- feedback.push({
151
- text: `Description is ${charCount} chars \u2014 exceeds recommended ${maxChar}.`,
152
- color: "red"
153
- });
154
- else
155
- feedback.push({ text: `Description length (${charCount}) looks good for SEO.`, color: "green" });
156
- if (isParentseoField) {
157
- if (keywords.length > 0) {
158
- const hasKeyword = hasMatchingKeyword(description, keywords);
159
- feedback.push({
160
- text: hasKeyword ? "Keyword found in description \u2014 good job!" : "Keywords defined but missing in description.",
161
- color: hasKeyword ? "green" : "red"
162
- });
163
- if (hasKeywordOveruse(description, keywords)) {
164
- feedback.push({
165
- text: "Keyword appears too many times \u2014 avoid keyword stuffing.",
166
- color: "orange"
167
- });
168
- }
169
- } else {
170
- feedback.push({
171
- text: "No keywords defined. Consider adding relevant keywords.",
172
- color: "orange"
173
- });
174
- }
175
- }
176
- if (startsWithStopWord(description))
177
- feedback.push({
178
- text: "Description starts with a stop word \u2014 consider rephrasing.",
179
- color: "orange"
180
- });
181
- if (hasExcessivePunctuation(description))
182
- feedback.push({
183
- text: "Description contains excessive punctuation \u2014 simplify it.",
184
- color: "orange"
185
- });
186
- return feedback;
187
- };
188
- getOgTitleValidation = (title, keywords = [], isParentseoField) => {
189
- const feedback = [];
190
- const min = 40;
191
- const max = 60;
192
- const count = (title == null ? void 0 : title.length) || 0;
193
- if (!(title == null ? void 0 : title.trim())) {
194
- feedback.push({ text: "OG Title is empty. Add content for better social preview.", color: "red" });
195
- return feedback;
196
- }
197
- if (count < min)
198
- feedback.push({
199
- text: `OG Title is ${count} chars \u2014 shorter than recommended ${min}.`,
200
- color: "orange"
201
- });
202
- else if (count > max)
203
- feedback.push({ text: `OG Title is ${count} chars \u2014 exceeds recommended ${max}.`, color: "red" });
204
- else feedback.push({ text: `OG Title length (${count}) looks good.`, color: "green" });
205
- if (isParentseoField) {
206
- if (keywords.length > 0) {
207
- const hasKeyword = hasMatchingKeyword(title, keywords);
208
- feedback.push({
209
- text: hasKeyword ? "Keyword found in OG title \u2014 good job!" : "Keywords defined but missing in OG title.",
210
- color: hasKeyword ? "green" : "red"
211
- });
212
- if (hasKeywordOveruse(title, keywords)) {
213
- feedback.push({
214
- text: "Keyword appears too many times in OG title \u2014 avoid keyword stuffing.",
215
- color: "orange"
216
- });
217
- }
218
- } else {
219
- feedback.push({
220
- text: "No keywords defined. Consider adding relevant keywords.",
221
- color: "orange"
222
- });
223
- }
224
- }
225
- if (startsWithStopWord(title))
226
- feedback.push({
227
- text: "OG Title starts with a stop word \u2014 consider rephrasing.",
228
- color: "orange"
229
- });
230
- if (hasExcessivePunctuation(title))
231
- feedback.push({ text: "OG Title contains excessive punctuation \u2014 simplify it.", color: "orange" });
232
- return feedback;
233
- };
234
- getOgDescriptionValidation = (desc, keywords = [], isParentseoField) => {
235
- const feedback = [];
236
- const min = 90;
237
- const max = 120;
238
- const count = (desc == null ? void 0 : desc.length) || 0;
239
- if (!(desc == null ? void 0 : desc.trim())) {
240
- feedback.push({
241
- text: "OG Description is empty. Add content for better social preview.",
242
- color: "red"
243
- });
244
- return feedback;
245
- }
246
- if (count < min)
247
- feedback.push({
248
- text: `OG Description is ${count} chars \u2014 shorter than recommended ${min}.`,
249
- color: "orange"
250
- });
251
- else if (count > max)
252
- feedback.push({
253
- text: `OG Description is ${count} chars \u2014 exceeds recommended ${max}.`,
254
- color: "red"
255
- });
256
- else feedback.push({ text: `OG Description length (${count}) looks good.`, color: "green" });
257
- if (isParentseoField) {
258
- if (keywords.length > 0) {
259
- const hasKeyword = hasMatchingKeyword(desc, keywords);
260
- feedback.push({
261
- text: hasKeyword ? "Keyword found in OG description \u2014 good job!" : "Keywords defined but missing in OG description.",
262
- color: hasKeyword ? "green" : "red"
263
- });
264
- if (hasKeywordOveruse(desc, keywords)) {
265
- feedback.push({
266
- text: "Keyword appears too many times in OG description \u2014 avoid keyword stuffing.",
267
- color: "orange"
268
- });
269
- }
270
- } else {
271
- feedback.push({
272
- text: "No keywords defined. Consider adding relevant keywords.",
273
- color: "orange"
274
- });
275
- }
276
- }
277
- if (startsWithStopWord(desc))
278
- feedback.push({
279
- text: "OG Description starts with a stop word \u2014 consider rephrasing.",
280
- color: "orange"
281
- });
282
- if (hasExcessivePunctuation(desc))
283
- feedback.push({
284
- text: "OG Description contains excessive punctuation \u2014 simplify it.",
285
- color: "orange"
286
- });
287
- return feedback;
288
- };
289
- getTwitterTitleValidation = (title, keywords = [], isParentseoField) => {
290
- const feedback = [];
291
- const min = 30;
292
- const max = 70;
293
- const count = (title == null ? void 0 : title.length) || 0;
294
- if (!(title == null ? void 0 : title.trim())) {
295
- feedback.push({ text: "X Title is empty. Add content for better SEO.", color: "red" });
296
- return feedback;
297
- }
298
- if (count < min)
299
- feedback.push({
300
- text: `X Title is ${count} chars \u2014 shorter than recommended ${min}.`,
301
- color: "orange"
302
- });
303
- else if (count > max)
304
- feedback.push({
305
- text: `X Title is ${count} chars \u2014 exceeds recommended ${max}.`,
306
- color: "red"
307
- });
308
- else feedback.push({ text: `X Title length (${count}) looks good.`, color: "green" });
309
- if (isParentseoField) {
310
- if (keywords.length > 0) {
311
- const hasKeyword = hasMatchingKeyword(title, keywords);
312
- feedback.push({
313
- text: hasKeyword ? "Keyword found in X title \u2014 good job!" : "Keywords defined but missing in X title.",
314
- color: hasKeyword ? "green" : "red"
315
- });
316
- } else {
317
- feedback.push({
318
- text: "No keywords defined. Consider adding relevant keywords.",
319
- color: "orange"
320
- });
321
- }
322
- }
323
- if (/[!@#$%^&*]{2,}/.test(title))
324
- feedback.push({ text: "X Title has excessive punctuation \u2014 simplify it.", color: "orange" });
325
- return feedback;
326
- };
327
- getTwitterDescriptionValidation = (desc, keywords = [], isParentseoField) => {
328
- const feedback = [];
329
- const min = 50;
330
- const max = 200;
331
- const count = (desc == null ? void 0 : desc.length) || 0;
332
- if (!(desc == null ? void 0 : desc.trim())) {
333
- feedback.push({ text: "X Description is empty. Add content for better SEO.", color: "red" });
334
- return feedback;
335
- }
336
- if (count < min)
337
- feedback.push({
338
- text: `X Description is ${count} chars \u2014 shorter than recommended ${min}.`,
339
- color: "orange"
340
- });
341
- else if (count > max)
342
- feedback.push({
343
- text: `X Description is ${count} chars \u2014 exceeds recommended ${max}.`,
344
- color: "red"
345
- });
346
- else feedback.push({ text: `X Description length (${count}) looks good.`, color: "green" });
347
- if (isParentseoField) {
348
- if (keywords.length > 0) {
349
- const hasKeyword = hasMatchingKeyword(desc, keywords);
350
- feedback.push({
351
- text: hasKeyword ? "Keyword found in X description \u2014 good job!" : "Keywords defined but missing in X description.",
352
- color: hasKeyword ? "green" : "red"
353
- });
354
- } else {
355
- feedback.push({
356
- text: "No keywords defined. Consider adding relevant keywords.",
357
- color: "orange"
358
- });
359
- }
360
- }
361
- if (/[!@#$%^&*]{2,}/.test(desc))
362
- feedback.push({
363
- text: "X Description has excessive punctuation \u2014 simplify it.",
364
- color: "orange"
365
- });
366
- return feedback;
367
- };
368
- isSubImageSet = (subObj) => {
369
- var _a;
370
- if (!subObj) return false;
371
- if (subObj.imageType === "url") return !!((_a = subObj.imageUrl) == null ? void 0 : _a.trim());
372
- const img = subObj.image;
373
- return !!(img == null ? void 0 : img.asset);
374
- };
375
- isMetaImageSet = (seoParent) => {
376
- if (!seoParent) return false;
377
- const metaImage = seoParent.metaImage;
378
- return !!(metaImage == null ? void 0 : metaImage.asset);
379
- };
380
- getMetaImageValidation = (hasImage, seoParent) => {
381
- const feedback = [];
382
- if (!hasImage) {
383
- feedback.push({
384
- text: "No meta image provided. Adding an image improves click-through rates.",
385
- color: "red"
386
- });
387
- return feedback;
388
- }
389
- feedback.push({ text: "Meta image is set \u2014 great for SEO and social sharing.", color: "green" });
390
- const ogSet = isSubImageSet(seoParent == null ? void 0 : seoParent.openGraph);
391
- const twSet = isSubImageSet(seoParent == null ? void 0 : seoParent.twitter);
392
- if (!ogSet && !twSet) {
393
- feedback.push({
394
- text: "OG and Twitter images are missing \u2014 add them for full social coverage.",
395
- color: "orange"
396
- });
397
- } else if (!ogSet) {
398
- feedback.push({
399
- text: "OG image is missing \u2014 add it for better Facebook/LinkedIn previews.",
400
- color: "orange"
401
- });
402
- } else if (twSet) {
403
- feedback.push({ text: "All images set (Meta, OG, Twitter) \u2014 full coverage!", color: "green" });
404
- } else {
405
- feedback.push({
406
- text: "Twitter image is missing \u2014 add it for better X (Twitter) cards.",
407
- color: "orange"
408
- });
409
- }
410
- return feedback;
411
- };
412
- getOgImageValidation = (hasImage, altText, seoParent) => {
413
- const feedback = [];
414
- if (!hasImage) {
415
- feedback.push({
416
- text: "No OG image provided. Social shares will lack a visual preview.",
417
- color: "red"
418
- });
419
- return feedback;
420
- }
421
- feedback.push({ text: "OG image is set \u2014 good for social sharing.", color: "green" });
422
- if (altText == null ? void 0 : altText.trim()) {
423
- feedback.push({ text: "Alt text is set \u2014 good for accessibility.", color: "green" });
424
- } else {
425
- feedback.push({ text: "Consider adding alt text for better accessibility.", color: "orange" });
426
- }
427
- const metaSet = isMetaImageSet(seoParent);
428
- const twSet = isSubImageSet(seoParent == null ? void 0 : seoParent.twitter);
429
- if (metaSet && twSet) {
430
- feedback.push({ text: "All images set (Meta, OG, Twitter) \u2014 full coverage!", color: "green" });
431
- } else {
432
- if (!metaSet)
433
- feedback.push({
434
- text: "Meta image is missing \u2014 add it for search engine results.",
435
- color: "orange"
436
- });
437
- if (!twSet)
438
- feedback.push({
439
- text: "Twitter image is missing \u2014 add it for X (Twitter) cards.",
440
- color: "orange"
441
- });
442
- }
443
- return feedback;
444
- };
445
- getOgImageUrlValidation = (imageUrl, seoParent) => {
446
- const feedback = [];
447
- if (!(imageUrl == null ? void 0 : imageUrl.trim())) {
448
- feedback.push({
449
- text: "No OG image URL provided. Social shares will lack a visual preview.",
450
- color: "red"
451
- });
452
- return feedback;
453
- }
454
- feedback.push({ text: "OG image URL is set \u2014 good for social sharing.", color: "green" });
455
- const metaSet = isMetaImageSet(seoParent);
456
- const twSet = isSubImageSet(seoParent == null ? void 0 : seoParent.twitter);
457
- if (metaSet && twSet) {
458
- feedback.push({ text: "All images set (Meta, OG, Twitter) \u2014 full coverage!", color: "green" });
459
- } else {
460
- if (!metaSet)
461
- feedback.push({
462
- text: "Meta image is missing \u2014 add it for search engine results.",
463
- color: "orange"
464
- });
465
- if (!twSet)
466
- feedback.push({
467
- text: "Twitter image is missing \u2014 add it for X (Twitter) cards.",
468
- color: "orange"
469
- });
470
- }
471
- return feedback;
472
- };
473
- getTwitterImageValidation = (hasImage, altText, seoParent) => {
474
- const feedback = [];
475
- if (!hasImage) {
476
- feedback.push({
477
- text: "No Twitter image provided. Posts on X will lack a visual.",
478
- color: "red"
479
- });
480
- return feedback;
481
- }
482
- feedback.push({ text: "Twitter image is set \u2014 good for X sharing.", color: "green" });
483
- if (altText == null ? void 0 : altText.trim()) {
484
- feedback.push({ text: "Alt text is set \u2014 good for accessibility.", color: "green" });
485
- } else {
486
- feedback.push({ text: "Consider adding alt text for better accessibility.", color: "orange" });
487
- }
488
- const metaSet = isMetaImageSet(seoParent);
489
- const ogSet = isSubImageSet(seoParent == null ? void 0 : seoParent.openGraph);
490
- if (metaSet && ogSet) {
491
- feedback.push({ text: "All images set (Meta, OG, Twitter) \u2014 full coverage!", color: "green" });
492
- } else {
493
- if (!metaSet)
494
- feedback.push({
495
- text: "Meta image is missing \u2014 add it for search engine results.",
496
- color: "orange"
497
- });
498
- if (!ogSet)
499
- feedback.push({
500
- text: "OG image is missing \u2014 add it for Facebook/LinkedIn sharing.",
501
- color: "orange"
502
- });
503
- }
504
- return feedback;
505
- };
506
- getTwitterImageUrlValidation = (imageUrl, seoParent) => {
507
- const feedback = [];
508
- if (!(imageUrl == null ? void 0 : imageUrl.trim())) {
509
- feedback.push({
510
- text: "No Twitter image URL provided. Posts on X will lack a visual.",
511
- color: "red"
512
- });
513
- return feedback;
514
- }
515
- feedback.push({ text: "Twitter image URL is set \u2014 good for X sharing.", color: "green" });
516
- const metaSet = isMetaImageSet(seoParent);
517
- const ogSet = isSubImageSet(seoParent == null ? void 0 : seoParent.openGraph);
518
- if (metaSet && ogSet) {
519
- feedback.push({ text: "All images set (Meta, OG, Twitter) \u2014 full coverage!", color: "green" });
520
- } else {
521
- if (!metaSet)
522
- feedback.push({
523
- text: "Meta image is missing \u2014 add it for search engine results.",
524
- color: "orange"
525
- });
526
- if (!ogSet)
527
- feedback.push({
528
- text: "OG image is missing \u2014 add it for Facebook/LinkedIn sharing.",
529
- color: "orange"
530
- });
531
- }
532
- return feedback;
533
- };
534
- }
535
- });
536
-
537
- // src/components/SeoPreview.tsx
538
- var SeoPreview_exports = {};
539
- __export(SeoPreview_exports, {
540
- default: () => SeoPreview_default
541
- });
542
- var import_ui12, import_sanity14, import_styled_components, import_jsx_runtime12, PreviewContainer, PreviewHeader, PreviewBody, SerpUrl, SerpTitle, SerpDescription, LiveIndicator, SeoPreview, SeoPreview_default;
543
- var init_SeoPreview = __esm({
544
- "src/components/SeoPreview.tsx"() {
545
- "use strict";
546
- import_ui12 = require("@sanity/ui");
547
- import_sanity14 = require("sanity");
548
- import_styled_components = __toESM(require("styled-components"), 1);
549
- init_seoUtils();
550
- import_jsx_runtime12 = require("react/jsx-runtime");
551
- PreviewContainer = import_styled_components.default.div`
552
- max-width: 600px;
553
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
554
- background: #ffffff;
555
- border: 1px solid #dadce0;
556
- border-radius: 8px;
557
- overflow: hidden;
558
- `;
559
- PreviewHeader = import_styled_components.default.div`
560
- background: #f8f9fa;
561
- padding: 12px 16px;
562
- border-bottom: 1px solid #dadce0;
563
- display: flex;
564
- align-items: center;
565
- justify-content: space-between;
566
- gap: 8px;
567
- `;
568
- PreviewBody = import_styled_components.default.div`
569
- padding: 16px;
570
- `;
571
- SerpUrl = import_styled_components.default.p`
572
- margin: 0 0 4px;
573
- color: #006621;
574
- font-size: 13px;
575
- line-height: 1.4;
576
- word-break: break-word;
577
- `;
578
- SerpTitle = import_styled_components.default.h3`
579
- margin: 0 0 8px;
580
- color: #1a0dab;
581
- font-size: 18px;
582
- font-weight: 500;
583
- line-height: 1.4;
584
- word-break: break-word;
585
-
586
- &:hover {
587
- text-decoration: underline;
588
- }
589
- `;
590
- SerpDescription = import_styled_components.default.p`
591
- margin: 0;
592
- color: #545454;
593
- font-size: 14px;
594
- line-height: 1.6;
595
- word-break: break-word;
596
- display: -webkit-box;
597
- -webkit-line-clamp: 2;
598
- -webkit-box-orient: vertical;
599
- overflow: hidden;
600
- `;
601
- LiveIndicator = import_styled_components.default.span`
602
- display: inline-flex;
603
- align-items: center;
604
- gap: 4px;
605
- font-size: 11px;
606
- font-weight: 600;
607
- text-transform: uppercase;
608
- letter-spacing: 0.05em;
609
- color: #4f46e5;
610
- background: #f0f4ff;
611
- padding: 4px 8px;
612
- border-radius: 4px;
613
- `;
614
- SeoPreview = (props) => {
615
- var _a, _b;
616
- const { path, schemaType } = props;
617
- const { options } = schemaType;
618
- const baseUrl = (options == null ? void 0 : options.baseUrl) || "https://www.example.com";
619
- const prefixFunction = options == null ? void 0 : options.prefix;
620
- const parent = (0, import_sanity14.useFormValue)([path[0]]) || {
621
- title: "",
622
- description: "",
623
- canonicalUrl: ""
624
- };
625
- const rootDoc = (0, import_sanity14.useFormValue)([]) || {
626
- slug: { current: "" }
627
- };
628
- const slug = ((_a = rootDoc == null ? void 0 : rootDoc.slug) == null ? void 0 : _a.current) || "";
629
- const {
630
- title,
631
- description,
632
- canonicalUrl: url
633
- } = parent;
634
- const base = (_b = url || baseUrl) == null ? void 0 : _b.replace(/\/+$/, "");
635
- const slugStr = String(slug || "").replace(/^\/+/, "");
636
- const pref = String(
637
- prefixFunction ? prefixFunction(rootDoc) : ""
638
- ).replace(/^\/+|\/+$/g, "");
639
- const urlPath = [pref, slugStr].filter(Boolean).join("/");
640
- const finalUrl = urlPath ? `${base}/${urlPath}` : base;
641
- const domain = (() => {
642
- try {
643
- const u = new URL(finalUrl || base);
644
- return u.hostname;
645
- } catch (e) {
646
- return "example.com";
647
- }
648
- })();
649
- const urlDisplay = `${domain}${urlPath ? ` \u203A ${urlPath.split("/").slice(-1)[0]}` : ""}`;
650
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ui12.Box, { padding: 3, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(PreviewContainer, { children: [
651
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(PreviewHeader, { children: [
652
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
653
- "span",
654
- {
655
- style: {
656
- fontSize: "11px",
657
- color: "#5f6368",
658
- textTransform: "uppercase",
659
- letterSpacing: "0.05em"
660
- },
661
- children: "Search Preview"
662
- }
663
- ),
664
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(LiveIndicator, { children: [
665
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
666
- "span",
667
- {
668
- style: {
669
- width: "4px",
670
- height: "4px",
671
- borderRadius: "50%",
672
- backgroundColor: "#4f46e5",
673
- display: "inline-block"
674
- }
675
- }
676
- ),
677
- "Live"
678
- ] })
679
- ] }),
680
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(PreviewBody, { children: [
681
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SerpUrl, { children: finalUrl ? urlDisplay : "example.com \u203A page-url" }),
682
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SerpTitle, { children: title && title.length > 0 ? truncate(title, 60) : "Your SEO Title will appear here" }),
683
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SerpDescription, { children: description && description.length > 0 ? truncate(description, 160) : "Your meta description will show up here. Make it compelling!" })
684
- ] })
685
- ] }) });
686
- };
687
- SeoPreview_default = SeoPreview;
688
- }
689
- });
690
-
691
- // src/components/SeoHealthDashboard.tsx
692
- var SeoHealthDashboard_exports = {};
693
- __export(SeoHealthDashboard_exports, {
694
- default: () => SeoHealthDashboard_default
695
- });
696
- var import_react13, import_sanity19, import_router, import_structure, import_styled_components2, import_jsx_runtime13, DashboardContainer, PageHeader, PageTitle, PreviewBadge, PageSubtitle, StatsGrid, StatCard, StatLabel, StatValue, ControlsBar, SearchWrapper, SearchIconSvg, SearchInput, StyledSelect, TableCard, TableHeader, TableRow, ColTitle, TitleWrapper, TitleCell, ColType, ColScore, ColIssues, DocTitleLink, DocId, TypeBadge, TypeText, CustomBadge, ScoreBadge, IssueTag, NonStringTitleWarning, MoreIssues, MoreIssuesWrapper, IssuesPopover, PopoverIssueItem, UpgradeContainer, UpgradeBox, UpgradeLock, UpgradeTitle, UpgradeText, UpgradeCode, UpgradeButton, ReloadButton, spin, DashboardRefreshButton, DocTitleAnchor, PaneLinkWrapper, DocTitleAnchorPane, DocBadgeRenderer, Spinner, LoadingState, EmptyState, DeprecationBanner, DeprecationBannerLink, TYPE_COLOR_PALETTE, getTypeColor, getStatusCategory, scoreMetaTitle, scoreMetaDescription, scoreOpenGraph, scoreTwitterCard, calculateHealthScore, resolveTypeLabel, buildTitleProjection, generateDummyData, SeoHealthDashboard, SeoHealthDashboard_default;
697
- var init_SeoHealthDashboard = __esm({
698
- "src/components/SeoHealthDashboard.tsx"() {
699
- "use strict";
700
- import_react13 = require("react");
701
- import_sanity19 = require("sanity");
702
- import_router = require("sanity/router");
703
- import_structure = require("sanity/structure");
704
- import_styled_components2 = __toESM(require("styled-components"), 1);
705
- import_jsx_runtime13 = require("react/jsx-runtime");
706
- DashboardContainer = import_styled_components2.default.div`
707
- width: 100%;
708
- min-height: 100%;
709
- background: #f0f2f5;
710
- padding: 28px 32px;
711
- box-sizing: border-box;
712
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
713
- `;
714
- PageHeader = import_styled_components2.default.div`
715
- display: flex;
716
- align-items: flex-start;
717
- justify-content: space-between;
718
- gap: 12px;
719
- margin-bottom: 28px;
720
- `;
721
- PageTitle = import_styled_components2.default.h1`
722
- margin: 0 0 6px 0;
723
- font-size: 22px;
724
- font-weight: 700;
725
- color: #111827;
726
- letter-spacing: -0.3px;
727
- display: flex;
728
- align-items: center;
729
- gap: 10px;
730
- `;
731
- PreviewBadge = import_styled_components2.default.span`
732
- display: inline-block;
733
- background: #fef3c7;
734
- color: #92400e;
735
- font-size: 11px;
736
- font-weight: 600;
737
- padding: 4px 8px;
738
- border-radius: 4px;
739
- text-transform: uppercase;
740
- letter-spacing: 0.5px;
741
- margin-left: 8px;
742
- `;
743
- PageSubtitle = import_styled_components2.default.p`
744
- margin: 0;
745
- font-size: 13px;
746
- color: #6b7280;
747
- `;
748
- StatsGrid = import_styled_components2.default.div`
749
- display: grid;
750
- grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
751
- gap: 14px;
752
- margin-bottom: 20px;
753
- `;
754
- StatCard = import_styled_components2.default.div`
755
- background: #ffffff;
756
- border-radius: 10px;
757
- padding: 16px 18px;
758
- box-shadow:
759
- 0 1px 3px rgba(0, 0, 0, 0.07),
760
- 0 1px 2px rgba(0, 0, 0, 0.05);
761
- border-left: ${(p) => p.$accent ? `4px solid ${p.$accent}` : "4px solid transparent"};
762
- transition: box-shadow 0.15s ease;
763
-
764
- &:hover {
765
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
766
- }
767
- `;
768
- StatLabel = import_styled_components2.default.div`
769
- font-size: 11px;
770
- font-weight: 500;
771
- color: #9ca3af;
772
- text-transform: uppercase;
773
- letter-spacing: 0.5px;
774
- margin-bottom: 8px;
775
- `;
776
- StatValue = import_styled_components2.default.div`
777
- font-size: 26px;
778
- font-weight: 700;
779
- color: #111827;
780
- line-height: 1;
781
- `;
782
- ControlsBar = import_styled_components2.default.div`
783
- background: #ffffff;
784
- border-radius: 10px;
785
- padding: 14px 18px;
786
- display: flex;
787
- align-items: center;
788
- gap: 12px;
789
- flex-wrap: wrap;
790
- margin-bottom: 20px;
791
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
792
- `;
793
- SearchWrapper = import_styled_components2.default.div`
794
- position: relative;
795
- flex: 1;
796
- min-width: 220px;
797
- `;
798
- SearchIconSvg = import_styled_components2.default.span`
799
- position: absolute;
800
- left: 11px;
801
- top: 50%;
802
- transform: translateY(-50%);
803
- color: #9ca3af;
804
- display: flex;
805
- align-items: center;
806
- pointer-events: none;
807
- `;
808
- SearchInput = import_styled_components2.default.input`
809
- width: 100%;
810
- height: 36px;
811
- padding: 0 12px 0 34px;
812
- border: 1px solid #e5e7eb;
813
- border-radius: 7px;
814
- font-size: 13px;
815
- color: #111827;
816
- background: #f9fafb;
817
- box-sizing: border-box;
818
- outline: none;
819
- transition:
820
- border-color 0.15s,
821
- background 0.15s;
822
-
823
- &::placeholder {
824
- color: #9ca3af;
825
- }
826
-
827
- &:focus {
828
- border-color: #6366f1;
829
- background: #fff;
830
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
831
- }
832
- `;
833
- StyledSelect = import_styled_components2.default.select`
834
- height: 36px;
835
- padding: 0 32px 0 12px;
836
- border: 1px solid #e5e7eb;
837
- border-radius: 7px;
838
- font-size: 13px;
839
- color: #374151;
840
- background: #f9fafb
841
- url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M6 8L1 3h10z'/%3E%3C/svg%3E")
842
- no-repeat right 10px center;
843
- appearance: none;
844
- outline: none;
845
- cursor: pointer;
846
- transition: border-color 0.15s;
1
+ 'use strict';
847
2
 
848
- &:focus {
849
- border-color: #6366f1;
850
- background-color: #fff;
851
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
852
- }
853
- `;
854
- TableCard = import_styled_components2.default.div`
855
- background: #ffffff;
856
- border-radius: 10px;
857
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
858
- overflow: hidden;
859
- `;
860
- TableHeader = import_styled_components2.default.div`
861
- display: flex;
862
- align-items: center;
863
- padding: 11px 20px;
864
- background: #f9fafb;
865
- border-bottom: 1px solid #e5e7eb;
866
- font-size: 11px;
867
- font-weight: 600;
868
- color: #6b7280;
869
- text-transform: uppercase;
870
- letter-spacing: 0.5px;
871
- gap: 12px;
872
- `;
873
- TableRow = import_styled_components2.default.div`
874
- display: flex;
875
- align-items: center;
876
- padding: 13px 20px;
877
- border-bottom: 1px solid #f3f4f6;
878
- gap: 12px;
879
- transition: background 0.1s;
880
-
881
- &:last-child {
882
- border-bottom: none;
883
- }
884
-
885
- &:hover {
886
- background: #fafafa;
887
- }
888
- `;
889
- ColTitle = import_styled_components2.default.div`
890
- flex: 2;
891
- min-width: 0;
892
- `;
893
- TitleWrapper = import_styled_components2.default.div`
894
- display: flex;
895
- align-items: center;
896
- gap: 4px;
897
- flex-wrap: wrap;
898
- min-width: 0;
899
- `;
900
- TitleCell = import_styled_components2.default.div`
901
- min-width: 0;
902
- overflow: hidden;
903
- flex: 1;
904
- `;
905
- ColType = import_styled_components2.default.div`
906
- flex: 0.8;
907
- min-width: 80px;
908
- `;
909
- ColScore = import_styled_components2.default.div`
910
- flex: 0.6;
911
- min-width: 70px;
912
- `;
913
- ColIssues = import_styled_components2.default.div`
914
- flex: 2;
915
- min-width: 0;
916
- `;
917
- DocTitleLink = import_styled_components2.default.a`
918
- font-size: 13px;
919
- font-weight: 600;
920
- color: #4f46e5;
921
- white-space: nowrap;
922
- overflow: hidden;
923
- text-overflow: ellipsis;
924
- text-decoration: none;
925
- display: block;
926
- transition: color 0.15s;
927
-
928
- &:hover {
929
- color: #4338ca;
930
- text-decoration: underline;
931
- }
932
- `;
933
- DocId = import_styled_components2.default.div`
934
- font-size: 11px;
935
- color: #9ca3af;
936
- margin-top: 2px;
937
- white-space: nowrap;
938
- overflow: hidden;
939
- text-overflow: ellipsis;
940
- `;
941
- TypeBadge = import_styled_components2.default.span`
942
- display: inline-block;
943
- padding: 3px 8px;
944
- border-radius: 5px;
945
- font-size: 11px;
946
- font-weight: 500;
947
- background: ${(p) => p.$bgColor || "#ede9fe"};
948
- color: ${(p) => p.$textColor || "#5b21b6"};
949
- `;
950
- TypeText = import_styled_components2.default.span`
951
- font-size: 12px;
952
- font-weight: 500;
953
- color: #374151;
954
- `;
955
- CustomBadge = import_styled_components2.default.span`
956
- display: inline-block;
957
- padding: 2px 6px;
958
- border-radius: 4px;
959
- font-size: ${(p) => p.$fontSize || "10px"};
960
- font-weight: 600;
961
- background: ${(p) => p.$bgColor || "#e0e7ff"};
962
- color: ${(p) => p.$textColor || "#3730a3"};
963
- white-space: nowrap;
964
- `;
965
- ScoreBadge = import_styled_components2.default.span`
966
- display: inline-block;
967
- padding: 4px 10px;
968
- border-radius: 6px;
969
- font-size: 12px;
970
- font-weight: 700;
971
- background: ${(p) => {
972
- if (p.$score >= 80) return "#d1fae5";
973
- if (p.$score >= 60) return "#fef3c7";
974
- if (p.$score >= 40) return "#ffedd5";
975
- return "#fee2e2";
976
- }};
977
- color: ${(p) => {
978
- if (p.$score >= 80) return "#065f46";
979
- if (p.$score >= 60) return "#92400e";
980
- if (p.$score >= 40) return "#9a3412";
981
- return "#991b1b";
982
- }};
983
- `;
984
- IssueTag = import_styled_components2.default.div`
985
- font-size: 11px;
986
- color: #ef4444;
987
- line-height: 1.5;
988
- white-space: nowrap;
989
- overflow: hidden;
990
- text-overflow: ellipsis;
991
- `;
992
- NonStringTitleWarning = import_styled_components2.default.div`
993
- display: inline-flex;
994
- align-items: center;
995
- gap: 4px;
996
- margin-top: 4px;
997
- padding: 2px 7px;
998
- border-radius: 4px;
999
- background: #fef3c7;
1000
- border: 1px solid #fcd34d;
1001
- font-size: 10px;
1002
- font-weight: 600;
1003
- color: #92400e;
1004
- line-height: 1.4;
1005
- cursor: default;
1006
- white-space: normal;
1007
- `;
1008
- MoreIssues = import_styled_components2.default.div`
1009
- font-size: 11px;
1010
- color: #6b7280;
1011
- cursor: pointer;
1012
- transition: color 0.15s;
1013
-
1014
- &:hover {
1015
- color: #374151;
1016
- }
1017
- `;
1018
- MoreIssuesWrapper = import_styled_components2.default.div`
1019
- position: relative;
1020
- display: inline-block;
1021
- `;
1022
- IssuesPopover = import_styled_components2.default.div`
1023
- position: fixed;
1024
- bottom: auto;
1025
- left: 0;
1026
- transform: translateY(calc(-100% - 14px));
1027
- background: #1f2937;
1028
- color: #ffffff;
1029
- padding: 12px;
1030
- border-radius: 8px;
1031
- font-size: 12px;
1032
- z-index: 50;
1033
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
1034
- width: 280px;
1035
- word-break: break-word;
1036
- line-height: 1.5;
3
+ Object.defineProperty(exports, '__esModule', { value: true });
1037
4
 
1038
- &::after {
1039
- content: '';
1040
- position: absolute;
1041
- bottom: -6px;
1042
- left: 12px;
1043
- width: 0;
1044
- height: 0;
1045
- border-left: 6px solid transparent;
1046
- border-right: 6px solid transparent;
1047
- border-top: 6px solid #1f2937;
1048
- }
1049
- `;
1050
- PopoverIssueItem = import_styled_components2.default.div`
1051
- display: flex;
1052
- gap: 6px;
1053
- margin-bottom: 6px;
5
+ var chunkIFDLKZET_cjs = require('./chunk-IFDLKZET.cjs');
6
+ var chunkS367Y35J_cjs = require('./chunk-S367Y35J.cjs');
7
+ var React12 = require('react');
8
+ var sanity = require('sanity');
9
+ var ui = require('@sanity/ui');
10
+ var jsxRuntime = require('react/jsx-runtime');
1054
11
 
1055
- &:last-child {
1056
- margin-bottom: 0;
1057
- }
1058
- `;
1059
- UpgradeContainer = import_styled_components2.default.div`
1060
- display: flex;
1061
- align-items: center;
1062
- justify-content: center;
1063
- min-height: 100%;
1064
- padding: 60px 24px;
1065
- `;
1066
- UpgradeBox = import_styled_components2.default.div`
1067
- background: #ffffff;
1068
- border-radius: 16px;
1069
- padding: 48px 40px;
1070
- max-width: 480px;
1071
- width: 100%;
1072
- text-align: center;
1073
- box-shadow:
1074
- 0 4px 24px rgba(0, 0, 0, 0.08),
1075
- 0 1px 4px rgba(0, 0, 0, 0.05);
1076
- border: 1px solid #e5e7eb;
1077
- `;
1078
- UpgradeLock = import_styled_components2.default.div`
1079
- font-size: 40px;
1080
- margin-bottom: 16px;
1081
- `;
1082
- UpgradeTitle = import_styled_components2.default.h2`
1083
- margin: 0 0 10px;
1084
- font-size: 20px;
1085
- font-weight: 700;
1086
- color: #111827;
1087
- `;
1088
- UpgradeText = import_styled_components2.default.p`
1089
- margin: 0 0 20px;
1090
- font-size: 14px;
1091
- color: #6b7280;
1092
- line-height: 1.6;
1093
- `;
1094
- UpgradeCode = import_styled_components2.default.pre`
1095
- background: #f3f4f6;
1096
- border-radius: 8px;
1097
- padding: 14px 16px;
1098
- font-size: 12px;
1099
- color: #374151;
1100
- text-align: left;
1101
- margin: 0 0 24px;
1102
- overflow-x: auto;
1103
- line-height: 1.6;
1104
- border: 1px solid #e5e7eb;
1105
- `;
1106
- UpgradeButton = import_styled_components2.default.a`
1107
- display: inline-block;
1108
- background: #4f46e5;
1109
- color: #ffffff;
1110
- font-size: 14px;
1111
- font-weight: 600;
1112
- padding: 10px 24px;
1113
- border-radius: 8px;
1114
- text-decoration: none;
1115
- transition: background 0.15s;
12
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
1116
13
 
1117
- &:hover {
1118
- background: #4338ca;
1119
- }
1120
- `;
1121
- ReloadButton = import_styled_components2.default.button`
1122
- display: inline-block;
1123
- background: transparent;
1124
- color: #6b7280;
1125
- font-size: 13px;
1126
- font-weight: 500;
1127
- padding: 8px 20px;
1128
- border-radius: 8px;
1129
- border: 1px solid #d1d5db;
1130
- cursor: pointer;
1131
- margin-top: 10px;
1132
- transition:
1133
- background 0.15s,
1134
- color 0.15s,
1135
- border-color 0.15s;
14
+ var React12__default = /*#__PURE__*/_interopDefault(React12);
1136
15
 
1137
- &:hover {
1138
- background: #f3f4f6;
1139
- color: #374151;
1140
- border-color: #9ca3af;
1141
- }
1142
- `;
1143
- spin = import_styled_components2.keyframes`
1144
- to { transform: rotate(360deg); }
1145
- `;
1146
- DashboardRefreshButton = import_styled_components2.default.button`
1147
- display: inline-flex;
1148
- align-items: center;
1149
- gap: 6px;
1150
- background: #ffffff;
1151
- color: #374151;
1152
- font-size: 13px;
1153
- font-weight: 500;
1154
- padding: 8px 14px;
1155
- border-radius: 8px;
1156
- border: 1px solid #d1d5db;
1157
- cursor: pointer;
1158
- flex-shrink: 0;
1159
- transition:
1160
- background 0.15s,
1161
- color 0.15s,
1162
- border-color 0.15s,
1163
- box-shadow 0.15s;
1164
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
1165
-
1166
- svg {
1167
- animation: ${(p) => p.$spinning ? import_styled_components2.css`
1168
- ${spin} 0.7s linear infinite
1169
- ` : "none"};
1170
- }
1171
-
1172
- &:hover {
1173
- background: #f3f4f6;
1174
- border-color: #9ca3af;
1175
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
1176
- }
1177
-
1178
- &:disabled {
1179
- opacity: 0.6;
1180
- cursor: not-allowed;
1181
- }
1182
- `;
1183
- DocTitleAnchor = ({ id, type, structureTool, children }) => {
1184
- const { basePath } = (0, import_sanity19.useWorkspace)();
1185
- const { onClick: intentOnClick, href: intentHref } = (0, import_router.useIntentLink)({
1186
- intent: "edit",
1187
- params: { id, type }
1188
- });
1189
- const href = structureTool ? `${basePath}/${structureTool}/intent/edit/id=${id};type=${type}/` : intentHref;
1190
- const onClick = structureTool ? void 0 : intentOnClick;
1191
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DocTitleLink, { href, onClick, title: "Open document", children });
1192
- };
1193
- PaneLinkWrapper = import_styled_components2.default.span`
1194
- display: block;
1195
- min-width: 0;
1196
- overflow: hidden;
1197
-
1198
- a {
1199
- font-size: 13px;
1200
- font-weight: 600;
1201
- color: #4f46e5;
1202
- white-space: nowrap;
1203
- overflow: hidden;
1204
- text-overflow: ellipsis;
1205
- text-decoration: none;
1206
- display: block;
1207
- transition: color 0.15s;
1208
-
1209
- &:hover {
1210
- color: #4338ca;
1211
- text-decoration: underline;
1212
- }
1213
- }
1214
- `;
1215
- DocTitleAnchorPane = ({
1216
- id,
1217
- type,
1218
- children
1219
- }) => {
1220
- const { ChildLink } = (0, import_structure.usePaneRouter)();
1221
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PaneLinkWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChildLink, { childId: id, childParameters: { type }, children }) });
1222
- };
1223
- DocBadgeRenderer = ({ doc, docBadge }) => {
1224
- const badge = docBadge(doc);
1225
- if (!badge) return null;
1226
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CustomBadge, { $bgColor: badge.bgColor, $textColor: badge.textColor, $fontSize: badge.fontSize, children: badge.label });
1227
- };
1228
- Spinner = import_styled_components2.default.div`
1229
- width: 28px;
1230
- height: 28px;
1231
- border: 3px solid #e5e7eb;
1232
- border-top-color: #6366f1;
1233
- border-radius: 50%;
1234
- animation: ${spin} 0.7s linear infinite;
1235
- margin: 0 auto 12px;
1236
- `;
1237
- LoadingState = import_styled_components2.default.div`
1238
- padding: 48px 24px;
1239
- text-align: center;
1240
- color: #6b7280;
1241
- font-size: 13px;
1242
- `;
1243
- EmptyState = import_styled_components2.default.div`
1244
- padding: 48px 24px;
1245
- text-align: center;
1246
- color: #9ca3af;
1247
- font-size: 13px;
1248
- `;
1249
- DeprecationBanner = import_styled_components2.default.div`
1250
- background: #fffbeb;
1251
- border: 1px solid #fcd34d;
1252
- border-radius: 8px;
1253
- padding: 10px 14px;
1254
- font-size: 12px;
1255
- color: #78350f;
1256
- margin-bottom: 16px;
1257
- line-height: 1.6;
1258
- `;
1259
- DeprecationBannerLink = import_styled_components2.default.a`
1260
- color: #92400e;
1261
- font-weight: 600;
1262
- text-decoration: underline;
1263
- &:hover {
1264
- color: #78350f;
1265
- }
1266
- `;
1267
- TYPE_COLOR_PALETTE = [
1268
- { bg: "#dbeafe", text: "#0c4a6e" },
1269
- // Blue
1270
- { bg: "#dcfce7", text: "#14532d" },
1271
- // Green
1272
- { bg: "#fce7f3", text: "#500724" },
1273
- // Pink
1274
- { bg: "#fed7aa", text: "#7c2d12" },
1275
- // Orange
1276
- { bg: "#e9d5ff", text: "#581c87" },
1277
- // Purple
1278
- { bg: "#f3e8ff", text: "#3f0f5c" },
1279
- // Deep Purple
1280
- { bg: "#ccfbf1", text: "#134e4a" },
1281
- // Teal
1282
- { bg: "#ddd6fe", text: "#3730a3" },
1283
- // Indigo
1284
- { bg: "#fca5a5", text: "#7f1d1d" },
1285
- // Red
1286
- { bg: "#a7f3d0", text: "#065f46" },
1287
- // Emerald
1288
- { bg: "#fbbf24", text: "#78350f" },
1289
- // Amber
1290
- { bg: "#c4b5fd", text: "#3b0764" },
1291
- // Violet
1292
- { bg: "#f0fdf4", text: "#15803d" },
1293
- // Light Green
1294
- { bg: "#fef2f2", text: "#991b1b" },
1295
- // Light Red
1296
- { bg: "#f5f3ff", text: "#5b21b6" },
1297
- // Light Purple
1298
- { bg: "#fffbeb", text: "#92400e" }
1299
- // Light Amber
1300
- ];
1301
- getTypeColor = (type) => {
1302
- let hash = 0;
1303
- for (let i = 0; i < type.length; i += 1) {
1304
- const char = type.charCodeAt(i);
1305
- hash = Math.abs(hash * 31 + char);
1306
- }
1307
- const colorIndex = hash % TYPE_COLOR_PALETTE.length;
1308
- return TYPE_COLOR_PALETTE[colorIndex];
1309
- };
1310
- getStatusCategory = (score) => {
1311
- if (score >= 80) return "excellent";
1312
- if (score >= 60) return "good";
1313
- if (score >= 40) return "fair";
1314
- if (score > 0) return "poor";
1315
- return "missing";
1316
- };
1317
- scoreMetaTitle = (title) => {
1318
- const issues = [];
1319
- let score = 0;
1320
- if (title && title.length >= 50 && title.length <= 60) {
1321
- score = 15;
1322
- } else if (title && title.length > 0) {
1323
- score = 10;
1324
- if (title.length < 50) issues.push("Meta title too short (< 50 chars)");
1325
- if (title.length > 60) issues.push("Meta title too long (> 60 chars)");
1326
- } else {
1327
- issues.push("Missing meta title");
1328
- }
1329
- return { score, issues };
1330
- };
1331
- scoreMetaDescription = (description) => {
1332
- const issues = [];
1333
- let score = 0;
1334
- if (description && description.length >= 120 && description.length <= 160) {
1335
- score = 15;
1336
- } else if (description && description.length > 0) {
1337
- score = 10;
1338
- if (description.length < 120) issues.push("Meta description too short (< 120 chars)");
1339
- if (description.length > 160) issues.push("Meta description too long (> 160 chars)");
1340
- } else {
1341
- issues.push("Missing meta description");
1342
- }
1343
- return { score, issues };
1344
- };
1345
- scoreOpenGraph = (openGraph2) => {
1346
- const issues = [];
1347
- let score = 0;
1348
- if (openGraph2) {
1349
- if (openGraph2.title) score += 6;
1350
- else issues.push("Missing OG title");
1351
- if (openGraph2.description) score += 6;
1352
- else issues.push("Missing OG description");
1353
- if (openGraph2.image) score += 6;
1354
- else issues.push("Missing OG image");
1355
- if (openGraph2.type) score += 7;
1356
- else issues.push("Missing OG type");
1357
- } else {
1358
- issues.push("Open Graph not configured");
1359
- }
1360
- return { score, issues };
1361
- };
1362
- scoreTwitterCard = (twitter2) => {
1363
- const issues = [];
1364
- let score = 0;
1365
- if (twitter2) {
1366
- if (twitter2.title) score += 5;
1367
- else issues.push("Missing Twitter title");
1368
- if (twitter2.description) score += 5;
1369
- else issues.push("Missing Twitter description");
1370
- if (twitter2.image) score += 5;
1371
- else issues.push("Missing Twitter image");
1372
- } else {
1373
- issues.push("Twitter Card not configured");
1374
- }
1375
- return { score, issues };
1376
- };
1377
- calculateHealthScore = (doc) => {
1378
- if (!doc.seo) {
1379
- return { score: 0, status: "missing", issues: ["SEO fields not configured"] };
1380
- }
1381
- const { title, description, keywords, robots, canonicalUrl, openGraph: openGraph2, twitter: twitter2 } = doc.seo;
1382
- let score = 0;
1383
- const issues = [];
1384
- const titleResult = scoreMetaTitle(title);
1385
- score += titleResult.score;
1386
- issues.push(...titleResult.issues);
1387
- const descResult = scoreMetaDescription(description);
1388
- score += descResult.score;
1389
- issues.push(...descResult.issues);
1390
- if (doc.seo.metaImage) score += 10;
1391
- else issues.push("Missing meta image");
1392
- if (keywords && keywords.length > 0) score += 10;
1393
- else issues.push("No keywords defined");
1394
- if (robots && !robots.noIndex) score += 5;
1395
- else if (!robots) score += 5;
1396
- if (canonicalUrl) score += 0;
1397
- const ogResult = scoreOpenGraph(openGraph2);
1398
- score += ogResult.score;
1399
- issues.push(...ogResult.issues);
1400
- const twResult = scoreTwitterCard(twitter2);
1401
- score += twResult.score;
1402
- issues.push(...twResult.issues);
1403
- const hasMetaImage = !!doc.seo.metaImage;
1404
- const hasOgImage = !!(openGraph2 && openGraph2.image);
1405
- const hasTwitterImage = !!(twitter2 && twitter2.image);
1406
- if (hasMetaImage && hasOgImage && hasTwitterImage) {
1407
- score += 5;
1408
- } else {
1409
- const missingImages = [];
1410
- if (!hasMetaImage) missingImages.push("meta image");
1411
- if (!hasOgImage) missingImages.push("OG image");
1412
- if (!hasTwitterImage) missingImages.push("Twitter image");
1413
- issues.push(`Missing images for full score: ${missingImages.join(", ")}`);
1414
- }
1415
- const status = getStatusCategory(score);
1416
- return { score, status, issues };
1417
- };
1418
- resolveTypeLabel = (type, typeLabels) => {
1419
- var _a;
1420
- return (_a = typeLabels == null ? void 0 : typeLabels[type]) != null ? _a : type;
1421
- };
1422
- buildTitleProjection = (titleField) => {
1423
- if (!titleField || titleField === "title") return "title";
1424
- if (typeof titleField === "string") return `"title": ${titleField}`;
1425
- const cases = Object.entries(titleField).map(([type, field]) => `_type == "${type}" => ${field}`).join(", ");
1426
- return `"title": select(${cases}, title)`;
1427
- };
1428
- generateDummyData = () => {
1429
- const dummyDocs = [
1430
- {
1431
- _id: "preview-post-1",
1432
- _type: "post",
1433
- title: "Getting Started with SEO Best Practices",
1434
- slug: { current: "getting-started-seo" },
1435
- _updatedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1e3).toISOString(),
1436
- seo: {
1437
- title: "Getting Started with SEO Best Practices | My Blog",
1438
- description: "Learn the fundamentals of SEO optimization to improve your website visibility and search rankings.",
1439
- keywords: ["seo", "best practices", "optimization"],
1440
- metaImage: { _type: "image", asset: { _ref: "image-123", _type: "reference" } },
1441
- openGraph: {
1442
- title: "SEO Best Practices Guide",
1443
- description: "Master SEO optimization",
1444
- image: { _type: "image", asset: { _ref: "image-123", _type: "reference" }, alt: "SEO Guide" },
1445
- type: "article"
1446
- },
1447
- twitter: {
1448
- title: "SEO Best Practices",
1449
- description: "Learn SEO optimization",
1450
- image: { _type: "image", asset: { _ref: "image-123", _type: "reference" }, alt: "Guide" },
1451
- card: "summary_large_image"
1452
- }
1453
- }
1454
- },
1455
- {
1456
- _id: "preview-post-2",
1457
- _type: "post",
1458
- title: "Advanced Analytics Strategy",
1459
- slug: { current: "advanced-analytics" },
1460
- _updatedAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1e3).toISOString(),
1461
- seo: {
1462
- title: "Advanced Analytics",
1463
- description: "Strategy tips",
1464
- keywords: ["analytics", "data"],
1465
- openGraph: {
1466
- title: "Analytics Guide"
1467
- }
1468
- }
1469
- },
1470
- {
1471
- _id: "preview-page-1",
1472
- _type: "page",
1473
- title: "About Us",
1474
- slug: { current: "about" },
1475
- _updatedAt: new Date(Date.now() - 10 * 24 * 60 * 60 * 1e3).toISOString(),
1476
- seo: {
1477
- title: "About",
1478
- keywords: ["company", "team"],
1479
- metaImage: { _type: "image", asset: { _ref: "image-456", _type: "reference" } }
1480
- }
1481
- },
1482
- {
1483
- _id: "preview-post-3",
1484
- _type: "post",
1485
- title: "Content Marketing Trends for 2024",
1486
- slug: { current: "content-marketing-trends" },
1487
- _updatedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1e3).toISOString(),
1488
- seo: {
1489
- title: "Content Marketing Trends 2024",
1490
- description: "Discover the latest content marketing trends and strategies to engage your audience effectively.",
1491
- keywords: ["content marketing", "trends", "strategy", "engagement"],
1492
- metaImage: { _type: "image", asset: { _ref: "image-789", _type: "reference" } },
1493
- openGraph: {
1494
- title: "Content Marketing Trends 2024",
1495
- description: "Latest trends in content marketing",
1496
- image: { _type: "image", asset: { _ref: "image-789", _type: "reference" }, alt: "Trends" },
1497
- type: "article"
1498
- },
1499
- twitter: {
1500
- title: "Content Marketing Trends",
1501
- description: "Discover the latest trends",
1502
- card: "summary"
1503
- }
1504
- }
1505
- },
1506
- {
1507
- _id: "preview-post-4",
1508
- _type: "product",
1509
- title: "Pro Plan",
1510
- slug: { current: "pro-plan" },
1511
- _updatedAt: new Date(Date.now() - 15 * 24 * 60 * 60 * 1e3).toISOString(),
1512
- seo: {
1513
- title: "Pro",
1514
- keywords: ["pricing"]
1515
- }
1516
- },
1517
- {
1518
- _id: "preview-page-2",
1519
- _type: "page",
1520
- title: "Contact",
1521
- slug: { current: "contact" },
1522
- _updatedAt: new Date(Date.now() - 8 * 24 * 60 * 60 * 1e3).toISOString(),
1523
- seo: {
1524
- openGraph: {
1525
- title: "Get in Touch"
1526
- }
1527
- }
1528
- },
1529
- {
1530
- _id: "preview-post-5",
1531
- _type: "post",
1532
- title: "Mobile Optimization Guide",
1533
- slug: { current: "mobile-optimization" },
1534
- _updatedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1e3).toISOString(),
1535
- seo: {
1536
- title: "Mobile Optimization Guide: Best Practices for Responsive Design",
1537
- description: "Complete guide to mobile optimization including responsive design, performance tips, and user experience best practices for modern web development.",
1538
- keywords: ["mobile", "optimization", "responsive", "performance"],
1539
- metaImage: { _type: "image", asset: { _ref: "image-mobile", _type: "reference" } },
1540
- openGraph: {
1541
- title: "Mobile Optimization Best Practices",
1542
- description: "Master mobile web optimization",
1543
- image: { _type: "image", asset: { _ref: "image-mobile", _type: "reference" }, alt: "Mobile" },
1544
- type: "article"
1545
- },
1546
- twitter: {
1547
- title: "Mobile Optimization Tips",
1548
- description: "Responsive design best practices",
1549
- image: { _type: "image", asset: { _ref: "image-mobile", _type: "reference" }, alt: "Mobile" },
1550
- card: "summary_large_image"
1551
- }
1552
- }
1553
- }
1554
- ];
1555
- return dummyDocs.map((doc) => __spreadProps(__spreadValues({}, doc), {
1556
- health: calculateHealthScore(doc)
1557
- }));
1558
- };
1559
- SeoHealthDashboard = ({
1560
- icon = "\u{1F4CA}",
1561
- title = "SEO Health Dashboard",
1562
- description = "Monitor and optimize SEO fields across all your documents",
1563
- showTypeColumn = true,
1564
- showDocumentId = true,
1565
- queryTypes,
1566
- queryRequireSeo = true,
1567
- customQuery,
1568
- apiVersion = "2023-01-01",
1569
- licenseKey,
1570
- typeDisplayLabels,
1571
- typeColumnMode = "badge",
1572
- titleField,
1573
- getDocumentBadge,
1574
- loadingLicense,
1575
- loadingDocuments,
1576
- noDocuments,
1577
- previewMode = false,
1578
- openInPane = false,
1579
- structureTool,
1580
- _deprecationWarnings
1581
- }) => {
1582
- const resolvedTypeLabels = typeDisplayLabels;
1583
- const resolvedDocBadge = getDocumentBadge;
1584
- const allDeprecationWarnings = (0, import_react13.useMemo)(() => _deprecationWarnings != null ? _deprecationWarnings : [], [_deprecationWarnings]);
1585
- const deprecationGroups = (0, import_react13.useMemo)(() => {
1586
- const groups = /* @__PURE__ */ new Map();
1587
- for (const w of allDeprecationWarnings) {
1588
- if (!groups.has(w.version)) {
1589
- groups.set(w.version, { version: w.version, changelogUrl: w.changelogUrl, keys: [] });
1590
- }
1591
- groups.get(w.version).keys.push(w.key);
1592
- }
1593
- return Array.from(groups.values());
1594
- }, [allDeprecationWarnings]);
1595
- const client = (0, import_sanity19.useClient)({ apiVersion });
1596
- const [licenseStatus, setLicenseStatus] = (0, import_react13.useState)("loading");
1597
- const [documents, setDocuments] = (0, import_react13.useState)([]);
1598
- const [loading, setLoading] = (0, import_react13.useState)(true);
1599
- const [isRefreshing, setIsRefreshing] = (0, import_react13.useState)(false);
1600
- const [searchQuery, setSearchQuery] = (0, import_react13.useState)("");
1601
- const [filterStatus, setFilterStatus] = (0, import_react13.useState)("all");
1602
- const [filterType, setFilterType] = (0, import_react13.useState)("all");
1603
- const [sortBy, setSortBy] = (0, import_react13.useState)("score");
1604
- const [activePopover, setActivePopover] = (0, import_react13.useState)(null);
1605
- const VALIDATION_ENDPOINT = "https://sanity-plugin-seofields.thehardik.in/api/validate-license";
1606
- const CACHE_TTL_MS = 60 * 60 * 1e3;
1607
- const validateLicense = (0, import_react13.useCallback)(
1608
- async (forceRefresh = false) => {
1609
- var _a;
1610
- if (previewMode) {
1611
- setLicenseStatus("valid");
1612
- return;
1613
- }
1614
- if (!licenseKey) {
1615
- setLicenseStatus("invalid");
1616
- return;
1617
- }
1618
- const projectId = (_a = client.config().projectId) != null ? _a : "";
1619
- const cacheKey = `seofields_license_${projectId}`;
1620
- if (forceRefresh) {
1621
- try {
1622
- sessionStorage.removeItem(cacheKey);
1623
- } catch (e) {
1624
- }
1625
- }
1626
- if (!forceRefresh) {
1627
- try {
1628
- const cached = sessionStorage.getItem(cacheKey);
1629
- if (cached) {
1630
- const { valid, ts } = JSON.parse(cached);
1631
- if (Date.now() - ts < CACHE_TTL_MS) {
1632
- setLicenseStatus(valid ? "valid" : "invalid");
1633
- return;
1634
- }
1635
- }
1636
- } catch (e) {
1637
- }
1638
- }
1639
- setLicenseStatus("loading");
1640
- try {
1641
- const res = await fetch(VALIDATION_ENDPOINT, {
1642
- method: "POST",
1643
- headers: { "Content-Type": "application/json" },
1644
- body: JSON.stringify({ licenseKey, projectId })
1645
- });
1646
- const valid = res.ok;
1647
- setLicenseStatus(valid ? "valid" : "invalid");
1648
- try {
1649
- sessionStorage.setItem(cacheKey, JSON.stringify({ valid, ts: Date.now() }));
1650
- } catch (e) {
1651
- }
1652
- } catch (e) {
1653
- setLicenseStatus("valid");
1654
- }
1655
- },
1656
- // eslint-disable-next-line react-hooks/exhaustive-deps
1657
- [licenseKey, previewMode]
1658
- );
1659
- (0, import_react13.useEffect)(() => {
1660
- validateLicense();
1661
- }, [licenseKey, previewMode]);
1662
- const handleMouseEnterIssues = (el, issues) => {
1663
- if (!el) return;
1664
- const rect = el.getBoundingClientRect();
1665
- const popoverWidth = 280;
1666
- const viewportWidth = window.innerWidth;
1667
- let left = rect.left;
1668
- if (left + popoverWidth > viewportWidth - 10) left = viewportWidth - popoverWidth - 10;
1669
- if (left < 10) left = 10;
1670
- setActivePopover({ top: rect.top, left, issues });
1671
- };
1672
- const JSONStringifiedQueryTypes = JSON.stringify(queryTypes);
1673
- const JSONStringifiedTitleField = JSON.stringify(titleField);
1674
- const fetchDocuments = (0, import_react13.useCallback)(
1675
- async (isManualRefresh = false) => {
1676
- try {
1677
- if (isManualRefresh) {
1678
- setIsRefreshing(true);
1679
- } else {
1680
- setLoading(true);
1681
- }
1682
- if (previewMode) {
1683
- setDocuments(generateDummyData());
1684
- return;
1685
- }
1686
- let groqQuery;
1687
- let params = {};
1688
- if (customQuery) {
1689
- groqQuery = customQuery;
1690
- } else if (queryTypes && queryTypes.length > 0) {
1691
- const seoFilter = queryRequireSeo ? " && seo != null" : "";
1692
- const titleProj = buildTitleProjection(titleField);
1693
- groqQuery = `*[_type in $types${seoFilter} && !(_id in path("drafts.**"))]{
1694
- _id,
1695
- _type,
1696
- ${titleProj},
1697
- slug,
1698
- seo,
1699
- _updatedAt
1700
- }`;
1701
- params = { types: queryTypes };
1702
- } else {
1703
- const titleProj = buildTitleProjection(titleField);
1704
- groqQuery = `*[seo != null && !(_id in path("drafts.**"))]{
1705
- _id,
1706
- _type,
1707
- ${titleProj},
1708
- slug,
1709
- seo,
1710
- _updatedAt
1711
- }`;
1712
- }
1713
- const result = await client.fetch(groqQuery, params, { perspective: "published" });
1714
- const docsWithHealth = result.map((doc) => __spreadProps(__spreadValues({}, doc), {
1715
- health: calculateHealthScore(doc)
1716
- }));
1717
- setDocuments(docsWithHealth);
1718
- } catch (error) {
1719
- console.error("Error fetching documents:", error);
1720
- } finally {
1721
- setLoading(false);
1722
- setIsRefreshing(false);
1723
- }
1724
- },
1725
- // eslint-disable-next-line react-hooks/exhaustive-deps
1726
- [
1727
- client,
1728
- customQuery,
1729
- queryRequireSeo,
1730
- JSONStringifiedQueryTypes,
1731
- JSONStringifiedTitleField,
1732
- previewMode
1733
- ]
1734
- );
1735
- (0, import_react13.useEffect)(() => {
1736
- fetchDocuments();
1737
- }, [
1738
- client,
1739
- customQuery,
1740
- queryRequireSeo,
1741
- JSONStringifiedQueryTypes,
1742
- JSONStringifiedTitleField,
1743
- previewMode
1744
- ]);
1745
- const handleRefresh = (0, import_react13.useCallback)(() => {
1746
- fetchDocuments(true);
1747
- }, [fetchDocuments]);
1748
- const uniqueDocumentTypes = (0, import_react13.useMemo)(() => {
1749
- const types2 = new Set(documents.map((doc) => doc._type));
1750
- return Array.from(types2).sort();
1751
- }, [documents]);
1752
- const filteredAndSortedDocs = (0, import_react13.useMemo)(() => {
1753
- let filtered = documents;
1754
- if (searchQuery) {
1755
- filtered = filtered.filter(
1756
- (doc) => {
1757
- var _a, _b;
1758
- return ((_a = doc.title) == null ? void 0 : _a.toLowerCase().includes(searchQuery.toLowerCase())) || ((_b = doc._id) == null ? void 0 : _b.toLowerCase().includes(searchQuery.toLowerCase()));
1759
- }
1760
- );
1761
- }
1762
- if (filterStatus !== "all") {
1763
- filtered = filtered.filter((doc) => doc.health.status === filterStatus);
1764
- }
1765
- if (filterType !== "all") {
1766
- filtered = filtered.filter((doc) => doc._type === filterType);
1767
- }
1768
- const sorted = [...filtered].sort((a, b) => {
1769
- if (sortBy === "score") {
1770
- return b.health.score - a.health.score;
1771
- }
1772
- return (a.title || "").localeCompare(b.title || "");
1773
- });
1774
- return sorted;
1775
- }, [documents, searchQuery, filterStatus, filterType, sortBy]);
1776
- const stats = (0, import_react13.useMemo)(() => {
1777
- const total = documents.length;
1778
- const excellent = documents.filter((d) => d.health.score >= 80).length;
1779
- const good = documents.filter((d) => d.health.score >= 60 && d.health.score < 80).length;
1780
- const fair = documents.filter((d) => d.health.score >= 40 && d.health.score < 60).length;
1781
- const poor = documents.filter((d) => d.health.score > 0 && d.health.score < 40).length;
1782
- const missing = documents.filter((d) => d.health.score === 0).length;
1783
- const avgScore = total > 0 ? Math.round(documents.reduce((sum, d) => sum + d.health.score, 0) / total) : 0;
1784
- return { total, excellent, good, fair, poor, missing, avgScore };
1785
- }, [documents]);
1786
- const handleMouseLeave = (0, import_react13.useCallback)(() => {
1787
- setActivePopover(null);
1788
- }, []);
1789
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DashboardContainer, { children: [
1790
- licenseStatus === "loading" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(LoadingState, { style: { padding: "80px 24px" }, children: [
1791
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Spinner, {}),
1792
- loadingLicense != null ? loadingLicense : "Verifying license\u2026"
1793
- ] }),
1794
- licenseStatus === "invalid" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeBox, { children: licenseKey ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1795
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeLock, { children: "\u274C" }),
1796
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeTitle, { children: "Invalid License Key" }),
1797
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeText, { children: "The license key you provided is invalid or has been revoked. Please check your key and update it in the plugin config." }),
1798
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeCode, { children: `seofields({
1799
- healthDashboard: {
1800
- licenseKey: 'YOUR_LICENSE_KEY', // \u2190 replace with a valid key
1801
- },
1802
- })` }),
1803
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1804
- UpgradeButton,
1805
- {
1806
- href: "https://sanity-plugin-seofields.thehardik.in",
1807
- target: "_blank",
1808
- rel: "noopener noreferrer",
1809
- children: "Get a New License Key \u2192"
1810
- }
1811
- ),
1812
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
1813
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ReloadButton, { onClick: () => validateLicense(true), children: "Click here If You Just Updated Your Key" })
1814
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1815
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeLock, { children: "\u{1F512}" }),
1816
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeTitle, { children: "SEO Health Dashboard" }),
1817
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeText, { children: "This feature requires a license key. Add your key to the plugin config to unlock the full dashboard." }),
1818
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(UpgradeCode, { children: `// sanity.config.ts
1819
- import { seofields } from 'sanity-plugin-seofields'
1820
-
1821
- export default defineConfig({
1822
- plugins: [
1823
- seofields({
1824
- healthDashboard: {
1825
- licenseKey: 'SEOF-XXXX-XXXX-XXXX',
1826
- },
1827
- }),
1828
- ],
1829
- })` }),
1830
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1831
- UpgradeButton,
1832
- {
1833
- href: "https://sanity-plugin-seofields.thehardik.in",
1834
- target: "_blank",
1835
- rel: "noopener noreferrer",
1836
- children: "Get a License Key \u2192"
1837
- }
1838
- )
1839
- ] }) }) }),
1840
- licenseStatus === "valid" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1841
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(PageHeader, { children: [
1842
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1843
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(PageTitle, { children: [
1844
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1845
- icon,
1846
- " ",
1847
- title
1848
- ] }),
1849
- previewMode && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PreviewBadge, { children: "Preview Mode" })
1850
- ] }),
1851
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PageSubtitle, { children: description })
1852
- ] }),
1853
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1854
- DashboardRefreshButton,
1855
- {
1856
- onClick: handleRefresh,
1857
- disabled: loading || isRefreshing,
1858
- $spinning: isRefreshing,
1859
- title: "Refresh documents",
1860
- children: [
1861
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1862
- "svg",
1863
- {
1864
- width: "14",
1865
- height: "14",
1866
- viewBox: "0 0 24 24",
1867
- fill: "none",
1868
- stroke: "currentColor",
1869
- strokeWidth: "2.2",
1870
- strokeLinecap: "round",
1871
- strokeLinejoin: "round",
1872
- children: [
1873
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("polyline", { points: "23 4 23 10 17 10" }),
1874
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("polyline", { points: "1 20 1 14 7 14" }),
1875
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
1876
- ]
1877
- }
1878
- ),
1879
- "Refresh"
1880
- ]
1881
- }
1882
- )
1883
- ] }),
1884
- deprecationGroups.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DeprecationBanner, { children: [
1885
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "\u26A0\uFE0F Deprecated config keys detected:" }),
1886
- " ",
1887
- deprecationGroups.map((group, gi) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1888
- group.keys.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1889
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { style: { background: "#fef9c3", padding: "1px 4px", borderRadius: 3 }, children: w.split("\u2192")[0].trim() }),
1890
- " \u2192 ",
1891
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { style: { background: "#dcfce7", padding: "1px 4px", borderRadius: 3 }, children: w.split("\u2192")[1].trim() }),
1892
- i < group.keys.length - 1 ? " \xB7 " : ""
1893
- ] }, w)),
1894
- " ",
1895
- "(",
1896
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1897
- DeprecationBannerLink,
1898
- {
1899
- href: group.changelogUrl,
1900
- target: "_blank",
1901
- rel: "noopener noreferrer",
1902
- children: [
1903
- group.version,
1904
- " changelog"
1905
- ]
1906
- }
1907
- ),
1908
- ")",
1909
- gi < deprecationGroups.length - 1 ? " \xB7 " : ""
1910
- ] }, group.version)),
1911
- " ",
1912
- "\u2014 Please update your config."
1913
- ] }),
1914
- !loading && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatsGrid, { children: [
1915
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatCard, { children: [
1916
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatLabel, { children: "Total Docs" }),
1917
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatValue, { children: stats.total })
1918
- ] }),
1919
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatCard, { children: [
1920
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatLabel, { children: "Avg Score" }),
1921
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatValue, { children: [
1922
- stats.avgScore,
1923
- "%"
1924
- ] })
1925
- ] }),
1926
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatCard, { $accent: "#10b981", children: [
1927
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatLabel, { children: "Excellent (80+)" }),
1928
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatValue, { children: stats.excellent })
1929
- ] }),
1930
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatCard, { $accent: "#f59e0b", children: [
1931
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatLabel, { children: "Good (60\u201379)" }),
1932
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatValue, { children: stats.good })
1933
- ] }),
1934
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatCard, { $accent: "#f97316", children: [
1935
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatLabel, { children: "Fair (40\u201359)" }),
1936
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatValue, { children: stats.fair })
1937
- ] }),
1938
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(StatCard, { $accent: "#ef4444", children: [
1939
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatLabel, { children: "Poor / Missing" }),
1940
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StatValue, { children: stats.poor + stats.missing })
1941
- ] })
1942
- ] }),
1943
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ControlsBar, { children: [
1944
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(SearchWrapper, { children: [
1945
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SearchIconSvg, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1946
- "path",
1947
- {
1948
- fillRule: "evenodd",
1949
- d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",
1950
- clipRule: "evenodd"
1951
- }
1952
- ) }) }),
1953
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1954
- SearchInput,
1955
- {
1956
- placeholder: "Search documents...",
1957
- value: searchQuery,
1958
- onChange: (e) => setSearchQuery(e.currentTarget.value)
1959
- }
1960
- )
1961
- ] }),
1962
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1963
- StyledSelect,
1964
- {
1965
- value: filterStatus,
1966
- onChange: (e) => setFilterStatus(e.currentTarget.value),
1967
- children: [
1968
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "all", children: "All Status" }),
1969
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "excellent", children: "Excellent" }),
1970
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "good", children: "Good" }),
1971
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "fair", children: "Fair" }),
1972
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "poor", children: "Poor" }),
1973
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "missing", children: "Missing" })
1974
- ]
1975
- }
1976
- ),
1977
- uniqueDocumentTypes.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1978
- StyledSelect,
1979
- {
1980
- value: filterType,
1981
- onChange: (e) => setFilterType(e.currentTarget.value),
1982
- children: [
1983
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "all", children: "All Types" }),
1984
- uniqueDocumentTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: type, children: resolveTypeLabel(type, resolvedTypeLabels) }, type))
1985
- ]
1986
- }
1987
- ),
1988
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1989
- StyledSelect,
1990
- {
1991
- value: sortBy,
1992
- onChange: (e) => setSortBy(e.currentTarget.value),
1993
- children: [
1994
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "score", children: "Sort by Score" }),
1995
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "title", children: "Sort by Title" })
1996
- ]
1997
- }
1998
- )
1999
- ] }),
2000
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TableCard, { children: [
2001
- loading && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(LoadingState, { children: [
2002
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Spinner, {}),
2003
- loadingDocuments != null ? loadingDocuments : "Loading documents\u2026"
2004
- ] }),
2005
- !loading && (filteredAndSortedDocs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EmptyState, { children: noDocuments != null ? noDocuments : "No documents found" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2006
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TableHeader, { children: [
2007
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColTitle, { children: "Title" }),
2008
- showTypeColumn && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColType, { children: "Type" }),
2009
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColScore, { children: "Score" }),
2010
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColIssues, { children: "Top Issues" })
2011
- ] }),
2012
- filteredAndSortedDocs.map((doc) => {
2013
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TableRow, { children: [
2014
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColTitle, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TitleWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TitleCell, { children: [
2015
- doc.title !== null && typeof doc.title !== "string" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NonStringTitleWarning, { title: "title is not a string \u2014 use pt::text(title) in your query.groq projection to convert Portable Text to a plain string", children: "\u26A0 title is not a string \u2014 use pt::text(title) in query.groq" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: openInPane ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DocTitleAnchorPane, { id: doc._id, type: doc._type, children: typeof doc.title === "string" ? doc.title || "Untitled" : "Untitled" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2016
- DocTitleAnchor,
2017
- {
2018
- id: doc._id,
2019
- type: doc._type,
2020
- structureTool,
2021
- children: typeof doc.title === "string" ? doc.title || "Untitled" : "Untitled"
2022
- }
2023
- ) }),
2024
- showDocumentId && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DocId, { children: doc._id }),
2025
- resolvedDocBadge && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2026
- DocBadgeRenderer,
2027
- {
2028
- doc,
2029
- docBadge: resolvedDocBadge
2030
- }
2031
- )
2032
- ] }) }) }),
2033
- showTypeColumn && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColType, { children: typeColumnMode === "text" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TypeText, { children: resolveTypeLabel(doc._type, resolvedTypeLabels) }) : (() => {
2034
- const typeColor = getTypeColor(doc._type);
2035
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TypeBadge, { $bgColor: typeColor.bg, $textColor: typeColor.text, children: resolveTypeLabel(doc._type, resolvedTypeLabels) });
2036
- })() }),
2037
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ColScore, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ScoreBadge, { $score: doc.health.score, children: [
2038
- doc.health.score,
2039
- "%"
2040
- ] }) }),
2041
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ColIssues, { children: [
2042
- doc.health.issues.slice(0, 2).map((issue) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(IssueTag, { children: [
2043
- "\u2022 ",
2044
- issue
2045
- ] }, `issue-${doc._id}-${issue}`)),
2046
- doc.health.issues.length > 2 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2047
- MoreIssuesWrapper,
2048
- {
2049
- onMouseEnter: function(e) {
2050
- handleMouseEnterIssues(
2051
- e.currentTarget,
2052
- doc.health.issues.slice(2)
2053
- );
2054
- },
2055
- onMouseLeave: handleMouseLeave,
2056
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(MoreIssues, { children: [
2057
- "+",
2058
- doc.health.issues.length - 2,
2059
- " more issues"
2060
- ] })
2061
- }
2062
- )
2063
- ] })
2064
- ] }, doc._id);
2065
- })
2066
- ] }))
2067
- ] }),
2068
- activePopover && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2069
- IssuesPopover,
2070
- {
2071
- style: {
2072
- top: activePopover.top,
2073
- left: activePopover.left,
2074
- transform: "translateY(calc(-100% - 10px))"
2075
- },
2076
- children: activePopover.issues.map((issue) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(PopoverIssueItem, { children: [
2077
- "\u26A0\uFE0F ",
2078
- issue
2079
- ] }, issue))
2080
- }
2081
- ),
2082
- " "
2083
- ] }),
2084
- " "
2085
- ] });
2086
- };
2087
- SeoHealthDashboard_default = SeoHealthDashboard;
2088
- }
2089
- });
2090
-
2091
- // src/components/SeoHealthTool.tsx
2092
- var SeoHealthTool_exports = {};
2093
- __export(SeoHealthTool_exports, {
2094
- default: () => SeoHealthTool_default
2095
- });
2096
- var import_jsx_runtime14, SeoHealthTool, SeoHealthTool_default;
2097
- var init_SeoHealthTool = __esm({
2098
- "src/components/SeoHealthTool.tsx"() {
2099
- "use strict";
2100
- init_SeoHealthDashboard();
2101
- import_jsx_runtime14 = require("react/jsx-runtime");
2102
- SeoHealthTool = (props) => {
2103
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SeoHealthDashboard_default, __spreadValues({}, props));
2104
- };
2105
- SeoHealthTool_default = SeoHealthTool;
2106
- }
2107
- });
2108
-
2109
- // src/index.ts
2110
- var src_exports = {};
2111
- __export(src_exports, {
2112
- allSchemas: () => types,
2113
- createSeoHealthPane: () => createSeoHealthPane,
2114
- default: () => src_default,
2115
- metaAttributeSchema: () => metaAttribute_default,
2116
- metaTagSchema: () => metaTag_default,
2117
- openGraphSchema: () => openGraph,
2118
- robotsSchema: () => robots_default,
2119
- seoFieldsSchema: () => seoFieldsSchema,
2120
- twitterSchema: () => twitter
2121
- });
2122
- module.exports = __toCommonJS(src_exports);
2123
-
2124
- // src/plugin.ts
2125
- var import_react14 = __toESM(require("react"), 1);
2126
- var import_sanity20 = require("sanity");
2127
-
2128
- // src/schemas/index.ts
2129
- var import_react12 = __toESM(require("react"), 1);
2130
- var import_sanity15 = require("sanity");
2131
-
2132
- // src/components/meta/MetaDescription.tsx
2133
- var import_ui = require("@sanity/ui");
2134
- var import_react = require("react");
2135
- var import_sanity = require("sanity");
2136
- init_seoUtils();
2137
- var import_jsx_runtime = require("react/jsx-runtime");
2138
16
  var MetaDescription = (props) => {
2139
17
  const { value, renderDefault, path } = props;
2140
- const parent = (0, import_sanity.useFormValue)([path[0]]);
18
+ const parent = sanity.useFormValue([path[0]]);
2141
19
  const isParentseoField = parent && (parent == null ? void 0 : parent._type) === "seoFields";
2142
- const keywords = (0, import_react.useMemo)(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
2143
- const feedbackItems = (0, import_react.useMemo)(
2144
- () => getMetaDescriptionValidationMessages(value || "", keywords, isParentseoField),
20
+ const keywords = React12.useMemo(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
21
+ const feedbackItems = React12.useMemo(
22
+ () => chunkIFDLKZET_cjs.getMetaDescriptionValidationMessages(value || "", keywords, isParentseoField),
2145
23
  [value, keywords, isParentseoField]
2146
24
  );
2147
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ui.Stack, { space: 3, children: [
25
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2148
26
  renderDefault(props),
2149
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2150
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
27
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
28
+ /* @__PURE__ */ jsxRuntime.jsx(
2151
29
  "div",
2152
30
  {
2153
31
  style: { width: 10, height: 10, borderRadius: "50%", backgroundColor: item.color }
2154
32
  }
2155
33
  ),
2156
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
34
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2157
35
  ] }, item.text)) })
2158
36
  ] });
2159
37
  };
2160
38
  var MetaDescription_default = MetaDescription;
2161
-
2162
- // src/components/meta/MetaImage.tsx
2163
- var import_ui2 = require("@sanity/ui");
2164
- var import_react2 = require("react");
2165
- var import_sanity2 = require("sanity");
2166
- init_seoUtils();
2167
- var import_jsx_runtime2 = require("react/jsx-runtime");
2168
39
  var MetaImage = (props) => {
2169
40
  const { value, renderDefault, path } = props;
2170
- const seoParent = (0, import_sanity2.useFormValue)([path[0]]);
41
+ const seoParent = sanity.useFormValue([path[0]]);
2171
42
  const hasImage = !!(value == null ? void 0 : value.asset);
2172
- const feedbackItems = (0, import_react2.useMemo)(
2173
- () => getMetaImageValidation(hasImage, seoParent),
43
+ const feedbackItems = React12.useMemo(
44
+ () => chunkIFDLKZET_cjs.getMetaImageValidation(hasImage, seoParent),
2174
45
  [hasImage, seoParent]
2175
46
  );
2176
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ui2.Stack, { space: 3, children: [
47
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2177
48
  renderDefault(props),
2178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2179
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
49
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
50
+ /* @__PURE__ */ jsxRuntime.jsx(
2180
51
  "div",
2181
52
  {
2182
53
  style: {
@@ -2187,31 +58,24 @@ var MetaImage = (props) => {
2187
58
  }
2188
59
  }
2189
60
  ),
2190
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui2.Text, { weight: "bold", muted: true, size: 14, children: item.text })
61
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2191
62
  ] }, item.text)) })
2192
63
  ] });
2193
64
  };
2194
65
  var MetaImage_default = MetaImage;
2195
-
2196
- // src/components/meta/MetaTitle.tsx
2197
- var import_ui3 = require("@sanity/ui");
2198
- var import_react3 = require("react");
2199
- var import_sanity3 = require("sanity");
2200
- init_seoUtils();
2201
- var import_jsx_runtime3 = require("react/jsx-runtime");
2202
66
  var MetaTitle = (props) => {
2203
67
  const { value, renderDefault, path } = props;
2204
- const parent = (0, import_sanity3.useFormValue)([path[0]]);
68
+ const parent = sanity.useFormValue([path[0]]);
2205
69
  const isParentseoField = parent && (parent == null ? void 0 : parent._type) === "seoFields";
2206
- const keywords = (0, import_react3.useMemo)(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
2207
- const feedbackItems = (0, import_react3.useMemo)(
2208
- () => getMetaTitleValidationMessages(value || "", keywords, isParentseoField),
70
+ const keywords = React12.useMemo(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
71
+ const feedbackItems = React12.useMemo(
72
+ () => chunkIFDLKZET_cjs.getMetaTitleValidationMessages(value || "", keywords, isParentseoField),
2209
73
  [value, keywords, isParentseoField]
2210
74
  );
2211
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Stack, { space: 3, children: [
75
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2212
76
  renderDefault(props),
2213
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2214
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
77
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
78
+ /* @__PURE__ */ jsxRuntime.jsx(
2215
79
  "div",
2216
80
  {
2217
81
  style: {
@@ -2222,7 +86,7 @@ var MetaTitle = (props) => {
2222
86
  }
2223
87
  }
2224
88
  ),
2225
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Text, { weight: "bold", muted: true, size: 14, children: item.text })
89
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2226
90
  ] }, item.text)) })
2227
91
  ] });
2228
92
  };
@@ -2350,29 +214,19 @@ var getFieldHiddenFunction = (fieldName, config) => {
2350
214
  var isEmpty = (value) => {
2351
215
  return value === null || value === void 0 || typeof value === "string" && value.trim() === "" || Array.isArray(value) && value.length === 0 || typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
2352
216
  };
2353
-
2354
- // src/schemas/types/openGraph/index.ts
2355
- var import_sanity8 = require("sanity");
2356
-
2357
- // src/components/openGraph/OgDescription.tsx
2358
- var import_ui4 = require("@sanity/ui");
2359
- var import_react4 = require("react");
2360
- var import_sanity4 = require("sanity");
2361
- init_seoUtils();
2362
- var import_jsx_runtime4 = require("react/jsx-runtime");
2363
217
  var OgDescription = (props) => {
2364
218
  const { value, renderDefault, path } = props;
2365
- const parent = (0, import_sanity4.useFormValue)([path[0]]);
219
+ const parent = sanity.useFormValue([path[0]]);
2366
220
  const isParentseoField = parent && (parent == null ? void 0 : parent._type) === "seoFields";
2367
- const keywords = (0, import_react4.useMemo)(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
2368
- const feedbackItems = (0, import_react4.useMemo)(
2369
- () => getOgDescriptionValidation(value || "", keywords, isParentseoField),
221
+ const keywords = React12.useMemo(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
222
+ const feedbackItems = React12.useMemo(
223
+ () => chunkIFDLKZET_cjs.getOgDescriptionValidation(value || "", keywords, isParentseoField),
2370
224
  [value, keywords, isParentseoField]
2371
225
  );
2372
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Stack, { space: 3, children: [
226
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2373
227
  renderDefault(props),
2374
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2375
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
228
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
229
+ /* @__PURE__ */ jsxRuntime.jsx(
2376
230
  "div",
2377
231
  {
2378
232
  style: {
@@ -2383,32 +237,25 @@ var OgDescription = (props) => {
2383
237
  }
2384
238
  }
2385
239
  ),
2386
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Text, { weight: "bold", muted: true, size: 14, children: item.text })
240
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2387
241
  ] }, item.text)) })
2388
242
  ] });
2389
243
  };
2390
244
  var OgDescription_default = OgDescription;
2391
-
2392
- // src/components/openGraph/OgImage.tsx
2393
- var import_ui5 = require("@sanity/ui");
2394
- var import_react5 = require("react");
2395
- var import_sanity5 = require("sanity");
2396
- init_seoUtils();
2397
- var import_jsx_runtime5 = require("react/jsx-runtime");
2398
245
  var OgImage = (props) => {
2399
246
  const { value, renderDefault, path } = props;
2400
- const seoParent = (0, import_sanity5.useFormValue)([path[0]]);
247
+ const seoParent = sanity.useFormValue([path[0]]);
2401
248
  const imgValue = value;
2402
249
  const hasImage = !!(imgValue == null ? void 0 : imgValue.asset);
2403
250
  const altText = imgValue == null ? void 0 : imgValue.alt;
2404
- const feedbackItems = (0, import_react5.useMemo)(
2405
- () => getOgImageValidation(hasImage, altText, seoParent),
251
+ const feedbackItems = React12.useMemo(
252
+ () => chunkIFDLKZET_cjs.getOgImageValidation(hasImage, altText, seoParent),
2406
253
  [hasImage, altText, seoParent]
2407
254
  );
2408
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Stack, { space: 3, children: [
255
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2409
256
  renderDefault(props),
2410
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2411
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
257
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
258
+ /* @__PURE__ */ jsxRuntime.jsx(
2412
259
  "div",
2413
260
  {
2414
261
  style: {
@@ -2419,26 +266,19 @@ var OgImage = (props) => {
2419
266
  }
2420
267
  }
2421
268
  ),
2422
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Text, { weight: "bold", muted: true, size: 14, children: item.text })
269
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2423
270
  ] }, item.text)) })
2424
271
  ] });
2425
272
  };
2426
273
  var OgImage_default = OgImage;
2427
-
2428
- // src/components/openGraph/OgImageUrl.tsx
2429
- var import_ui6 = require("@sanity/ui");
2430
- var import_react6 = require("react");
2431
- var import_sanity6 = require("sanity");
2432
- init_seoUtils();
2433
- var import_jsx_runtime6 = require("react/jsx-runtime");
2434
274
  var OgImageUrl = (props) => {
2435
275
  const { value, renderDefault, path } = props;
2436
- const seoParent = (0, import_sanity6.useFormValue)([path[0]]);
2437
- const feedbackItems = (0, import_react6.useMemo)(() => getOgImageUrlValidation(value, seoParent), [value, seoParent]);
2438
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Stack, { space: 3, children: [
276
+ const seoParent = sanity.useFormValue([path[0]]);
277
+ const feedbackItems = React12.useMemo(() => chunkIFDLKZET_cjs.getOgImageUrlValidation(value, seoParent), [value, seoParent]);
278
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2439
279
  renderDefault(props),
2440
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2441
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
280
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
281
+ /* @__PURE__ */ jsxRuntime.jsx(
2442
282
  "div",
2443
283
  {
2444
284
  style: {
@@ -2449,31 +289,24 @@ var OgImageUrl = (props) => {
2449
289
  }
2450
290
  }
2451
291
  ),
2452
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Text, { weight: "bold", muted: true, size: 14, children: item.text })
292
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2453
293
  ] }, item.text)) })
2454
294
  ] });
2455
295
  };
2456
296
  var OgImageUrl_default = OgImageUrl;
2457
-
2458
- // src/components/openGraph/OgTitle.tsx
2459
- var import_ui7 = require("@sanity/ui");
2460
- var import_react7 = require("react");
2461
- var import_sanity7 = require("sanity");
2462
- init_seoUtils();
2463
- var import_jsx_runtime7 = require("react/jsx-runtime");
2464
297
  var OgTitle = (props) => {
2465
298
  const { value, renderDefault, path } = props;
2466
- const parent = (0, import_sanity7.useFormValue)([path[0]]);
299
+ const parent = sanity.useFormValue([path[0]]);
2467
300
  const isParentseoField = parent && (parent == null ? void 0 : parent._type) === "seoFields";
2468
- const keywords = (0, import_react7.useMemo)(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
2469
- const feedbackItems = (0, import_react7.useMemo)(
2470
- () => getOgTitleValidation(value || "", keywords, isParentseoField),
301
+ const keywords = React12.useMemo(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
302
+ const feedbackItems = React12.useMemo(
303
+ () => chunkIFDLKZET_cjs.getOgTitleValidation(value || "", keywords, isParentseoField),
2471
304
  [value, keywords, isParentseoField]
2472
305
  );
2473
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ui7.Stack, { space: 3, children: [
306
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2474
307
  renderDefault(props),
2475
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ui7.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2476
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
308
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
309
+ /* @__PURE__ */ jsxRuntime.jsx(
2477
310
  "div",
2478
311
  {
2479
312
  style: {
@@ -2484,7 +317,7 @@ var OgTitle = (props) => {
2484
317
  }
2485
318
  }
2486
319
  ),
2487
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ui7.Text, { weight: "bold", muted: true, size: 14, children: item.text })
320
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2488
321
  ] }, item.text)) })
2489
322
  ] });
2490
323
  };
@@ -2492,19 +325,19 @@ var OgTitle_default = OgTitle;
2492
325
 
2493
326
  // src/schemas/types/openGraph/index.ts
2494
327
  function openGraph(config = {}) {
2495
- return (0, import_sanity8.defineType)({
328
+ return sanity.defineType({
2496
329
  name: "openGraph",
2497
330
  title: "Open Graph Settings",
2498
331
  type: "object",
2499
332
  fields: [
2500
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
333
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2501
334
  name: "url",
2502
335
  type: "url"
2503
336
  }, getFieldInfo("openGraphUrl", config.fieldOverrides)), {
2504
337
  hidden: getFieldHiddenFunction("openGraphUrl", config),
2505
338
  description: "The canonical URL of the page. This should be the full URL including protocol (https://)."
2506
339
  })),
2507
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
340
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2508
341
  name: "title"
2509
342
  }, getFieldInfo("openGraphTitle", config.fieldOverrides)), {
2510
343
  type: "string",
@@ -2514,7 +347,7 @@ function openGraph(config = {}) {
2514
347
  // Can also wrap with a string input + preview
2515
348
  }
2516
349
  })),
2517
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
350
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2518
351
  name: "description"
2519
352
  }, getFieldInfo("openGraphDescription", config.fieldOverrides)), {
2520
353
  type: "text",
@@ -2525,13 +358,13 @@ function openGraph(config = {}) {
2525
358
  // Can also wrap with a text area + preview
2526
359
  }
2527
360
  })),
2528
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
361
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2529
362
  name: "siteName"
2530
363
  }, getFieldInfo("openGraphSiteName", config.fieldOverrides)), {
2531
364
  type: "string",
2532
365
  hidden: getFieldHiddenFunction("openGraphSiteName", config)
2533
366
  })),
2534
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
367
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2535
368
  name: "type"
2536
369
  }, getFieldInfo("openGraphType", config.fieldOverrides)), {
2537
370
  type: "string",
@@ -2550,7 +383,7 @@ function openGraph(config = {}) {
2550
383
  hidden: getFieldHiddenFunction("openGraphType", config),
2551
384
  initialValue: "website"
2552
385
  })),
2553
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
386
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2554
387
  name: "imageType"
2555
388
  }, getFieldInfo("openGraphImageType", config.fieldOverrides)), {
2556
389
  type: "string",
@@ -2563,7 +396,7 @@ function openGraph(config = {}) {
2563
396
  hidden: getFieldHiddenFunction("openGraphImage", config),
2564
397
  initialValue: "upload"
2565
398
  })),
2566
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
399
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2567
400
  name: "image"
2568
401
  }, getFieldInfo("openGraphImage", config.fieldOverrides)), {
2569
402
  type: "image",
@@ -2574,7 +407,7 @@ function openGraph(config = {}) {
2574
407
  input: OgImage_default
2575
408
  },
2576
409
  fields: [
2577
- (0, import_sanity8.defineField)({
410
+ sanity.defineField({
2578
411
  name: "alt",
2579
412
  title: "Image Alt Text",
2580
413
  type: "string",
@@ -2588,7 +421,7 @@ function openGraph(config = {}) {
2588
421
  return typeof hiddenFn === "function" ? hiddenFn(context) : hiddenFn;
2589
422
  }
2590
423
  })),
2591
- (0, import_sanity8.defineField)(__spreadProps(__spreadValues({
424
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2592
425
  name: "imageUrl"
2593
426
  }, getFieldInfo("openGraphImageUrl", config.fieldOverrides)), {
2594
427
  type: "url",
@@ -2605,29 +438,19 @@ function openGraph(config = {}) {
2605
438
  ]
2606
439
  });
2607
440
  }
2608
-
2609
- // src/schemas/types/twitter/index.ts
2610
- var import_sanity13 = require("sanity");
2611
-
2612
- // src/components/twitter/twitterDescription.tsx
2613
- var import_ui8 = require("@sanity/ui");
2614
- var import_react8 = require("react");
2615
- var import_sanity9 = require("sanity");
2616
- init_seoUtils();
2617
- var import_jsx_runtime8 = require("react/jsx-runtime");
2618
441
  var TwitterDescription = (props) => {
2619
442
  const { value, renderDefault, path } = props;
2620
- const parent = (0, import_sanity9.useFormValue)([path[0]]);
443
+ const parent = sanity.useFormValue([path[0]]);
2621
444
  const isParentseoField = parent && (parent == null ? void 0 : parent._type) === "seoFields";
2622
- const keywords = (0, import_react8.useMemo)(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
2623
- const feedbackItems = (0, import_react8.useMemo)(
2624
- () => getTwitterDescriptionValidation(value || "", keywords, isParentseoField),
445
+ const keywords = React12.useMemo(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
446
+ const feedbackItems = React12.useMemo(
447
+ () => chunkIFDLKZET_cjs.getTwitterDescriptionValidation(value || "", keywords, isParentseoField),
2625
448
  [value, keywords, isParentseoField]
2626
449
  );
2627
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ui8.Stack, { space: 3, children: [
450
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2628
451
  renderDefault(props),
2629
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ui8.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2630
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
452
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
453
+ /* @__PURE__ */ jsxRuntime.jsx(
2631
454
  "div",
2632
455
  {
2633
456
  style: {
@@ -2638,32 +461,25 @@ var TwitterDescription = (props) => {
2638
461
  }
2639
462
  }
2640
463
  ),
2641
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ui8.Text, { weight: "bold", muted: true, size: 14, children: item.text })
464
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2642
465
  ] }, item.text)) })
2643
466
  ] });
2644
467
  };
2645
468
  var twitterDescription_default = TwitterDescription;
2646
-
2647
- // src/components/twitter/TwitterImage.tsx
2648
- var import_ui9 = require("@sanity/ui");
2649
- var import_react9 = require("react");
2650
- var import_sanity10 = require("sanity");
2651
- init_seoUtils();
2652
- var import_jsx_runtime9 = require("react/jsx-runtime");
2653
469
  var TwitterImage = (props) => {
2654
470
  const { value, renderDefault, path } = props;
2655
- const seoParent = (0, import_sanity10.useFormValue)([path[0]]);
471
+ const seoParent = sanity.useFormValue([path[0]]);
2656
472
  const imgValue = value;
2657
473
  const hasImage = !!(imgValue == null ? void 0 : imgValue.asset);
2658
474
  const altText = imgValue == null ? void 0 : imgValue.alt;
2659
- const feedbackItems = (0, import_react9.useMemo)(
2660
- () => getTwitterImageValidation(hasImage, altText, seoParent),
475
+ const feedbackItems = React12.useMemo(
476
+ () => chunkIFDLKZET_cjs.getTwitterImageValidation(hasImage, altText, seoParent),
2661
477
  [hasImage, altText, seoParent]
2662
478
  );
2663
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ui9.Stack, { space: 3, children: [
479
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2664
480
  renderDefault(props),
2665
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ui9.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2666
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
481
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
482
+ /* @__PURE__ */ jsxRuntime.jsx(
2667
483
  "div",
2668
484
  {
2669
485
  style: {
@@ -2674,29 +490,22 @@ var TwitterImage = (props) => {
2674
490
  }
2675
491
  }
2676
492
  ),
2677
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ui9.Text, { weight: "bold", muted: true, size: 14, children: item.text })
493
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2678
494
  ] }, item.text)) })
2679
495
  ] });
2680
496
  };
2681
497
  var TwitterImage_default = TwitterImage;
2682
-
2683
- // src/components/twitter/TwitterImageUrl.tsx
2684
- var import_ui10 = require("@sanity/ui");
2685
- var import_react10 = require("react");
2686
- var import_sanity11 = require("sanity");
2687
- init_seoUtils();
2688
- var import_jsx_runtime10 = require("react/jsx-runtime");
2689
498
  var TwitterImageUrl = (props) => {
2690
499
  const { value, renderDefault, path } = props;
2691
- const seoParent = (0, import_sanity11.useFormValue)([path[0]]);
2692
- const feedbackItems = (0, import_react10.useMemo)(
2693
- () => getTwitterImageUrlValidation(value, seoParent),
500
+ const seoParent = sanity.useFormValue([path[0]]);
501
+ const feedbackItems = React12.useMemo(
502
+ () => chunkIFDLKZET_cjs.getTwitterImageUrlValidation(value, seoParent),
2694
503
  [value, seoParent]
2695
504
  );
2696
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ui10.Stack, { space: 3, children: [
505
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2697
506
  renderDefault(props),
2698
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ui10.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2699
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
507
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
508
+ /* @__PURE__ */ jsxRuntime.jsx(
2700
509
  "div",
2701
510
  {
2702
511
  style: {
@@ -2707,31 +516,24 @@ var TwitterImageUrl = (props) => {
2707
516
  }
2708
517
  }
2709
518
  ),
2710
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ui10.Text, { weight: "bold", muted: true, size: 14, children: item.text })
519
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2711
520
  ] }, item.text)) })
2712
521
  ] });
2713
522
  };
2714
523
  var TwitterImageUrl_default = TwitterImageUrl;
2715
-
2716
- // src/components/twitter/twitterTitle.tsx
2717
- var import_ui11 = require("@sanity/ui");
2718
- var import_react11 = require("react");
2719
- var import_sanity12 = require("sanity");
2720
- init_seoUtils();
2721
- var import_jsx_runtime11 = require("react/jsx-runtime");
2722
524
  var TwitterTitle = (props) => {
2723
525
  const { value, renderDefault, path } = props;
2724
- const parent = (0, import_sanity12.useFormValue)([path[0]]);
526
+ const parent = sanity.useFormValue([path[0]]);
2725
527
  const isParentseoField = parent && (parent == null ? void 0 : parent._type) === "seoFields";
2726
- const keywords = (0, import_react11.useMemo)(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
2727
- const feedbackItems = (0, import_react11.useMemo)(
2728
- () => getTwitterTitleValidation(value || "", keywords, isParentseoField),
528
+ const keywords = React12.useMemo(() => (parent == null ? void 0 : parent.keywords) || [], [parent == null ? void 0 : parent.keywords]);
529
+ const feedbackItems = React12.useMemo(
530
+ () => chunkIFDLKZET_cjs.getTwitterTitleValidation(value || "", keywords, isParentseoField),
2729
531
  [value, keywords, isParentseoField]
2730
532
  );
2731
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ui11.Stack, { space: 3, children: [
533
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
2732
534
  renderDefault(props),
2733
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ui11.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
2734
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
535
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
536
+ /* @__PURE__ */ jsxRuntime.jsx(
2735
537
  "div",
2736
538
  {
2737
539
  style: {
@@ -2742,7 +544,7 @@ var TwitterTitle = (props) => {
2742
544
  }
2743
545
  }
2744
546
  ),
2745
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ui11.Text, { weight: "bold", muted: true, size: 14, children: item.text })
547
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
2746
548
  ] }, item.text)) })
2747
549
  ] });
2748
550
  };
@@ -2750,12 +552,12 @@ var twitterTitle_default = TwitterTitle;
2750
552
 
2751
553
  // src/schemas/types/twitter/index.ts
2752
554
  function twitter(config = {}) {
2753
- return (0, import_sanity13.defineType)({
555
+ return sanity.defineType({
2754
556
  name: "twitter",
2755
557
  title: "X (Formerly Twitter)",
2756
558
  type: "object",
2757
559
  fields: [
2758
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
560
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2759
561
  name: "card"
2760
562
  }, getFieldInfo("twitterCard", config.fieldOverrides)), {
2761
563
  type: "string",
@@ -2771,19 +573,19 @@ function twitter(config = {}) {
2771
573
  initialValue: "summary_large_image"
2772
574
  // good default
2773
575
  })),
2774
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
576
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2775
577
  name: "site"
2776
578
  }, getFieldInfo("twitterSite", config.fieldOverrides)), {
2777
579
  type: "string",
2778
580
  hidden: getFieldHiddenFunction("twitterSite", config)
2779
581
  })),
2780
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
582
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2781
583
  name: "creator",
2782
584
  type: "string"
2783
585
  }, getFieldInfo("twitterCreator", config.fieldOverrides)), {
2784
586
  hidden: getFieldHiddenFunction("twitterCreator", config)
2785
587
  })),
2786
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
588
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2787
589
  name: "title",
2788
590
  type: "string"
2789
591
  }, getFieldInfo("twitterTitle", config.fieldOverrides)), {
@@ -2792,7 +594,7 @@ function twitter(config = {}) {
2792
594
  input: twitterTitle_default
2793
595
  }
2794
596
  })),
2795
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
597
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2796
598
  name: "description",
2797
599
  type: "text",
2798
600
  rows: 3
@@ -2802,7 +604,7 @@ function twitter(config = {}) {
2802
604
  input: twitterDescription_default
2803
605
  }
2804
606
  })),
2805
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
607
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2806
608
  name: "imageType"
2807
609
  }, getFieldInfo("twitterImageType", config.fieldOverrides)), {
2808
610
  type: "string",
@@ -2815,7 +617,7 @@ function twitter(config = {}) {
2815
617
  hidden: getFieldHiddenFunction("twitterImage", config),
2816
618
  initialValue: "upload"
2817
619
  })),
2818
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
620
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2819
621
  name: "image"
2820
622
  }, getFieldInfo("twitterImage", config.fieldOverrides)), {
2821
623
  type: "image",
@@ -2826,7 +628,7 @@ function twitter(config = {}) {
2826
628
  input: TwitterImage_default
2827
629
  },
2828
630
  fields: [
2829
- (0, import_sanity13.defineField)({
631
+ sanity.defineField({
2830
632
  name: "alt",
2831
633
  title: "Image Alt Text",
2832
634
  type: "string",
@@ -2840,7 +642,7 @@ function twitter(config = {}) {
2840
642
  return typeof hiddenFn === "function" ? hiddenFn(context) : hiddenFn;
2841
643
  }
2842
644
  })),
2843
- (0, import_sanity13.defineField)(__spreadProps(__spreadValues({
645
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2844
646
  name: "imageUrl"
2845
647
  }, getFieldInfo("twitterImageUrl", config.fieldOverrides)), {
2846
648
  type: "url",
@@ -2859,15 +661,15 @@ function twitter(config = {}) {
2859
661
  }
2860
662
 
2861
663
  // src/schemas/index.ts
2862
- var LazySeoPreview = import_react12.default.lazy(() => Promise.resolve().then(() => (init_SeoPreview(), SeoPreview_exports)));
2863
- var SeoPreviewWrapper = (props) => import_react12.default.createElement(import_react12.default.Suspense, { fallback: null }, import_react12.default.createElement(LazySeoPreview, props));
664
+ var LazySeoPreview = React12__default.default.lazy(() => import('./SeoPreview-Y3CFDVBR.cjs'));
665
+ var SeoPreviewWrapper = (props) => React12__default.default.createElement(React12__default.default.Suspense, { fallback: null }, React12__default.default.createElement(LazySeoPreview, props));
2864
666
  function seoFieldsSchema(config = {}) {
2865
- return (0, import_sanity15.defineType)({
667
+ return sanity.defineType({
2866
668
  name: "seoFields",
2867
669
  title: "SEO Fields",
2868
670
  type: "object",
2869
671
  fields: [
2870
- (0, import_sanity15.defineField)({
672
+ sanity.defineField({
2871
673
  name: "robots",
2872
674
  title: "Robots Settings",
2873
675
  type: "robots",
@@ -2876,12 +678,12 @@ function seoFieldsSchema(config = {}) {
2876
678
  }),
2877
679
  // 👇 conditionally spread preview field
2878
680
  ...typeof config.seoPreview === "boolean" && config.seoPreview || typeof config.seoPreview === "object" && !isEmpty(config.seoPreview) ? [
2879
- (0, import_sanity15.defineField)({
681
+ sanity.defineField({
2880
682
  name: "preview",
2881
683
  title: "SEO Preview",
2882
684
  type: "string",
2883
685
  components: { input: SeoPreviewWrapper },
2884
- options: __spreadValues({
686
+ options: chunkS367Y35J_cjs.__spreadValues({
2885
687
  baseUrl: config.baseUrl || "https://www.example.com"
2886
688
  }, typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.prefix ? { prefix: config.seoPreview.prefix } : {}),
2887
689
  // Use a readOnly field to prevent editing
@@ -2891,7 +693,7 @@ function seoFieldsSchema(config = {}) {
2891
693
  readOnly: true
2892
694
  })
2893
695
  ] : [],
2894
- (0, import_sanity15.defineField)(__spreadProps(__spreadValues({
696
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2895
697
  name: "title"
2896
698
  }, getFieldInfo("title", config.fieldOverrides)), {
2897
699
  // title: 'Meta Title',
@@ -2904,7 +706,7 @@ function seoFieldsSchema(config = {}) {
2904
706
  // validation: (Rule) => Rule.max(60).warning('Meta title should be under 60 characters.'),
2905
707
  hidden: getFieldHiddenFunction("title", config)
2906
708
  })),
2907
- (0, import_sanity15.defineField)(__spreadProps(__spreadValues({
709
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2908
710
  name: "description"
2909
711
  }, getFieldInfo("description", config.fieldOverrides)), {
2910
712
  // title: 'Meta Description',
@@ -2918,7 +720,7 @@ function seoFieldsSchema(config = {}) {
2918
720
  // validation: (Rule) => Rule.max(160).warning('Meta description should be under 160 characters.'),
2919
721
  hidden: getFieldHiddenFunction("description", config)
2920
722
  })),
2921
- (0, import_sanity15.defineField)(__spreadProps(__spreadValues({
723
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2922
724
  name: "metaImage"
2923
725
  }, getFieldInfo("metaImage", config.fieldOverrides)), {
2924
726
  // title: 'Meta Image',
@@ -2933,7 +735,7 @@ function seoFieldsSchema(config = {}) {
2933
735
  },
2934
736
  hidden: getFieldHiddenFunction("metaImage", config)
2935
737
  })),
2936
- (0, import_sanity15.defineField)(__spreadProps(__spreadValues({
738
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2937
739
  name: "metaAttributes"
2938
740
  }, getFieldInfo("metaAttributes", config.fieldOverrides)), {
2939
741
  type: "array",
@@ -2942,7 +744,7 @@ function seoFieldsSchema(config = {}) {
2942
744
  // 'Add custom meta attributes to the head of the document for additional SEO and social media integration.',
2943
745
  hidden: getFieldHiddenFunction("metaAttributes", config)
2944
746
  })),
2945
- (0, import_sanity15.defineField)(__spreadProps(__spreadValues({
747
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2946
748
  name: "keywords"
2947
749
  }, getFieldInfo("keywords", config.fieldOverrides)), {
2948
750
  title: "Keywords",
@@ -2951,7 +753,7 @@ function seoFieldsSchema(config = {}) {
2951
753
  description: "Add relevant keywords for this page. These keywords will be used for SEO purposes.",
2952
754
  hidden: getFieldHiddenFunction("keywords", config)
2953
755
  })),
2954
- (0, import_sanity15.defineField)(__spreadProps(__spreadValues({
756
+ sanity.defineField(chunkS367Y35J_cjs.__spreadProps(chunkS367Y35J_cjs.__spreadValues({
2955
757
  name: "canonicalUrl"
2956
758
  }, getFieldInfo("canonicalUrl", config.fieldOverrides)), {
2957
759
  title: "Canonical URL",
@@ -2964,20 +766,17 @@ function seoFieldsSchema(config = {}) {
2964
766
  ]
2965
767
  });
2966
768
  }
2967
-
2968
- // src/schemas/types/metaAttribute/index.ts
2969
- var import_sanity16 = require("sanity");
2970
- var metaAttribute_default = (0, import_sanity16.defineType)({
769
+ var metaAttribute_default = sanity.defineType({
2971
770
  name: "metaAttribute",
2972
771
  title: "Meta Attribute",
2973
772
  type: "object",
2974
773
  fields: [
2975
- (0, import_sanity16.defineField)({
774
+ sanity.defineField({
2976
775
  name: "key",
2977
776
  title: "Attribute Name",
2978
777
  type: "string"
2979
778
  }),
2980
- (0, import_sanity16.defineField)({
779
+ sanity.defineField({
2981
780
  name: "type",
2982
781
  title: "Attribute Value Type",
2983
782
  type: "string",
@@ -2989,13 +788,13 @@ var metaAttribute_default = (0, import_sanity16.defineType)({
2989
788
  },
2990
789
  initialValue: "string"
2991
790
  }),
2992
- (0, import_sanity16.defineField)({
791
+ sanity.defineField({
2993
792
  name: "value",
2994
793
  title: "Attribute Value",
2995
794
  type: "string",
2996
795
  hidden: ({ parent }) => (parent == null ? void 0 : parent.type) === "image"
2997
796
  }),
2998
- (0, import_sanity16.defineField)({
797
+ sanity.defineField({
2999
798
  name: "image",
3000
799
  title: "Attribute Image Value",
3001
800
  type: "image",
@@ -3025,10 +824,7 @@ var metaAttribute_default = (0, import_sanity16.defineType)({
3025
824
  }
3026
825
  }
3027
826
  });
3028
-
3029
- // src/schemas/types/metaTag/index.ts
3030
- var import_sanity17 = require("sanity");
3031
- var metaTag_default = (0, import_sanity17.defineType)({
827
+ var metaTag_default = sanity.defineType({
3032
828
  name: "metaTag",
3033
829
  title: "Meta Tag",
3034
830
  type: "object",
@@ -3042,22 +838,19 @@ var metaTag_default = (0, import_sanity17.defineType)({
3042
838
  }
3043
839
  ]
3044
840
  });
3045
-
3046
- // src/schemas/types/robots/index.ts
3047
- var import_sanity18 = require("sanity");
3048
- var robots_default = (0, import_sanity18.defineType)({
841
+ var robots_default = sanity.defineType({
3049
842
  name: "robots",
3050
843
  title: "Robots Settings",
3051
844
  type: "object",
3052
845
  fields: [
3053
- (0, import_sanity18.defineField)({
846
+ sanity.defineField({
3054
847
  name: "noIndex",
3055
848
  title: "No Index",
3056
849
  type: "boolean",
3057
850
  initialValue: false,
3058
851
  description: "Enable this to prevent search engines from indexing this page. The page will not appear in search results."
3059
852
  }),
3060
- (0, import_sanity18.defineField)({
853
+ sanity.defineField({
3061
854
  name: "noFollow",
3062
855
  title: "No Follow",
3063
856
  type: "boolean",
@@ -3183,14 +976,14 @@ var resolveDashboardConfig = (healthDashboard) => {
3183
976
  deprecationWarnings
3184
977
  };
3185
978
  };
3186
- var seofields = (0, import_sanity20.definePlugin)((config = {}) => {
979
+ var seofields = sanity.definePlugin((config = {}) => {
3187
980
  const { healthDashboard = true } = config;
3188
981
  const dash = resolveDashboardConfig(healthDashboard);
3189
- const LazySeoHealthTool = import_react14.default.lazy(() => Promise.resolve().then(() => (init_SeoHealthTool(), SeoHealthTool_exports)));
3190
- const BoundSeoHealthTool = () => import_react14.default.createElement(
3191
- import_react14.default.Suspense,
982
+ const LazySeoHealthTool = React12__default.default.lazy(() => import('./SeoHealthTool-4P6JST5S.cjs'));
983
+ const BoundSeoHealthTool = () => React12__default.default.createElement(
984
+ React12__default.default.Suspense,
3192
985
  { fallback: null },
3193
- import_react14.default.createElement(LazySeoHealthTool, {
986
+ React12__default.default.createElement(LazySeoHealthTool, {
3194
987
  icon: dash.icon,
3195
988
  title: dash.title,
3196
989
  description: dash.description,
@@ -3213,7 +1006,7 @@ var seofields = (0, import_sanity20.definePlugin)((config = {}) => {
3213
1006
  _deprecationWarnings: dash.deprecationWarnings
3214
1007
  })
3215
1008
  );
3216
- return __spreadValues({
1009
+ return chunkS367Y35J_cjs.__spreadValues({
3217
1010
  name: "sanity-plugin-seofields",
3218
1011
  schema: {
3219
1012
  types: types(config)
@@ -3230,17 +1023,13 @@ var seofields = (0, import_sanity20.definePlugin)((config = {}) => {
3230
1023
  });
3231
1024
  });
3232
1025
  var plugin_default = seofields;
3233
-
3234
- // src/components/SeoHealthPane.tsx
3235
- var import_react15 = __toESM(require("react"), 1);
3236
- var import_jsx_runtime15 = require("react/jsx-runtime");
3237
- var LazySeoHealthDashboard = import_react15.default.lazy(() => Promise.resolve().then(() => (init_SeoHealthDashboard(), SeoHealthDashboard_exports)));
1026
+ var LazySeoHealthDashboard = React12__default.default.lazy(() => import('./SeoHealthDashboard-3VBITMWT.cjs'));
3238
1027
  function createSeoHealthPane(optionsOrS, optionsWhenS) {
3239
1028
  const S = optionsOrS;
3240
- const _a = optionsWhenS != null ? optionsWhenS : {}, { query, openInPane = true, title: paneTitle } = _a, rest = __objRest(_a, ["query", "openInPane", "title"]);
3241
- const SeoHealthPane = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react15.default.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1029
+ const _a = optionsWhenS != null ? optionsWhenS : {}, { query, openInPane = true, title: paneTitle } = _a, rest = chunkS367Y35J_cjs.__objRest(_a, ["query", "openInPane", "title"]);
1030
+ const SeoHealthPane = () => /* @__PURE__ */ jsxRuntime.jsx(React12__default.default.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(
3242
1031
  LazySeoHealthDashboard,
3243
- __spreadValues({
1032
+ chunkS367Y35J_cjs.__spreadValues({
3244
1033
  customQuery: query,
3245
1034
  openInPane,
3246
1035
  title: paneTitle
@@ -3255,15 +1044,15 @@ function createSeoHealthPane(optionsOrS, optionsWhenS) {
3255
1044
 
3256
1045
  // src/index.ts
3257
1046
  var src_default = plugin_default;
3258
- // Annotate the CommonJS export names for ESM import in node:
3259
- 0 && (module.exports = {
3260
- allSchemas,
3261
- createSeoHealthPane,
3262
- metaAttributeSchema,
3263
- metaTagSchema,
3264
- openGraphSchema,
3265
- robotsSchema,
3266
- seoFieldsSchema,
3267
- twitterSchema
3268
- });
1047
+
1048
+ exports.allSchemas = types;
1049
+ exports.createSeoHealthPane = createSeoHealthPane;
1050
+ exports.default = src_default;
1051
+ exports.metaAttributeSchema = metaAttribute_default;
1052
+ exports.metaTagSchema = metaTag_default;
1053
+ exports.openGraphSchema = openGraph;
1054
+ exports.robotsSchema = robots_default;
1055
+ exports.seoFieldsSchema = seoFieldsSchema;
1056
+ exports.twitterSchema = twitter;
1057
+ //# sourceMappingURL=index.cjs.map
3269
1058
  //# sourceMappingURL=index.cjs.map