@payloadcms/plugin-seo 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # Payload SEO Plugin
2
+
3
+ [![NPM](https://img.shields.io/npm/v/@payloadcms/plugin-seo)](https://www.npmjs.com/package/@payloadcms/plugin-seo)
4
+
5
+ A plugin for [Payload CMS](https://github.com/payloadcms/payload) to auto-generate SEO meta data based on the content of your documents.
6
+
7
+ Core features:
8
+ - Adds a `meta` field to every SEO-enabled collection that:
9
+ - Includes title, description, and image subfields
10
+ - Auto-generates meta data from your document's content
11
+ - Displays hints and indicators to help content editors
12
+ - Renders a snippet of what a search engine might display
13
+ - Soon: variable injection
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ yarn add @payloadcms/plugin-seo
19
+ # OR
20
+ npm i @payloadcms/plugin-seo
21
+ ```
22
+
23
+ ## Basic Usage
24
+
25
+ In the `plugins` array of your [Payload config](https://payloadcms.com/docs/configuration/overview), call the plugin with [options](#options):
26
+
27
+ ```js
28
+ import { buildConfig } from 'payload/config';
29
+ import seo from '@payloadcms/plugin-seo';
30
+
31
+ const config = buildConfig({
32
+ collections: [
33
+ {
34
+ slug: 'pages',
35
+ fields: []
36
+ },
37
+ {
38
+ slug: 'media',
39
+ upload: {
40
+ staticDir: // path to your static directory,
41
+ },
42
+ fields: []
43
+ }
44
+ ],
45
+ plugins: [
46
+ seo({
47
+ collections: [
48
+ 'pages',
49
+ ],
50
+ uploadsCollection: 'media',
51
+ generateTitle: ({ doc }) => `Website.com — ${doc.title.value}`,
52
+ generateDescription: ({ doc }) => doc.excerpt
53
+ })
54
+ ]
55
+ });
56
+
57
+ export default config;
58
+ ```
59
+
60
+ ### Options
61
+
62
+ - `collections`
63
+
64
+ An array of collections slugs to enable SEO. Enabled collections receive a `meta` field which is an object of title, description, and image subfields.
65
+
66
+
67
+ - `uploadsCollection`
68
+
69
+ An upload-enabled collection slug, for the meta image to access.
70
+
71
+ - `generateTitle`
72
+
73
+ A function that allows you to return any meta title, including from document's content.
74
+
75
+ ```js
76
+ seo({
77
+ ...
78
+ generateTitle: ({ doc }) => `Website.com — ${doc?.title?.value}`,
79
+ })
80
+ ```
81
+
82
+ - `generateDescription`
83
+
84
+ A function that allows you to return any meta description, including from document's content.
85
+
86
+ ```js
87
+ seo({
88
+ ...
89
+ generateDescription: ({ doc }) => doc?.excerpt?.value
90
+ })
91
+ ```
92
+
93
+ - `generateURL`
94
+
95
+ A function called by the search preview component to display the actual URL of your page.
96
+
97
+ ```js
98
+ seo({
99
+ ...
100
+ generateURL: ({ doc }) => `https://yoursite.com/${doc?.slug?.value}`
101
+ })
102
+ ```
103
+
104
+ ## TypeScript
105
+
106
+ All types can be directly imported:
107
+
108
+ ```js
109
+ import {
110
+ SEOConfig,
111
+ GenerateTitle,
112
+ GenerateDescription
113
+ GenerateURL
114
+ } from '@payloadcms/plugin-seo/dist/types';
115
+ ```
116
+
117
+ ## Screenshots
118
+ ![image](https://user-images.githubusercontent.com/70709113/163850633-f3da5f8e-2527-4688-bc79-17233307a883.png)
119
+
120
+ <!-- ![screenshot 1](https://github.com/trouble/@payloadcms/plugin-seo/blob/main/images/screenshot-1.jpg?raw=true) -->
@@ -0,0 +1,10 @@
1
+ export declare const defaults: {
2
+ title: {
3
+ minLength: number;
4
+ maxLength: number;
5
+ };
6
+ description: {
7
+ minLength: number;
8
+ maxLength: number;
9
+ };
10
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaults = void 0;
4
+ exports.defaults = {
5
+ title: {
6
+ minLength: 50,
7
+ maxLength: 60,
8
+ },
9
+ description: {
10
+ minLength: 100,
11
+ maxLength: 150,
12
+ },
13
+ };
14
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":";;;AAAa,QAAA,QAAQ,GAAG;IACtB,KAAK,EAAE;QACL,SAAS,EAAE,EAAE;QACb,SAAS,EAAE,EAAE;KACd;IACD,WAAW,EAAE;QACX,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf;CACF,CAAC"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { TextareaField } from 'payload/dist/fields/config/types';
3
+ import { SEOConfig } from '../types';
4
+ declare type TextareaFieldWithProps = TextareaField & {
5
+ path: string;
6
+ seoConfig: SEOConfig;
7
+ };
8
+ export declare const MetaDescription: React.FC<(TextareaFieldWithProps | {}) & {
9
+ seoConfig: SEOConfig;
10
+ }>;
11
+ export declare const getMetaDescriptionField: (props: any) => JSX.Element;
12
+ export {};
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (_) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
72
+ var __importDefault = (this && this.__importDefault) || function (mod) {
73
+ return (mod && mod.__esModule) ? mod : { "default": mod };
74
+ };
75
+ Object.defineProperty(exports, "__esModule", { value: true });
76
+ exports.getMetaDescriptionField = exports.MetaDescription = void 0;
77
+ var react_1 = __importStar(require("react"));
78
+ var forms_1 = require("payload/components/forms");
79
+ var LengthIndicator_1 = require("../ui/LengthIndicator");
80
+ var defaults_1 = require("../defaults");
81
+ var Input_1 = __importDefault(require("payload/dist/admin/components/forms/field-types/Textarea/Input"));
82
+ var _a = defaults_1.defaults.description, minLength = _a.minLength, maxLength = _a.maxLength;
83
+ var MetaDescription = function (props) {
84
+ var _a = props || {}, path = _a.path, label = _a.label, name = _a.name, seoConfig = _a.seoConfig; // TODO: this typing is temporary until payload types are updated for custom field props
85
+ var fields = (0, forms_1.useWatchForm)().fields;
86
+ var field = (0, forms_1.useField)({
87
+ label: label,
88
+ name: name,
89
+ path: path
90
+ });
91
+ var value = field.value, setValue = field.setValue, showError = field.showError;
92
+ var regenerateDescription = (0, react_1.useCallback)(function () {
93
+ var generateDescription = seoConfig.generateDescription;
94
+ var getDescription = function () { return __awaiter(void 0, void 0, void 0, function () {
95
+ var generatedDescription;
96
+ return __generator(this, function (_a) {
97
+ switch (_a.label) {
98
+ case 0:
99
+ if (!(typeof generateDescription === 'function')) return [3 /*break*/, 2];
100
+ return [4 /*yield*/, generateDescription({ doc: __assign({}, fields) })];
101
+ case 1:
102
+ generatedDescription = _a.sent();
103
+ _a.label = 2;
104
+ case 2:
105
+ setValue(generatedDescription);
106
+ return [2 /*return*/];
107
+ }
108
+ });
109
+ }); };
110
+ getDescription();
111
+ }, [
112
+ fields,
113
+ setValue,
114
+ seoConfig
115
+ ]);
116
+ return (react_1.default.createElement("div", { style: {
117
+ marginBottom: '20px',
118
+ } },
119
+ react_1.default.createElement("div", { style: {
120
+ marginBottom: '5px',
121
+ position: 'relative',
122
+ } },
123
+ react_1.default.createElement("div", null,
124
+ label,
125
+ "\u00A0 \u2014 \u00A0",
126
+ react_1.default.createElement("button", { onClick: regenerateDescription, type: "button", style: {
127
+ padding: 0,
128
+ background: 'none',
129
+ border: 'none',
130
+ backgroundColor: 'transparent',
131
+ cursor: 'pointer',
132
+ textDecoration: 'underline',
133
+ } }, "Auto-generate")),
134
+ react_1.default.createElement("div", { style: {
135
+ color: '#9A9A9A',
136
+ } }, "This should be between ".concat(minLength, " and ").concat(maxLength, " characters. Auto-generation will format a description using the page content. For help in writing quality meta descriptions, see "),
137
+ react_1.default.createElement("a", { href: "https://developers.google.com/search/docs/advanced/appearance/snippet#meta-descriptions", rel: "noopener noreferrer", target: "_blank", style: {
138
+ color: '-webkit-link',
139
+ textDecoration: 'none',
140
+ } }, "best practices"))),
141
+ react_1.default.createElement("div", { style: {
142
+ marginBottom: '10px',
143
+ position: 'relative',
144
+ } },
145
+ react_1.default.createElement(Input_1.default, { path: name, name: name, onChange: setValue, value: value, showError: showError, style: {
146
+ marginBottom: 0
147
+ } })),
148
+ react_1.default.createElement("div", { style: {
149
+ display: 'flex',
150
+ alignItems: 'center',
151
+ width: '100%',
152
+ } },
153
+ react_1.default.createElement(LengthIndicator_1.LengthIndicator, { text: value, minLength: minLength, maxLength: maxLength }))));
154
+ };
155
+ exports.MetaDescription = MetaDescription;
156
+ var getMetaDescriptionField = function (props) { return (react_1.default.createElement(exports.MetaDescription, __assign({}, props))); };
157
+ exports.getMetaDescriptionField = getMetaDescriptionField;
158
+ //# sourceMappingURL=MetaDescription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetaDescription.js","sourceRoot":"","sources":["../../src/fields/MetaDescription.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Props as UploadFieldType } from 'payload/dist/admin/components/forms/field-types/Upload/types';
3
+ import { SEOConfig } from '../types';
4
+ declare type UploadFieldWithProps = UploadFieldType & {
5
+ path: string;
6
+ seoConfig: SEOConfig;
7
+ };
8
+ export declare const MetaImage: React.FC<UploadFieldWithProps | {}>;
9
+ export declare const getMetaImageField: (props: any) => JSX.Element;
10
+ export {};
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (_) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
72
+ var __importDefault = (this && this.__importDefault) || function (mod) {
73
+ return (mod && mod.__esModule) ? mod : { "default": mod };
74
+ };
75
+ Object.defineProperty(exports, "__esModule", { value: true });
76
+ exports.getMetaImageField = exports.MetaImage = void 0;
77
+ var react_1 = __importStar(require("react"));
78
+ var config_provider_1 = require("@payloadcms/config-provider");
79
+ var Input_1 = __importDefault(require("payload/dist/admin/components/forms/field-types/Upload/Input"));
80
+ var forms_1 = require("payload/components/forms");
81
+ var Pill_1 = require("../ui/Pill");
82
+ var MetaImage = function (props) {
83
+ var _a = props || {}, label = _a.label, relationTo = _a.relationTo, fieldTypes = _a.fieldTypes, name = _a.name, seoConfig = _a.seoConfig; // TODO: this typing is temporary until payload types are updated for custom field props
84
+ var field = (0, forms_1.useField)(props);
85
+ var fields = (0, forms_1.useWatchForm)().fields;
86
+ var value = field.value, setValue = field.setValue, showError = field.showError;
87
+ var regenerateImage = (0, react_1.useCallback)(function () {
88
+ var generateImage = seoConfig.generateImage;
89
+ var getDescription = function () { return __awaiter(void 0, void 0, void 0, function () {
90
+ var generatedImage;
91
+ return __generator(this, function (_a) {
92
+ switch (_a.label) {
93
+ case 0:
94
+ if (!(typeof generateImage === 'function')) return [3 /*break*/, 2];
95
+ return [4 /*yield*/, generateImage({ doc: __assign({}, fields) })];
96
+ case 1:
97
+ generatedImage = _a.sent();
98
+ _a.label = 2;
99
+ case 2:
100
+ setValue(generatedImage);
101
+ return [2 /*return*/];
102
+ }
103
+ });
104
+ }); };
105
+ getDescription();
106
+ }, [
107
+ fields,
108
+ setValue,
109
+ seoConfig
110
+ ]);
111
+ var hasImage = Boolean(value);
112
+ var config = (0, config_provider_1.useConfig)();
113
+ var collections = config.collections, serverURL = config.serverURL, _b = config.routes, _c = _b === void 0 ? {} : _b, api = _c.api;
114
+ var collection = (collections === null || collections === void 0 ? void 0 : collections.find(function (coll) { return coll.slug === relationTo; })) || undefined;
115
+ return (react_1.default.createElement("div", { style: {
116
+ marginBottom: '20px',
117
+ } },
118
+ react_1.default.createElement("div", { style: {
119
+ marginBottom: '5px',
120
+ position: 'relative',
121
+ } },
122
+ react_1.default.createElement("div", null,
123
+ label,
124
+ "\u00A0 \u2014 \u00A0",
125
+ react_1.default.createElement("button", { onClick: regenerateImage, type: "button", style: {
126
+ padding: 0,
127
+ background: 'none',
128
+ border: 'none',
129
+ backgroundColor: 'transparent',
130
+ cursor: 'pointer',
131
+ textDecoration: 'underline',
132
+ } }, "Auto-generate")),
133
+ react_1.default.createElement("div", { style: {
134
+ color: '#9A9A9A',
135
+ } }, "Auto-generation will retrieve the selected hero image.")),
136
+ react_1.default.createElement("div", { style: {
137
+ marginBottom: '10px',
138
+ position: 'relative',
139
+ } },
140
+ react_1.default.createElement(Input_1.default, { path: name, fieldTypes: fieldTypes, name: name, relationTo: relationTo, value: value, onChange: function (incomingImage) {
141
+ if (incomingImage !== null) {
142
+ var incomingID = incomingImage.id;
143
+ setValue(incomingID);
144
+ }
145
+ else {
146
+ setValue(null);
147
+ }
148
+ }, label: undefined, showError: showError, api: api, collection: collection, serverURL: serverURL, filterOptions: {}, style: {
149
+ marginBottom: 0,
150
+ } })),
151
+ react_1.default.createElement("div", { style: {
152
+ display: 'flex',
153
+ alignItems: 'center',
154
+ width: '100%',
155
+ } },
156
+ react_1.default.createElement(Pill_1.Pill, { backgroundColor: hasImage ? 'green' : 'red', color: "white", label: hasImage ? 'Good' : 'No Image' }))));
157
+ };
158
+ exports.MetaImage = MetaImage;
159
+ var getMetaImageField = function (props) { return (react_1.default.createElement(exports.MetaImage, __assign({}, props))); };
160
+ exports.getMetaImageField = getMetaImageField;
161
+ //# sourceMappingURL=MetaImage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetaImage.js","sourceRoot":"","sources":["../../src/fields/MetaImage.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Props as TextFieldType } from 'payload/dist/admin/components/forms/field-types/Text/types';
3
+ import { SEOConfig } from '../types';
4
+ declare type TextFieldWithProps = TextFieldType & {
5
+ path: string;
6
+ seoConfig: SEOConfig;
7
+ };
8
+ export declare const MetaTitle: React.FC<TextFieldWithProps | {}>;
9
+ export declare const getMetaTitleField: (props: any) => JSX.Element;
10
+ export {};