@jini-ai/admin 0.4.3 → 0.4.4
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/CHANGELOG.md +4 -0
- package/dist/comments/comments.module.d.ts +4 -4
- package/dist/comments/messages.en.d.ts +4 -4
- package/dist/comments/messages.en.js +4 -4
- package/dist/comments/react/components/QueueSection.js +1 -1
- package/dist/comments/react/index.d.ts +16 -16
- package/dist/forms/forms.module.d.ts +3 -2
- package/dist/forms/html-rules.d.ts +14 -0
- package/dist/forms/html-rules.js +10 -0
- package/dist/forms/messages.en.d.ts +3 -2
- package/dist/forms/messages.en.js +4 -3
- package/dist/forms/react/components/FormEditorHeaderText.js +2 -2
- package/dist/forms/react/components/FormSubmissionDetail.d.ts +3 -1
- package/dist/forms/react/components/FormSubmissionDetail.js +3 -2
- package/dist/forms/react/components/FormSubmissions.js +1 -1
- package/dist/forms/react/hooks/forms-view.hooks.d.ts +1 -6
- package/dist/forms/react/hooks/forms-view.hooks.js +3 -4
- package/dist/forms/react/index.d.ts +9 -6
- package/dist/forms/react/pages/FormsList.js +2 -7
- package/dist/react/components/RowMenu/RowMenu.hooks.js +14 -3
- package/dist/redirects/messages.en.d.ts +9 -7
- package/dist/redirects/messages.en.js +14 -9
- package/dist/redirects/react/hooks/RedirectsPage.hooks.js +2 -2
- package/dist/redirects/react/index.d.ts +36 -28
- package/dist/redirects/react/pages/RedirectsPage.js +1 -1
- package/dist/redirects/redirects.module.d.ts +9 -7
- package/dist/seo/messages.en.d.ts +5 -4
- package/dist/seo/messages.en.js +6 -5
- package/dist/seo/react/components/MediaRefField.d.ts +4 -0
- package/dist/seo/react/components/MediaRefField.js +2 -2
- package/dist/seo/react/components/SitemapModal.js +4 -2
- package/dist/seo/react/hooks/MediaRefField.hooks.d.ts +4 -1
- package/dist/seo/react/hooks/MediaRefField.hooks.js +3 -3
- package/dist/seo/react/index.d.ts +15 -12
- package/dist/seo/react/options.d.ts +7 -0
- package/dist/seo/react/pages/SeoPage.js +23 -23
- package/dist/seo/rules.d.ts +6 -0
- package/dist/seo/rules.js +8 -0
- package/dist/seo/seo.module.d.ts +5 -4
- package/dist/widgets/react/pages/WidgetRegionEditor.js +1 -1
- package/package.json +5 -5
|
@@ -24,8 +24,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
24
24
|
readonly Import: "Import";
|
|
25
25
|
readonly Marketing: "Marketing";
|
|
26
26
|
readonly Redirects: "Redirects";
|
|
27
|
-
readonly "
|
|
28
|
-
readonly ") also show up here.": ") also show up here.";
|
|
27
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
29
28
|
readonly "Match type": "Match type";
|
|
30
29
|
readonly "From path": "From path";
|
|
31
30
|
readonly "To target": "To target";
|
|
@@ -46,9 +45,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
46
45
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
47
46
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
48
47
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
49
|
-
readonly exact: "
|
|
50
|
-
readonly prefix: "
|
|
51
|
-
readonly wildcard: "
|
|
48
|
+
readonly exact: "Exact match";
|
|
49
|
+
readonly prefix: "Starts with";
|
|
50
|
+
readonly wildcard: "Wildcard";
|
|
52
51
|
readonly Status: "Status";
|
|
53
52
|
readonly More: "More";
|
|
54
53
|
readonly Delete: "Delete";
|
|
@@ -56,8 +55,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
56
55
|
readonly Enable: "Enable";
|
|
57
56
|
readonly "Saving\u2026": "Saving…";
|
|
58
57
|
readonly Created: "Created";
|
|
59
|
-
readonly active: "
|
|
60
|
-
readonly disabled: "
|
|
58
|
+
readonly active: "Active";
|
|
59
|
+
readonly disabled: "Disabled";
|
|
61
60
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
62
61
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
63
62
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -65,6 +64,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
65
64
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
66
65
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
67
66
|
readonly "\"?": "\"?";
|
|
67
|
+
readonly manual: "Manual";
|
|
68
|
+
readonly auto_slug_change: "URL change";
|
|
69
|
+
readonly import: "Imported";
|
|
68
70
|
};
|
|
69
71
|
pages: {
|
|
70
72
|
readonly list: {
|
|
@@ -101,8 +103,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
101
103
|
readonly Import: "Import";
|
|
102
104
|
readonly Marketing: "Marketing";
|
|
103
105
|
readonly Redirects: "Redirects";
|
|
104
|
-
readonly "
|
|
105
|
-
readonly ") also show up here.": ") also show up here.";
|
|
106
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
106
107
|
readonly "Match type": "Match type";
|
|
107
108
|
readonly "From path": "From path";
|
|
108
109
|
readonly "To target": "To target";
|
|
@@ -123,9 +124,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
123
124
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
124
125
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
125
126
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
126
|
-
readonly exact: "
|
|
127
|
-
readonly prefix: "
|
|
128
|
-
readonly wildcard: "
|
|
127
|
+
readonly exact: "Exact match";
|
|
128
|
+
readonly prefix: "Starts with";
|
|
129
|
+
readonly wildcard: "Wildcard";
|
|
129
130
|
readonly Status: "Status";
|
|
130
131
|
readonly More: "More";
|
|
131
132
|
readonly Delete: "Delete";
|
|
@@ -133,8 +134,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
133
134
|
readonly Enable: "Enable";
|
|
134
135
|
readonly "Saving\u2026": "Saving…";
|
|
135
136
|
readonly Created: "Created";
|
|
136
|
-
readonly active: "
|
|
137
|
-
readonly disabled: "
|
|
137
|
+
readonly active: "Active";
|
|
138
|
+
readonly disabled: "Disabled";
|
|
138
139
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
139
140
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
140
141
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -142,6 +143,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
142
143
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
143
144
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
144
145
|
readonly "\"?": "\"?";
|
|
146
|
+
readonly manual: "Manual";
|
|
147
|
+
readonly auto_slug_change: "URL change";
|
|
148
|
+
readonly import: "Imported";
|
|
145
149
|
};
|
|
146
150
|
readonly pages: {
|
|
147
151
|
readonly list: {
|
|
@@ -176,8 +180,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
176
180
|
readonly Import: "Import";
|
|
177
181
|
readonly Marketing: "Marketing";
|
|
178
182
|
readonly Redirects: "Redirects";
|
|
179
|
-
readonly "
|
|
180
|
-
readonly ") also show up here.": ") also show up here.";
|
|
183
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
181
184
|
readonly "Match type": "Match type";
|
|
182
185
|
readonly "From path": "From path";
|
|
183
186
|
readonly "To target": "To target";
|
|
@@ -198,9 +201,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
198
201
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
199
202
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
200
203
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
201
|
-
readonly exact: "
|
|
202
|
-
readonly prefix: "
|
|
203
|
-
readonly wildcard: "
|
|
204
|
+
readonly exact: "Exact match";
|
|
205
|
+
readonly prefix: "Starts with";
|
|
206
|
+
readonly wildcard: "Wildcard";
|
|
204
207
|
readonly Status: "Status";
|
|
205
208
|
readonly More: "More";
|
|
206
209
|
readonly Delete: "Delete";
|
|
@@ -208,8 +211,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
208
211
|
readonly Enable: "Enable";
|
|
209
212
|
readonly "Saving\u2026": "Saving…";
|
|
210
213
|
readonly Created: "Created";
|
|
211
|
-
readonly active: "
|
|
212
|
-
readonly disabled: "
|
|
214
|
+
readonly active: "Active";
|
|
215
|
+
readonly disabled: "Disabled";
|
|
213
216
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
214
217
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
215
218
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -217,6 +220,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
217
220
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
218
221
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
219
222
|
readonly "\"?": "\"?";
|
|
223
|
+
readonly manual: "Manual";
|
|
224
|
+
readonly auto_slug_change: "URL change";
|
|
225
|
+
readonly import: "Imported";
|
|
220
226
|
};
|
|
221
227
|
readonly pages: {
|
|
222
228
|
readonly list: {
|
|
@@ -255,8 +261,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
255
261
|
readonly Import: "Import";
|
|
256
262
|
readonly Marketing: "Marketing";
|
|
257
263
|
readonly Redirects: "Redirects";
|
|
258
|
-
readonly "
|
|
259
|
-
readonly ") also show up here.": ") also show up here.";
|
|
264
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
260
265
|
readonly "Match type": "Match type";
|
|
261
266
|
readonly "From path": "From path";
|
|
262
267
|
readonly "To target": "To target";
|
|
@@ -277,9 +282,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
277
282
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
278
283
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
279
284
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
280
|
-
readonly exact: "
|
|
281
|
-
readonly prefix: "
|
|
282
|
-
readonly wildcard: "
|
|
285
|
+
readonly exact: "Exact match";
|
|
286
|
+
readonly prefix: "Starts with";
|
|
287
|
+
readonly wildcard: "Wildcard";
|
|
283
288
|
readonly Status: "Status";
|
|
284
289
|
readonly More: "More";
|
|
285
290
|
readonly Delete: "Delete";
|
|
@@ -287,8 +292,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
287
292
|
readonly Enable: "Enable";
|
|
288
293
|
readonly "Saving\u2026": "Saving…";
|
|
289
294
|
readonly Created: "Created";
|
|
290
|
-
readonly active: "
|
|
291
|
-
readonly disabled: "
|
|
295
|
+
readonly active: "Active";
|
|
296
|
+
readonly disabled: "Disabled";
|
|
292
297
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
293
298
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
294
299
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -296,6 +301,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
296
301
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
297
302
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
298
303
|
readonly "\"?": "\"?";
|
|
304
|
+
readonly manual: "Manual";
|
|
305
|
+
readonly auto_slug_change: "URL change";
|
|
306
|
+
readonly import: "Imported";
|
|
299
307
|
};
|
|
300
308
|
readonly pages: {
|
|
301
309
|
readonly list: {
|
|
@@ -15,6 +15,6 @@ export function RedirectsPage({ useRedirectsHook = useWiredRedirects } = {}) {
|
|
|
15
15
|
}
|
|
16
16
|
if (!redirects)
|
|
17
17
|
return _jsx("div", { className: "notice", children: t("Loading redirects…") });
|
|
18
|
-
return (_jsxs("div", { className: "page", children: [_jsxs("div", { className: "page-header", children: [_jsxs("div", { className: "page-header-text", children: [_jsx("p", { className: "page-kicker", children: t("Marketing") }), _jsx("h1", { className: "page-title", children: t("Redirects") }),
|
|
18
|
+
return (_jsxs("div", { className: "page", children: [_jsxs("div", { className: "page-header", children: [_jsxs("div", { className: "page-header-text", children: [_jsx("p", { className: "page-kicker", children: t("Marketing") }), _jsx("h1", { className: "page-title", children: t("Redirects") }), _jsx("p", { className: "page-description", children: t("Manage URL redirects, including those created automatically when a page's address changes.") })] }), _jsx("div", { className: "page-actions", children: headerActions })] }), error ? _jsx("div", { className: "notice error", children: describeApiError({ e: error, fallback: "request failed" }) }) : null, _jsxs("form", { className: "card form-measure", onSubmit: submitCreate, children: [_jsx("div", { className: "field-group", children: _jsxs("div", { className: "field-row", children: [_jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-match-type", children: t("Match type") }), _jsxs("select", { id: "redirect-match-type", name: "matchType", defaultValue: "exact", ...agentHandle({ handle: "redirects-create-match-type" }, { role: "field", label: "New redirect's match type" }), children: [_jsx("option", { value: "exact", children: t("exact", { serverLabel: "exact" }) }), _jsx("option", { value: "prefix", children: t("prefix", { serverLabel: "prefix" }) }), _jsx("option", { value: "wildcard", children: t("wildcard", { serverLabel: "wildcard" }) })] })] }), _jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-from-pattern", children: t("From path") }), _jsx("input", { id: "redirect-from-pattern", name: "fromPattern", placeholder: "/old-path", required: true, ...agentHandle({ handle: "redirects-create-from-pattern" }, { role: "field", label: "New redirect's source path or pattern" }) })] }), _jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-to-target", children: t("To target") }), _jsx("input", { id: "redirect-to-target", name: "toTarget", placeholder: "/new-path or https://example.com/...", required: true, ...agentHandle({ handle: "redirects-create-to-target" }, { role: "field", label: "New redirect's destination path or URL" }) })] }), _jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-status-code", children: t("Status code") }), _jsxs("select", { id: "redirect-status-code", name: "statusCode", defaultValue: "301", ...agentHandle({ handle: "redirects-create-status-code" }, { role: "field", label: "New redirect's HTTP status code" }), children: [_jsx("option", { value: "301", children: t("301 (permanent)") }), _jsx("option", { value: "302", children: t("302 (temporary)") }), _jsx("option", { value: "307", children: t("307 (temporary, method-preserving)") }), _jsx("option", { value: "308", children: t("308 (permanent, method-preserving)") })] })] })] }) }), _jsx("div", { className: "editor-actions form-actions", children: _jsx("button", { type: "submit", disabled: saving, ...agentHandle({ handle: "redirects-create-submit" }, { role: "button", label: "Add this redirect rule" }), children: saving ? t("Saving…") : t("Add redirect") }) })] }), _jsx(ImportRedirectsForm, { t: t, locale: locale }), _jsx(DataTable, { rows: redirects, rowKey: (rule) => rule.id, empty: _jsx("div", { className: "card", children: _jsx("div", { className: "empty-state", children: _jsx("p", { children: t("No redirect rules yet.") }) }) }), columns: columns }), _jsx(ConfirmDialog, { open: pendingDelete !== null, agentHandle: "redirects-delete", title: t("Delete redirect rule?"), body: deleteBody, confirmLabel: t("Delete"), destructive: true, pending: deletePending, onConfirm: confirmDelete, onCancel: cancelDelete })] }));
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=RedirectsPage.js.map
|
|
@@ -16,8 +16,7 @@ export declare const redirectsModule: {
|
|
|
16
16
|
readonly Import: "Import";
|
|
17
17
|
readonly Marketing: "Marketing";
|
|
18
18
|
readonly Redirects: "Redirects";
|
|
19
|
-
readonly "
|
|
20
|
-
readonly ") also show up here.": ") also show up here.";
|
|
19
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
21
20
|
readonly "Match type": "Match type";
|
|
22
21
|
readonly "From path": "From path";
|
|
23
22
|
readonly "To target": "To target";
|
|
@@ -38,9 +37,9 @@ export declare const redirectsModule: {
|
|
|
38
37
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
39
38
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
40
39
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
41
|
-
readonly exact: "
|
|
42
|
-
readonly prefix: "
|
|
43
|
-
readonly wildcard: "
|
|
40
|
+
readonly exact: "Exact match";
|
|
41
|
+
readonly prefix: "Starts with";
|
|
42
|
+
readonly wildcard: "Wildcard";
|
|
44
43
|
readonly Status: "Status";
|
|
45
44
|
readonly More: "More";
|
|
46
45
|
readonly Delete: "Delete";
|
|
@@ -48,8 +47,8 @@ export declare const redirectsModule: {
|
|
|
48
47
|
readonly Enable: "Enable";
|
|
49
48
|
readonly "Saving\u2026": "Saving…";
|
|
50
49
|
readonly Created: "Created";
|
|
51
|
-
readonly active: "
|
|
52
|
-
readonly disabled: "
|
|
50
|
+
readonly active: "Active";
|
|
51
|
+
readonly disabled: "Disabled";
|
|
53
52
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
54
53
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
55
54
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -57,6 +56,9 @@ export declare const redirectsModule: {
|
|
|
57
56
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
58
57
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
59
58
|
readonly "\"?": "\"?";
|
|
59
|
+
readonly manual: "Manual";
|
|
60
|
+
readonly auto_slug_change: "URL change";
|
|
61
|
+
readonly import: "Imported";
|
|
60
62
|
};
|
|
61
63
|
readonly pages: {
|
|
62
64
|
readonly list: {
|
|
@@ -22,10 +22,10 @@ export declare const seoMessagesEn: {
|
|
|
22
22
|
readonly Nofollow: "Nofollow";
|
|
23
23
|
readonly "OG title": "OG title";
|
|
24
24
|
readonly "OG description": "OG description";
|
|
25
|
-
readonly "OG image
|
|
25
|
+
readonly "OG image": "OG image";
|
|
26
26
|
readonly "Twitter title": "Twitter title";
|
|
27
27
|
readonly "Twitter description": "Twitter description";
|
|
28
|
-
readonly "Twitter image
|
|
28
|
+
readonly "Twitter image": "Twitter image";
|
|
29
29
|
readonly "Saving\u2026": "Saving…";
|
|
30
30
|
readonly "Save overrides": "Save overrides";
|
|
31
31
|
readonly "Per-entry SEO": "Per-entry SEO";
|
|
@@ -33,7 +33,7 @@ export declare const seoMessagesEn: {
|
|
|
33
33
|
readonly "Title template (must contain %s)": "Title template (must contain %s)";
|
|
34
34
|
readonly "Default meta description": "Default meta description";
|
|
35
35
|
readonly "Social sharing": "Social sharing";
|
|
36
|
-
readonly "Default Open Graph / Twitter image
|
|
36
|
+
readonly "Default Open Graph / Twitter image": "Default Open Graph / Twitter image";
|
|
37
37
|
readonly "Twitter @site handle": "Twitter @site handle";
|
|
38
38
|
readonly Crawling: "Crawling";
|
|
39
39
|
readonly "Default noindex": "Default noindex";
|
|
@@ -41,7 +41,7 @@ export declare const seoMessagesEn: {
|
|
|
41
41
|
readonly "Sitemap enabled": "Sitemap enabled";
|
|
42
42
|
readonly "Save settings": "Save settings";
|
|
43
43
|
readonly "Cached sitemap": "Cached sitemap";
|
|
44
|
-
readonly "
|
|
44
|
+
readonly "Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.";
|
|
45
45
|
readonly "Working\u2026": "Working…";
|
|
46
46
|
readonly "Regenerate sitemap": "Regenerate sitemap";
|
|
47
47
|
readonly "View sitemap": "View sitemap";
|
|
@@ -74,5 +74,6 @@ export declare const seoMessagesEn: {
|
|
|
74
74
|
readonly "failed to regenerate sitemap": "failed to regenerate sitemap";
|
|
75
75
|
readonly "failed to load the sitemap": "failed to load the sitemap";
|
|
76
76
|
readonly "Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).";
|
|
77
|
+
readonly "Selected image": "Selected image";
|
|
77
78
|
};
|
|
78
79
|
//# sourceMappingURL=messages.en.d.ts.map
|
package/dist/seo/messages.en.js
CHANGED
|
@@ -22,10 +22,10 @@ export const seoMessagesEn = {
|
|
|
22
22
|
"Nofollow": "Nofollow",
|
|
23
23
|
"OG title": "OG title",
|
|
24
24
|
"OG description": "OG description",
|
|
25
|
-
"OG image
|
|
25
|
+
"OG image": "OG image",
|
|
26
26
|
"Twitter title": "Twitter title",
|
|
27
27
|
"Twitter description": "Twitter description",
|
|
28
|
-
"Twitter image
|
|
28
|
+
"Twitter image": "Twitter image",
|
|
29
29
|
"Saving…": "Saving…",
|
|
30
30
|
"Save overrides": "Save overrides",
|
|
31
31
|
"Per-entry SEO": "Per-entry SEO",
|
|
@@ -33,7 +33,7 @@ export const seoMessagesEn = {
|
|
|
33
33
|
"Title template (must contain %s)": "Title template (must contain %s)",
|
|
34
34
|
"Default meta description": "Default meta description",
|
|
35
35
|
"Social sharing": "Social sharing",
|
|
36
|
-
"Default Open Graph / Twitter image
|
|
36
|
+
"Default Open Graph / Twitter image": "Default Open Graph / Twitter image",
|
|
37
37
|
"Twitter @site handle": "Twitter @site handle",
|
|
38
38
|
"Crawling": "Crawling",
|
|
39
39
|
"Default noindex": "Default noindex",
|
|
@@ -41,7 +41,7 @@ export const seoMessagesEn = {
|
|
|
41
41
|
"Sitemap enabled": "Sitemap enabled",
|
|
42
42
|
"Save settings": "Save settings",
|
|
43
43
|
"Cached sitemap": "Cached sitemap",
|
|
44
|
-
"
|
|
44
|
+
"Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.",
|
|
45
45
|
"Working…": "Working…",
|
|
46
46
|
"Regenerate sitemap": "Regenerate sitemap",
|
|
47
47
|
"View sitemap": "View sitemap",
|
|
@@ -73,6 +73,7 @@ export const seoMessagesEn = {
|
|
|
73
73
|
"Sitemap regeneration accepted.": "Sitemap regeneration accepted.",
|
|
74
74
|
"failed to regenerate sitemap": "failed to regenerate sitemap",
|
|
75
75
|
"failed to load the sitemap": "failed to load the sitemap",
|
|
76
|
-
"Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status})."
|
|
76
|
+
"Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).",
|
|
77
|
+
"Selected image": "Selected image",
|
|
77
78
|
};
|
|
78
79
|
//# sourceMappingURL=messages.en.js.map
|
|
@@ -12,6 +12,10 @@ import { useWiredMediaRefField } from "../hooks/MediaRefField.hooks.js";
|
|
|
12
12
|
* `react/hooks/MediaRefField.hooks.ts`, split out the same way `MediaPickerDialog`/`MediaPickerDialog.hooks
|
|
13
13
|
* .tsx` does; this file stays props-and-JSX only. `MediaPickerDialog` itself is reused unchanged
|
|
14
14
|
* (`components/MediaPickerDialog/MediaPickerDialog.tsx`) — no fork, no new picker UI.
|
|
15
|
+
*
|
|
16
|
+
* 2026-10-08 polish: the original editable-input rationale above still applies to pasted URLs
|
|
17
|
+
* and empty fields. A selected library reference now shows plain copy with its preview; Remove
|
|
18
|
+
* returns to manual entry. A hidden input preserves the exact FormData value on defaults saves.
|
|
15
19
|
*/
|
|
16
20
|
export interface MediaRefFieldProps {
|
|
17
21
|
locale: string;
|
|
@@ -5,8 +5,8 @@ import { useSeoCopy } from "../hooks/SeoPorts.hooks.js";
|
|
|
5
5
|
import { useWiredMediaRefField, useMediaRefPresentation, handleSpread } from "../hooks/MediaRefField.hooks.js";
|
|
6
6
|
export function MediaRefField({ locale, id, name, label, value, onChange, agentHandle: base, useField = useWiredMediaRefField, }, _optional = {}) {
|
|
7
7
|
const t = useSeoCopy();
|
|
8
|
-
const { Picker = MediaPickerBridge } = useMediaRefPresentation();
|
|
8
|
+
const { Picker = MediaPickerBridge, storedReference } = useMediaRefPresentation({ value });
|
|
9
9
|
const { pickerOpen, openPicker, closePicker, handleSelect, clear, previewUrl, accept } = useField({ value, onChange });
|
|
10
|
-
return (_jsxs("div", { className: "field media-ref-field", children: [_jsx("label", { className: "field-label", htmlFor: id, children: label }), _jsxs("div", { className: "media-ref-field-row", children: [_jsx("input", { id: id, name: name, value: value, onChange: (e) => onChange(e.target.value), ...(base ? agentHandle({ handle: base }, { role: "field", label }) : {}) }), _jsx("button", { type: "button", className: "btn-secondary", onClick: openPicker, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "choose", label: `Choose an image for: ${label}` }), children: t({ locale: locale, key: "Choose image" }) }), value ? (_jsx("button", { type: "button", className: "btn-secondary", onClick: clear, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "clear", label: `Remove the selected image for: ${label}` }), children: t({ locale: locale, key: "Remove" }) })) : null] }), previewUrl ? _jsx("img", { className: "media-ref-field-preview", src: previewUrl, alt: `${label} preview` }) : null, pickerOpen ? (_jsx(Picker, { onSelect: handleSelect, onCancel: closePicker, accept: accept, agentHandle: base ? `${base}-dialog` : undefined })) : null] }));
|
|
10
|
+
return (_jsxs("div", { className: "jini-field jini-media-ref-field", children: [_jsx("label", { className: "jini-field-label", htmlFor: id, children: label }), _jsxs("div", { className: "jini-media-ref-field-row", children: [_jsx("input", { className: "jini-input", id: id, name: storedReference ? undefined : name, value: storedReference ? t({ locale, key: "Selected image" }) : value, readOnly: storedReference, onChange: (e) => onChange(e.target.value), ...(base ? agentHandle({ handle: base }, { role: "field", label }) : {}) }), storedReference && name ? _jsx("input", { type: "hidden", name: name, value: value }) : null, _jsx("button", { type: "button", className: "jini-btn jini-btn-secondary", onClick: openPicker, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "choose", label: `Choose an image for: ${label}` }), children: t({ locale: locale, key: "Choose image" }) }), value ? (_jsx("button", { type: "button", className: "jini-btn jini-btn-secondary", onClick: clear, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "clear", label: `Remove the selected image for: ${label}` }), children: t({ locale: locale, key: "Remove" }) })) : null] }), previewUrl ? _jsx("img", { className: "jini-media-ref-field-preview", src: previewUrl, alt: `${label} preview` }) : null, pickerOpen ? (_jsx(Picker, { onSelect: handleSelect, onCancel: closePicker, accept: accept, agentHandle: base ? `${base}-dialog` : undefined })) : null] }));
|
|
11
11
|
}
|
|
12
12
|
//# sourceMappingURL=MediaRefField.js.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { agentHandle } from "@jini-ai/agentic";
|
|
3
3
|
import { Dialog } from "@jini-ai/ui-kit/react";
|
|
4
|
-
import {
|
|
4
|
+
import { formatTimestamp } from "@jini-ai/ui/panel-kit";
|
|
5
|
+
import { useSeoCopy, useSeoOptions } from "../hooks/SeoPorts.hooks.js";
|
|
5
6
|
import { actionLabel } from "../../rules.js";
|
|
6
7
|
import { useWiredSitemapModal } from "../hooks/use-sitemap-modal.hooks.js";
|
|
7
8
|
import { useSitemapModalRegenerate, useSitemapPresentation, useSitemapTable, useSitemapViewToggle } from "../hooks/SitemapModal.hooks.js";
|
|
@@ -30,13 +31,14 @@ function SitemapModalHeaderActions({ locale, modal }) {
|
|
|
30
31
|
* `useSitemapModal` (memoized there), this only maps them to JSX. */
|
|
31
32
|
function SitemapModalTable({ locale, modal }) {
|
|
32
33
|
const t = useSeoCopy();
|
|
34
|
+
const { formatDate = formatTimestamp } = useSeoOptions();
|
|
33
35
|
const { rowHandles } = useSitemapTable({ modal });
|
|
34
36
|
if (modal.entries.length === 0)
|
|
35
37
|
return _jsx("div", { className: "notice", children: t({ locale: locale, key: "The sitemap has no URLs yet." }) });
|
|
36
38
|
return (_jsxs(_Fragment, { children: [_jsx("input", { type: "search", className: "sitemap-modal-filter", "aria-label": t({ locale: locale, key: "Filter sitemap URLs" }), placeholder: t({ locale: locale, key: "Filter by URL…" }), value: modal.filter, onChange: (e) => modal.setFilter(e.target.value), ...agentHandle({ handle: "seo-sitemap-filter" }, {
|
|
37
39
|
role: "field",
|
|
38
40
|
label: "Narrow the sitemap table by a substring match on the URL",
|
|
39
|
-
}) }), modal.filteredEntries.length === 0 ? (_jsx("p", { className: "muted-cell", children: t({ locale: locale, key: "No URLs match this filter." }) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("table", { className: "list-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: t({ locale: locale, key: "URL" }) }), _jsx("th", { children: t({ locale: locale, key: "Last modified" }) })] }) }), _jsx("tbody", { children: modal.filteredEntries.map((entry, index) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("a", { href: entry.loc, target: "_blank", rel: "noreferrer", ...agentHandle({ handle: rowHandles[index] }, { role: "link", label: "Open this URL on the live site" }), children: entry.loc }) }), _jsx("td", { children: entry.lastmod
|
|
41
|
+
}) }), modal.filteredEntries.length === 0 ? (_jsx("p", { className: "muted-cell", children: t({ locale: locale, key: "No URLs match this filter." }) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("table", { className: "list-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: t({ locale: locale, key: "URL" }) }), _jsx("th", { children: t({ locale: locale, key: "Last modified" }) })] }) }), _jsx("tbody", { children: modal.filteredEntries.map((entry, index) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("a", { href: entry.loc, target: "_blank", rel: "noreferrer", ...agentHandle({ handle: rowHandles[index] }, { role: "link", label: "Open this URL on the live site" }), children: entry.loc }) }), _jsx("td", { children: entry.lastmod === null ? _jsx("span", { className: "muted-cell", children: t({ locale: locale, key: "—" }) }) : formatDate({ iso: entry.lastmod }) })] }, entry.loc))) })] }) }))] }));
|
|
40
42
|
}
|
|
41
43
|
/** The body's content-status switch (REQ 8/9: disabled, loading, error, then raw-vs-table) — kept
|
|
42
44
|
* as its own flat sequence of guards rather than a nested ternary inline in {@link SitemapModal}.
|
|
@@ -11,8 +11,11 @@ export declare function useWiredMediaRefField({ value, onChange }: {
|
|
|
11
11
|
onChange: (value: string) => void;
|
|
12
12
|
}, _optional?: Record<string, never>): MediaRefFieldController;
|
|
13
13
|
/** Slot or existing promise picker; no picker implementation is forked into SEO. */
|
|
14
|
-
export declare function useMediaRefPresentation(
|
|
14
|
+
export declare function useMediaRefPresentation({ value }: {
|
|
15
|
+
value: string;
|
|
16
|
+
}, _optional?: Record<string, never>): {
|
|
15
17
|
Picker: import("react").ComponentType<import("../options.js").SeoMediaPickerSlotProps> | undefined;
|
|
18
|
+
storedReference: boolean;
|
|
16
19
|
};
|
|
17
20
|
export declare function handleSpread({ base, suffix, label }: {
|
|
18
21
|
base?: string;
|
|
@@ -2,7 +2,7 @@ import { useRef } from 'react';
|
|
|
2
2
|
import { agentHandle } from '@jini-ai/agentic';
|
|
3
3
|
import { useController } from '../../../core/react/use-controller.js';
|
|
4
4
|
import { createMediaRefController } from '../../controllers/media-ref.controller.js';
|
|
5
|
-
import { resolveMediaRefPreviewUrl } from '../../rules.js';
|
|
5
|
+
import { isStoredMediaRef, resolveMediaRefPreviewUrl } from '../../rules.js';
|
|
6
6
|
import { useSeoPorts, useSeoOptions } from './SeoPorts.hooks.js';
|
|
7
7
|
export function useMediaRefField({ value, onChange, api }, _optional = {}) {
|
|
8
8
|
const change = useRef(onChange);
|
|
@@ -20,9 +20,9 @@ export function useWiredMediaRefField({ value, onChange }, _optional = {}) {
|
|
|
20
20
|
return useMediaRefField({ value, onChange, api });
|
|
21
21
|
}
|
|
22
22
|
/** Slot or existing promise picker; no picker implementation is forked into SEO. */
|
|
23
|
-
export function useMediaRefPresentation(
|
|
23
|
+
export function useMediaRefPresentation({ value }, _optional = {}) {
|
|
24
24
|
const { slots } = useSeoOptions();
|
|
25
|
-
return { Picker: slots?.MediaPickerDialog };
|
|
25
|
+
return { Picker: slots?.MediaPickerDialog, storedReference: isStoredMediaRef({ value }) };
|
|
26
26
|
}
|
|
27
27
|
export function handleSpread({ base, suffix, label }, _optional = {}) {
|
|
28
28
|
return base ? agentHandle({ handle: `${base}-${suffix}` }, { role: 'button', label }) : {};
|
|
@@ -38,10 +38,10 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
38
38
|
readonly Nofollow: "Nofollow";
|
|
39
39
|
readonly "OG title": "OG title";
|
|
40
40
|
readonly "OG description": "OG description";
|
|
41
|
-
readonly "OG image
|
|
41
|
+
readonly "OG image": "OG image";
|
|
42
42
|
readonly "Twitter title": "Twitter title";
|
|
43
43
|
readonly "Twitter description": "Twitter description";
|
|
44
|
-
readonly "Twitter image
|
|
44
|
+
readonly "Twitter image": "Twitter image";
|
|
45
45
|
readonly "Saving\u2026": "Saving…";
|
|
46
46
|
readonly "Save overrides": "Save overrides";
|
|
47
47
|
readonly "Per-entry SEO": "Per-entry SEO";
|
|
@@ -49,7 +49,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
49
49
|
readonly "Title template (must contain %s)": "Title template (must contain %s)";
|
|
50
50
|
readonly "Default meta description": "Default meta description";
|
|
51
51
|
readonly "Social sharing": "Social sharing";
|
|
52
|
-
readonly "Default Open Graph / Twitter image
|
|
52
|
+
readonly "Default Open Graph / Twitter image": "Default Open Graph / Twitter image";
|
|
53
53
|
readonly "Twitter @site handle": "Twitter @site handle";
|
|
54
54
|
readonly Crawling: "Crawling";
|
|
55
55
|
readonly "Default noindex": "Default noindex";
|
|
@@ -57,7 +57,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
57
57
|
readonly "Sitemap enabled": "Sitemap enabled";
|
|
58
58
|
readonly "Save settings": "Save settings";
|
|
59
59
|
readonly "Cached sitemap": "Cached sitemap";
|
|
60
|
-
readonly "
|
|
60
|
+
readonly "Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.";
|
|
61
61
|
readonly "Working\u2026": "Working…";
|
|
62
62
|
readonly "Regenerate sitemap": "Regenerate sitemap";
|
|
63
63
|
readonly "View sitemap": "View sitemap";
|
|
@@ -90,6 +90,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
90
90
|
readonly "failed to regenerate sitemap": "failed to regenerate sitemap";
|
|
91
91
|
readonly "failed to load the sitemap": "failed to load the sitemap";
|
|
92
92
|
readonly "Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).";
|
|
93
|
+
readonly "Selected image": "Selected image";
|
|
93
94
|
};
|
|
94
95
|
pages: {
|
|
95
96
|
readonly settings: {
|
|
@@ -159,10 +160,10 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
159
160
|
readonly Nofollow: "Nofollow";
|
|
160
161
|
readonly "OG title": "OG title";
|
|
161
162
|
readonly "OG description": "OG description";
|
|
162
|
-
readonly "OG image
|
|
163
|
+
readonly "OG image": "OG image";
|
|
163
164
|
readonly "Twitter title": "Twitter title";
|
|
164
165
|
readonly "Twitter description": "Twitter description";
|
|
165
|
-
readonly "Twitter image
|
|
166
|
+
readonly "Twitter image": "Twitter image";
|
|
166
167
|
readonly "Saving\u2026": "Saving…";
|
|
167
168
|
readonly "Save overrides": "Save overrides";
|
|
168
169
|
readonly "Per-entry SEO": "Per-entry SEO";
|
|
@@ -170,7 +171,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
170
171
|
readonly "Title template (must contain %s)": "Title template (must contain %s)";
|
|
171
172
|
readonly "Default meta description": "Default meta description";
|
|
172
173
|
readonly "Social sharing": "Social sharing";
|
|
173
|
-
readonly "Default Open Graph / Twitter image
|
|
174
|
+
readonly "Default Open Graph / Twitter image": "Default Open Graph / Twitter image";
|
|
174
175
|
readonly "Twitter @site handle": "Twitter @site handle";
|
|
175
176
|
readonly Crawling: "Crawling";
|
|
176
177
|
readonly "Default noindex": "Default noindex";
|
|
@@ -178,7 +179,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
178
179
|
readonly "Sitemap enabled": "Sitemap enabled";
|
|
179
180
|
readonly "Save settings": "Save settings";
|
|
180
181
|
readonly "Cached sitemap": "Cached sitemap";
|
|
181
|
-
readonly "
|
|
182
|
+
readonly "Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.";
|
|
182
183
|
readonly "Working\u2026": "Working…";
|
|
183
184
|
readonly "Regenerate sitemap": "Regenerate sitemap";
|
|
184
185
|
readonly "View sitemap": "View sitemap";
|
|
@@ -211,6 +212,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
211
212
|
readonly "failed to regenerate sitemap": "failed to regenerate sitemap";
|
|
212
213
|
readonly "failed to load the sitemap": "failed to load the sitemap";
|
|
213
214
|
readonly "Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).";
|
|
215
|
+
readonly "Selected image": "Selected image";
|
|
214
216
|
};
|
|
215
217
|
readonly pages: {
|
|
216
218
|
readonly settings: {
|
|
@@ -281,10 +283,10 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
281
283
|
readonly Nofollow: "Nofollow";
|
|
282
284
|
readonly "OG title": "OG title";
|
|
283
285
|
readonly "OG description": "OG description";
|
|
284
|
-
readonly "OG image
|
|
286
|
+
readonly "OG image": "OG image";
|
|
285
287
|
readonly "Twitter title": "Twitter title";
|
|
286
288
|
readonly "Twitter description": "Twitter description";
|
|
287
|
-
readonly "Twitter image
|
|
289
|
+
readonly "Twitter image": "Twitter image";
|
|
288
290
|
readonly "Saving\u2026": "Saving…";
|
|
289
291
|
readonly "Save overrides": "Save overrides";
|
|
290
292
|
readonly "Per-entry SEO": "Per-entry SEO";
|
|
@@ -292,7 +294,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
292
294
|
readonly "Title template (must contain %s)": "Title template (must contain %s)";
|
|
293
295
|
readonly "Default meta description": "Default meta description";
|
|
294
296
|
readonly "Social sharing": "Social sharing";
|
|
295
|
-
readonly "Default Open Graph / Twitter image
|
|
297
|
+
readonly "Default Open Graph / Twitter image": "Default Open Graph / Twitter image";
|
|
296
298
|
readonly "Twitter @site handle": "Twitter @site handle";
|
|
297
299
|
readonly Crawling: "Crawling";
|
|
298
300
|
readonly "Default noindex": "Default noindex";
|
|
@@ -300,7 +302,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
300
302
|
readonly "Sitemap enabled": "Sitemap enabled";
|
|
301
303
|
readonly "Save settings": "Save settings";
|
|
302
304
|
readonly "Cached sitemap": "Cached sitemap";
|
|
303
|
-
readonly "
|
|
305
|
+
readonly "Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.";
|
|
304
306
|
readonly "Working\u2026": "Working…";
|
|
305
307
|
readonly "Regenerate sitemap": "Regenerate sitemap";
|
|
306
308
|
readonly "View sitemap": "View sitemap";
|
|
@@ -333,6 +335,7 @@ export declare function seo({ siteUrl }: Pick<SeoReactOptions, 'siteUrl'>, optio
|
|
|
333
335
|
readonly "failed to regenerate sitemap": "failed to regenerate sitemap";
|
|
334
336
|
readonly "failed to load the sitemap": "failed to load the sitemap";
|
|
335
337
|
readonly "Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).";
|
|
338
|
+
readonly "Selected image": "Selected image";
|
|
336
339
|
};
|
|
337
340
|
readonly pages: {
|
|
338
341
|
readonly settings: {
|
|
@@ -11,6 +11,13 @@ export interface SeoReactOptions {
|
|
|
11
11
|
siteUrl: () => string;
|
|
12
12
|
t?: SeoTranslator | undefined;
|
|
13
13
|
describeError?: SeoErrorFormatter | undefined;
|
|
14
|
+
/** Format parsed lastmod values in the host's live locale/timezone; raw XML remains untouched.
|
|
15
|
+
* Omit to use the shared compact ISO timestamp display.
|
|
16
|
+
* @example ({ iso }) => formDateDisplay({ iso, locale }).text
|
|
17
|
+
*/
|
|
18
|
+
formatDate?: ((required: {
|
|
19
|
+
iso: string;
|
|
20
|
+
}, optional?: Record<string, never>) => string) | undefined;
|
|
14
21
|
headerActions?: ReactNode;
|
|
15
22
|
slots?: {
|
|
16
23
|
MediaPickerDialog?: ComponentType<SeoMediaPickerSlotProps>;
|