@canvas-digital/blog-sdk 2.0.2 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blog-client.iife.js +1 -1
- package/dist/components/admin/AdminPostDetail.js +5 -5
- package/dist/components/admin/BrandSettings.js +5 -5
- package/dist/components/admin/BrandSwitcher.js +1 -1
- package/dist/components/admin/Chips.js +5 -5
- package/dist/components/admin/CommentsManager.js +6 -6
- package/dist/components/admin/Dashboard.js +1 -1
- package/dist/components/admin/MediaLibrary.js +5 -5
- package/dist/components/admin/MediaPicker.js +4 -4
- package/dist/components/admin/PostList.d.ts.map +1 -1
- package/dist/components/admin/PostList.js +13 -4
- package/dist/components/admin/PostsTable.d.ts +6 -1
- package/dist/components/admin/PostsTable.d.ts.map +1 -1
- package/dist/components/admin/PostsTable.js +15 -9
- package/dist/components/admin/Shell.js +3 -3
- package/dist/components/admin/TermManager.js +4 -4
- package/dist/components/admin/UsersManager.js +3 -3
- package/dist/components/admin/charts.js +7 -7
- package/dist/components/admin/editor/PostEditor.js +16 -16
- package/dist/components/admin/editor/RichTextEditor.js +8 -8
- package/dist/components/admin/editor/YoastCollapsible.js +2 -2
- package/dist/components/admin/editor/YoastInsightsPanel.js +1 -1
- package/dist/components/admin/editor/YoastInternalLinksPanel.js +1 -1
- package/dist/components/admin/editor/YoastSeoAnalysisPanel.js +6 -6
- package/dist/components/admin/editor/YoastSeoMetabox.js +8 -8
- package/dist/components/admin/editor/YoastSnippetField.js +2 -2
- package/dist/components/admin/internal/States.js +3 -3
- package/dist/components/admin/mock/store.d.ts.map +1 -1
- package/dist/components/admin/mock/store.js +3 -2
- package/dist/components/admin/seo/Ga4Settings.js +6 -6
- package/dist/components/admin/seo/RedirectAnalyticsDashboard.js +1 -1
- package/dist/components/admin/seo/RedirectDetail.js +6 -6
- package/dist/components/admin/seo/RedirectForm.js +1 -1
- package/dist/components/admin/seo/RedirectList.js +4 -4
- package/dist/components/admin/seo/RobotsEditor.js +1 -1
- package/dist/components/admin/seo/shared.js +2 -2
- package/dist/components/admin/tools/ToolsHub.js +4 -4
- package/dist/components/user/BlogCard.js +3 -3
- package/dist/components/user/BlogCategories.js +1 -1
- package/dist/components/user/BlogDetail.js +1 -1
- package/dist/components/user/BlogList.js +1 -1
- package/dist/components/user/BlogSearch.js +2 -2
- package/dist/components/user/BlogTags.js +1 -1
- package/dist/components/user/FeaturedBlogs.js +1 -1
- package/dist/components/user/RelatedBlogs.js +1 -1
- package/dist/components/user/SiteMediaHero.js +1 -1
- package/dist/components/user/detail/ArticleDetailHero.js +5 -5
- package/dist/components/user/detail/ArticleRailDetails.js +2 -2
- package/dist/components/user/detail/CommentSection.js +2 -2
- package/dist/components/user/detail/HeroFadeSlide.js +1 -1
- package/dist/components/user/detail/ReadingProgress.js +1 -1
- package/dist/components/user/detail/ShareRow.js +1 -1
- package/dist/components/user/internal/States.js +4 -4
- package/dist/lib/lexical-doc.js +1 -1
- package/dist/pages/admin/BlogAdmin.d.ts.map +1 -1
- package/dist/pages/admin/BlogAdmin.js +23 -11
- package/dist/services/admin-sdk-client.d.ts +9 -0
- package/dist/services/admin-sdk-client.d.ts.map +1 -1
- package/dist/services/admin-sdk-client.js +17 -0
- package/dist/style.css +1023 -1016
- package/package.json +2 -1
|
@@ -386,7 +386,7 @@ export const RichTextEditor = ({ initialHtml, onChange, onPickImage, searchTarge
|
|
|
386
386
|
}, 220);
|
|
387
387
|
return () => clearTimeout(id);
|
|
388
388
|
}, [linkOpen, linkQuery, searchTargets]);
|
|
389
|
-
const linkPopover = linkOpen && linkPos && mode === 'visual' ? (_jsxs("div", { ref: linkPopoverRef, className: "
|
|
389
|
+
const linkPopover = linkOpen && linkPos && mode === 'visual' ? (_jsxs("div", { ref: linkPopoverRef, className: "blog_ed-link-popover", style: { top: linkPos.top, left: linkPos.left }, role: "dialog", "aria-label": "Insert link", onMouseDown: (e) => e.stopPropagation(), children: [linkSelection ? _jsxs("p", { className: "blog_ed-link-selection", children: ["Linking: \u201C", linkSelection, "\u201D"] }) : null, _jsxs("div", { className: "blog_ed-link-row", children: [_jsx("input", { className: "blog_fld", placeholder: "Paste URL or type to search", value: linkUrl || linkQuery, onChange: (e) => {
|
|
390
390
|
const v = e.target.value;
|
|
391
391
|
if (/^https?:\/\//i.test(v) || v.includes('.')) {
|
|
392
392
|
setLinkUrl(v);
|
|
@@ -404,13 +404,13 @@ export const RichTextEditor = ({ initialHtml, onChange, onPickImage, searchTarge
|
|
|
404
404
|
}
|
|
405
405
|
if (e.key === 'Escape')
|
|
406
406
|
closeLinkDialog();
|
|
407
|
-
}, autoFocus: true }), _jsx("button", { type: "button", className: "
|
|
407
|
+
}, autoFocus: true }), _jsx("button", { type: "button", className: "blog_btn blog_btn-primary blog_btn-tiny", onMouseDown: (e) => e.preventDefault(), onClick: applyExternalLink, disabled: !linkUrl.trim(), children: "Apply" })] }), _jsxs("label", { className: "blog_ed-link-tab", children: [_jsx("input", { type: "checkbox", checked: linkNewTab, onChange: (e) => setLinkNewTab(e.target.checked) }), "Open in new tab"] }), hits.length ? (_jsx("ul", { className: "blog_ed-link-hits", children: hits.map((hit) => (_jsx("li", { children: _jsxs("button", { type: "button", onMouseDown: (e) => e.preventDefault(), onClick: () => applyInternalLink(hit), children: [_jsx("span", { className: "blog_hit-label", children: hit.label }), _jsx("span", { className: "blog_hit-path blog_mono", children: hit.path })] }) }, `${hit.collection}-${hit.id}`))) })) : linkQuery.trim() ? (_jsx("p", { className: "blog_ed-link-note", children: "No posts or categories match." })) : null, _jsxs("div", { className: "blog_ed-link-actions", children: [marks.link ? (_jsx("button", { type: "button", className: "blog_linkish", onMouseDown: (e) => e.preventDefault(), onClick: removeLink, children: "Remove link" })) : null, _jsx("button", { type: "button", className: "blog_linkish", onClick: closeLinkDialog, children: "Cancel" })] })] })) : null;
|
|
408
408
|
const insertImage = async () => {
|
|
409
409
|
const picked = await onPickImage();
|
|
410
410
|
if (!picked)
|
|
411
411
|
return;
|
|
412
412
|
focusBack();
|
|
413
|
-
document.execCommand('insertHTML', false, `<figure class="
|
|
413
|
+
document.execCommand('insertHTML', false, `<figure class="blog_ed-figure" contenteditable="false" data-media-id="${escapeAttr(picked.id)}">` +
|
|
414
414
|
`<img src="${escapeAttr(picked.url)}" alt="${escapeAttr(picked.alt)}">` +
|
|
415
415
|
`<figcaption>${escapeAttr(picked.alt || 'Image')}</figcaption></figure><p><br></p>`);
|
|
416
416
|
emit();
|
|
@@ -447,8 +447,8 @@ export const RichTextEditor = ({ initialHtml, onChange, onPickImage, searchTarge
|
|
|
447
447
|
}
|
|
448
448
|
};
|
|
449
449
|
const [active, setActive] = useState(false);
|
|
450
|
-
const Btn = ({ cmd, label, title, onClick, active: btnActive, }) => (_jsx("button", { type: "button", className: `
|
|
451
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: `
|
|
450
|
+
const Btn = ({ cmd, label, title, onClick, active: btnActive, }) => (_jsx("button", { type: "button", className: `blog_tb-btn${btnActive ? ' blog_is-on' : ''}`, title: title, "aria-label": title, "aria-pressed": btnActive ? 'true' : 'false', onMouseDown: (e) => e.preventDefault(), onClick: () => (onClick ? onClick() : cmd ? exec(cmd) : undefined), children: label }));
|
|
451
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: `blog_ed${active ? ' blog_is-active' : ''}`, onFocusCapture: () => setActive(true), onBlurCapture: (e) => {
|
|
452
452
|
const root = e.currentTarget;
|
|
453
453
|
const next = e.relatedTarget;
|
|
454
454
|
if (next && root.contains(next))
|
|
@@ -463,13 +463,13 @@ export const RichTextEditor = ({ initialHtml, onChange, onPickImage, searchTarge
|
|
|
463
463
|
return;
|
|
464
464
|
setActive(false);
|
|
465
465
|
}, 0);
|
|
466
|
-
}, children: [_jsxs("div", { className: "
|
|
466
|
+
}, children: [_jsxs("div", { className: "blog_ed-chrome", children: [_jsxs("div", { className: "blog_ed-mode-tabs", role: "tablist", "aria-label": "Editor mode", children: [_jsx("button", { type: "button", role: "tab", className: mode === 'visual' ? 'blog_is-on' : undefined, "aria-selected": mode === 'visual', onClick: () => switchMode('visual'), children: "Visual" }), _jsx("button", { type: "button", role: "tab", className: mode === 'code' ? 'blog_is-on' : undefined, "aria-selected": mode === 'code', onClick: () => switchMode('code'), children: "Code" })] }), mode === 'visual' ? (_jsxs("div", { className: "blog_ed-toolbar", role: "toolbar", "aria-label": "Formatting", children: [_jsx("button", { type: "button", className: "blog_tb-btn blog_tb-media", title: "Add Media", onMouseDown: (e) => e.preventDefault(), onClick: () => void insertImage(), children: "Add Media" }), _jsx("select", { className: "blog_tb-select", value: BLOCKS.some((b) => b.tag === block) ? block : 'p', onChange: (e) => setBlockTag(e.target.value), "aria-label": "Text style", children: BLOCKS.map((b) => (_jsx("option", { value: b.tag, children: b.label }, b.tag))) }), _jsx("span", { className: "blog_tb-sep" }), _jsx(Btn, { cmd: "bold", label: _jsx("b", { children: "B" }), title: "Bold (\u2318B)", active: marks.bold }), _jsx(Btn, { cmd: "italic", label: _jsx("i", { children: "I" }), title: "Italic (\u2318I)", active: marks.italic }), _jsx(Btn, { cmd: "underline", label: _jsx("u", { children: "U" }), title: "Underline (\u2318U)", active: marks.underline }), _jsx("span", { className: "blog_tb-sep" }), _jsx(Btn, { cmd: "insertUnorderedList", label: "\u2022\u2014", title: "Bulleted list", active: marks.insertUnorderedList }), _jsx(Btn, { cmd: "insertOrderedList", label: "1\u2014", title: "Numbered list", active: marks.insertOrderedList }), _jsx(Btn, { label: "\u275D", title: "Quote", onClick: toggleQuote, active: marks.quote }), _jsx("span", { className: "blog_tb-sep" }), _jsx(Btn, { cmd: "justifyLeft", label: "\u2261", title: "Align left" }), _jsx(Btn, { cmd: "justifyCenter", label: "\u2263", title: "Align centre" }), _jsx(Btn, { cmd: "justifyRight", label: "\u2261", title: "Align right" }), _jsx("span", { className: "blog_tb-sep" }), _jsx(Btn, { label: "\uD83D\uDD17", title: "Link (\u2318K)", onClick: () => {
|
|
467
467
|
refreshState();
|
|
468
468
|
openLinkDialog();
|
|
469
|
-
}, active: marks.link }), _jsx(Btn, { label: "\u26D3\uFE0E", title: "Remove link", onClick: () => exec('unlink') }), _jsx(Btn, { label: "\uD83D\uDDBC", title: "Insert image", onClick: insertImage }), _jsx("span", { className: "
|
|
469
|
+
}, active: marks.link }), _jsx(Btn, { label: "\u26D3\uFE0E", title: "Remove link", onClick: () => exec('unlink') }), _jsx(Btn, { label: "\uD83D\uDDBC", title: "Insert image", onClick: insertImage }), _jsx("span", { className: "blog_tb-sep" }), _jsx(Btn, { label: "\u25BE", title: "Toolbar toggle", active: moreTools, onClick: () => setMoreTools((v) => !v) }), _jsxs("span", { className: "blog_tb-count", children: [words, " words"] }), moreTools ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "blog_tb-sep" }), _jsx(Btn, { cmd: "strikeThrough", label: _jsx("s", { children: "S" }), title: "Strikethrough", active: marks.strikeThrough }), _jsx(Btn, { label: "\u2015", title: "Divider", onClick: () => exec('insertHorizontalRule') }), _jsxs("label", { className: "blog_tb-color", title: "Text colour", children: [_jsx("span", { "aria-hidden": "true", children: "A" }), _jsx("input", { type: "color", value: foreColor, onChange: (e) => {
|
|
470
470
|
setForeColor(e.target.value);
|
|
471
471
|
focusBack();
|
|
472
472
|
document.execCommand('foreColor', false, e.target.value);
|
|
473
473
|
emit();
|
|
474
|
-
}, "aria-label": "Text colour" })] }), _jsx(Btn, { label: "\u03A9", title: "Special character", onClick: () => setCharsOpen((v) => !v), active: charsOpen }), _jsx(Btn, { cmd: "outdent", label: "\u21E4", title: "Decrease indent" }), _jsx(Btn, { cmd: "indent", label: "\u21E5", title: "Increase indent" }), _jsx(Btn, { label: _jsx("span", { className: "
|
|
474
|
+
}, "aria-label": "Text colour" })] }), _jsx(Btn, { label: "\u03A9", title: "Special character", onClick: () => setCharsOpen((v) => !v), active: charsOpen }), _jsx(Btn, { cmd: "outdent", label: "\u21E4", title: "Decrease indent" }), _jsx(Btn, { cmd: "indent", label: "\u21E5", title: "Increase indent" }), _jsx(Btn, { label: _jsx("span", { className: "blog_mono", children: '</>' }), title: "Inline code", onClick: toggleCode, active: marks.code }), _jsx(Btn, { cmd: "removeFormat", label: "Tx", title: "Clear formatting" }), _jsx(Btn, { label: "\u21BA", title: "Undo", onClick: () => exec('undo') }), _jsx(Btn, { label: "\u21BB", title: "Redo", onClick: () => exec('redo') })] })) : null] })) : null, charsOpen && mode === 'visual' ? (_jsx("div", { className: "blog_ed-chars", role: "listbox", "aria-label": "Special characters", children: SPECIAL_CHARS.map((ch) => (_jsx("button", { type: "button", onMouseDown: (e) => e.preventDefault(), onClick: () => insertSpecial(ch), children: ch }, ch))) })) : null] }), mode === 'code' ? (_jsx("textarea", { className: "blog_ed-code blog_mono", value: codeHtml, onChange: (e) => setCodeHtml(e.target.value), "aria-label": "HTML source", spellCheck: false })) : !mounted ? (_jsx("div", { className: "blog_ed-surface", ref: surfaceRef, children: _jsx("div", { className: "blog_ed-input blog_prose blog_ed-skeleton", "aria-hidden": "true" }) })) : (_jsxs("div", { className: "blog_ed-surface", ref: surfaceRef, children: [empty ? _jsx("div", { className: "blog_ed-placeholder", children: "Tell the story\u2026" }) : null, _jsx("div", { ref: editorRef, className: "blog_ed-input blog_prose", contentEditable: true, suppressContentEditableWarning: true, role: "textbox", "aria-multiline": "true", "aria-label": "Post content", spellCheck: true, onInput: scheduleEmit, onBlur: emit, onPaste: onPaste, onKeyDown: onKeyDown, onKeyUp: refreshState, onMouseUp: refreshState })] }))] }), mounted && linkPopover ? createPortal(linkPopover, document.body) : null] }));
|
|
475
475
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
const AccChevron = () => (_jsx("span", { className: "
|
|
3
|
+
const AccChevron = () => (_jsx("span", { className: "blog_acc-chevron", "aria-hidden": "true", children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M2.5 4.5L6 8L9.5 4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
|
|
4
4
|
export { AccChevron };
|
|
5
|
-
export const YoastCollapsible = ({ title, defaultOpen = false, status, children, className }) => (_jsxs("details", { className: `
|
|
5
|
+
export const YoastCollapsible = ({ title, defaultOpen = false, status, children, className }) => (_jsxs("details", { className: `blog_yoast-collapse${className ? ` ${className}` : ''}`, open: defaultOpen, children: [_jsxs("summary", { className: "blog_yoast-collapse-summary", children: [_jsx(AccChevron, {}), _jsx("span", { className: "blog_yoast-collapse-title", children: title }), status ? _jsx("span", { className: "blog_yoast-collapse-status", children: status }) : null] }), _jsx("div", { className: "blog_yoast-collapse-body", children: children })] }));
|
|
@@ -27,5 +27,5 @@ export const YoastInsightsPanel = ({ contentText }) => {
|
|
|
27
27
|
.sort((a, b) => b[1] - a[1])
|
|
28
28
|
.slice(0, 8);
|
|
29
29
|
}, [words]);
|
|
30
|
-
return (_jsxs("div", { className: "
|
|
30
|
+
return (_jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsx("p", { className: "blog_yoast-help", children: "See word count and prominent terms used in your post content." }), _jsxs("div", { className: "blog_yoast-link-section", children: [_jsx("h4", { className: "blog_yoast-link-section-title", children: "Word count" }), _jsx("p", { className: "blog_yoast-insight-value", children: wordCount })] }), _jsxs("div", { className: "blog_yoast-link-section", children: [_jsx("h4", { className: "blog_yoast-link-section-title", children: "Prominent words" }), prominent.length === 0 ? (_jsx("p", { className: "blog_yoast-result-empty", children: "Add body content to see prominent words." })) : (_jsx("ul", { className: "blog_yoast-link-list", children: prominent.map(([word, count]) => (_jsxs("li", { children: [_jsx("span", { className: "blog_yoast-link-label", children: word }), _jsxs("span", { className: "blog_yoast-link-href", children: [count, " occurrences"] })] }, word))) }))] })] }));
|
|
31
31
|
};
|
|
@@ -31,5 +31,5 @@ export const YoastInternalLinksPanel = ({ contentHtml }) => {
|
|
|
31
31
|
}
|
|
32
32
|
return { outgoing, external };
|
|
33
33
|
}, [contentHtml]);
|
|
34
|
-
return (_jsxs("div", { className: "
|
|
34
|
+
return (_jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsx("p", { className: "blog_yoast-help", children: "Internal links help visitors and search engines navigate your site. Outbound links add context." }), _jsxs("div", { className: "blog_yoast-link-section", children: [_jsx("h4", { className: "blog_yoast-link-section-title", children: "Outgoing internal links" }), outgoing.length === 0 ? (_jsx("p", { className: "blog_yoast-result-empty", children: "No internal links in this post yet." })) : (_jsx("ul", { className: "blog_yoast-link-list", children: outgoing.map((l, i) => (_jsxs("li", { children: [_jsx("span", { className: "blog_yoast-link-label", children: l.label }), _jsx("span", { className: "blog_yoast-link-href blog_mono", children: l.href })] }, `${l.href}-${i}`))) }))] }), _jsxs("div", { className: "blog_yoast-link-section", children: [_jsx("h4", { className: "blog_yoast-link-section-title", children: "Outgoing external links" }), external.length === 0 ? (_jsx("p", { className: "blog_yoast-result-empty", children: "No external links in this post yet." })) : (_jsx("ul", { className: "blog_yoast-link-list", children: external.map((l, i) => (_jsxs("li", { children: [_jsx("span", { className: "blog_yoast-link-label", children: l.label }), _jsx("span", { className: "blog_yoast-link-href blog_mono", children: l.href })] }, `${l.href}-${i}`))) }))] })] }));
|
|
35
35
|
};
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { toneLabel } from '../../../lib/seo-analysis';
|
|
4
|
-
const Dot = ({ tone }) => (_jsx("span", { className: `
|
|
4
|
+
const Dot = ({ tone }) => (_jsx("span", { className: `blog_yoast-dot blog_yoast-dot-${tone}`, "aria-hidden": "true" }));
|
|
5
5
|
const CheckList = ({ items }) => {
|
|
6
6
|
if (!items.length) {
|
|
7
|
-
return _jsx("p", { className: "
|
|
7
|
+
return _jsx("p", { className: "blog_yoast-result-empty", children: "No items in this group." });
|
|
8
8
|
}
|
|
9
|
-
return (_jsx("ul", { className: "
|
|
9
|
+
return (_jsx("ul", { className: "blog_yoast-link-list", children: items.map((c) => (_jsxs("li", { children: [_jsxs("span", { className: "blog_yoast-link-label", children: [_jsx(Dot, { tone: c.tone }), " ", c.label] }), _jsx("span", { className: "blog_yoast-link-href", children: c.detail })] }, c.id))) }));
|
|
10
10
|
};
|
|
11
|
-
const AnalysisBlock = ({ title, items, }) => (_jsxs("div", { className: "
|
|
11
|
+
const AnalysisBlock = ({ title, items, }) => (_jsxs("div", { className: "blog_yoast-link-section", children: [_jsxs("h4", { className: "blog_yoast-link-section-title", children: [title, " (", items.length, ")"] }), _jsx(CheckList, { items: items })] }));
|
|
12
12
|
export const YoastSeoAnalysisPanel = ({ checks, tone, hasKeyphrase, }) => {
|
|
13
13
|
const problems = checks.filter((c) => c.tone === 'bad');
|
|
14
14
|
const improvements = checks.filter((c) => c.tone === 'ok');
|
|
15
15
|
const good = checks.filter((c) => c.tone === 'good');
|
|
16
|
-
return (_jsxs("div", { className: "
|
|
16
|
+
return (_jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsx("p", { className: "blog_yoast-help", children: "Review SEO recommendations for your focus keyphrase, title, meta description, and content." }), !hasKeyphrase ? (_jsx("p", { className: "blog_yoast-result-empty", role: "status", children: "Please enter a focus keyphrase to see your SEO score." })) : (_jsxs("div", { className: "blog_yoast-analysis-results-head", children: [_jsx("h4", { className: "blog_yoast-link-section-title", children: "Overall score" }), _jsxs("span", { className: `blog_seo-pill blog_seo-pill-${tone}`, children: [_jsx(Dot, { tone: tone }), " ", toneLabel(tone)] })] })), _jsx(AnalysisBlock, { title: "Problems", tone: "bad", items: problems }), _jsx(AnalysisBlock, { title: "Improvements", tone: "ok", items: improvements }), _jsx(AnalysisBlock, { title: "Good results", tone: "good", items: good })] }));
|
|
17
17
|
};
|
|
18
18
|
export const YoastReadabilityPanel = ({ checks, tone, }) => {
|
|
19
19
|
const problems = checks.filter((c) => c.tone === 'bad');
|
|
20
20
|
const improvements = checks.filter((c) => c.tone === 'ok');
|
|
21
21
|
const good = checks.filter((c) => c.tone === 'good');
|
|
22
|
-
return (_jsxs("div", { className: "
|
|
22
|
+
return (_jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsx("p", { className: "blog_yoast-help", children: "Yoast SEO checks sentence length, passive voice, subheading distribution, and more." }), _jsxs("div", { className: "blog_yoast-analysis-results-head", children: [_jsx("h4", { className: "blog_yoast-link-section-title", children: "Overall score" }), _jsxs("span", { className: `blog_seo-pill blog_seo-pill-${tone}`, children: [_jsx(Dot, { tone: tone }), " ", toneLabel(tone)] })] }), _jsx(AnalysisBlock, { title: "Problems", tone: "bad", items: problems }), _jsx(AnalysisBlock, { title: "Improvements", tone: "ok", items: improvements }), _jsx(AnalysisBlock, { title: "Good results", tone: "good", items: good })] }));
|
|
23
23
|
};
|
|
@@ -19,11 +19,11 @@ const TABS = [
|
|
|
19
19
|
{ id: 'schema', label: 'Schema' },
|
|
20
20
|
{ id: 'social', label: 'Social' },
|
|
21
21
|
];
|
|
22
|
-
const Dot = ({ tone }) => (_jsx("span", { className: `
|
|
22
|
+
const Dot = ({ tone }) => (_jsx("span", { className: `blog_yoast-dot blog_yoast-dot-${tone}`, "aria-hidden": "true" }));
|
|
23
23
|
const CheckList = ({ title, items, count }) => {
|
|
24
24
|
if (!items.length)
|
|
25
25
|
return null;
|
|
26
|
-
return (_jsxs("div", { className: "
|
|
26
|
+
return (_jsxs("div", { className: "blog_seo-group", children: [title ? (_jsxs("p", { className: "blog_seo-group-title", children: [title, count ? _jsxs("span", { className: "blog_yoast-count", children: [" (", items.length, ")"] }) : null] })) : null, _jsx("ul", { className: "blog_seo-checks", children: items.map((c) => (_jsxs("li", { children: [_jsx(Dot, { tone: c.tone }), _jsxs("div", { children: [_jsx("strong", { children: c.label }), _jsx("span", { children: c.detail })] })] }, c.id))) })] }));
|
|
27
27
|
};
|
|
28
28
|
const highlightPhrase = (text, phrase) => {
|
|
29
29
|
if (!phrase.trim() || !text)
|
|
@@ -76,26 +76,26 @@ export const YoastSeoMetabox = ({ title, slug, excerpt, visibility, featuredImag
|
|
|
76
76
|
const previewHost = `${(siteName || 'example').toLowerCase().replace(/[^a-z0-9]+/g, '')}.com`;
|
|
77
77
|
const hasKeyphrase = Boolean(seo.focusKeyphrase.trim());
|
|
78
78
|
const seoTitleQuickVars = SEO_TITLE_QUICK;
|
|
79
|
-
return (_jsxs("div", { className: "
|
|
79
|
+
return (_jsxs("div", { className: "blog_box blog_yoast-box", id: "wpseo_meta", children: [_jsx("div", { className: "blog_box-head", children: _jsx("h3", { children: "Yoast SEO" }) }), _jsx("div", { className: "blog_yoast-tabs", role: "tablist", "aria-label": "Yoast SEO", children: TABS.map(({ id, label }) => (_jsxs("button", { type: "button", role: "tab", id: `yoast-tab-${id}`, "aria-selected": tab === id, "aria-controls": `yoast-panel-${id}`, className: `blog_yoast-tab${tab === id ? ' blog_is-active' : ''}`, onClick: () => setTab(id), children: [_jsx(Dot, { tone: tabTone[id] }), label] }, id))) }), _jsxs("div", { className: "blog_box-body blog_yoast-inside blog_wpseo-metabox-content", children: [tab === 'seo' ? (_jsxs("div", { className: "blog_yoast-panel blog_yoast-panel-seo", role: "tabpanel", id: "yoast-panel-seo", "aria-labelledby": "yoast-tab-seo", children: [_jsx("p", { className: "blog_yoast-intro", children: "Optimize your content for discovery." }), _jsxs("div", { className: "blog_yoast-accordion", children: [_jsx(YoastCollapsible, { title: "Focus keyphrase", defaultOpen: false, status: !hasKeyphrase ? _jsx("span", { className: "blog_yoast-status-bad", title: "Missing focus keyphrase", children: "!" }) : _jsx(Dot, { tone: seoTone }), children: _jsx("div", { className: "blog_yoast-accordion-panel", children: _jsxs("div", { className: "blog_yoast-field", children: [_jsx("input", { id: "yoast-focus-keyphrase", className: "blog_fld blog_yoast-input", value: seo.focusKeyphrase, "aria-label": "Focus keyphrase", onChange: (e) => onSeoChange('focusKeyphrase', e.target.value) }), _jsxs("p", { className: "blog_yoast-help", children: ["Use the main word or phrase you want your content found for across search, AI, and beyond.", ' ', _jsx("a", { className: "blog_yoast-learn-more", href: "https://yoast.com/focus-keyword/", target: "_blank", rel: "noreferrer", children: "Learn more about keyword research" })] }), _jsx("button", { type: "button", className: "blog_yoast-link-btn", disabled: true, title: "Requires Yoast SEO Premium", children: "Get related keyphrases" })] }) }) }), !hasKeyphrase ? (_jsx("p", { className: "blog_yoast-accordion-note", role: "status", children: "Please enter a focus keyphrase to see your SEO score." })) : null, _jsx(YoastCollapsible, { title: "Google preview", defaultOpen: false, children: _jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsxs("div", { className: "blog_yoast-preview-toolbar", children: [_jsx("span", { className: "blog_yoast-preview-label", children: "Preview as:" }), _jsxs("div", { className: "blog_yoast-preview-modes", role: "group", "aria-label": "Preview device", children: [_jsx("button", { type: "button", className: `blog_yoast-preview-mode${previewMode === 'mobile' ? ' blog_is-active' : ''}`, "aria-pressed": previewMode === 'mobile', onClick: () => setPreviewMode('mobile'), children: "Mobile result" }), _jsx("button", { type: "button", className: `blog_yoast-preview-mode${previewMode === 'desktop' ? ' blog_is-active' : ''}`, "aria-pressed": previewMode === 'desktop', onClick: () => setPreviewMode('desktop'), children: "Desktop result" })] })] }), _jsxs("div", { className: `blog_yoast-google-card blog_yoast-google-${previewMode}`, children: [_jsxs("div", { className: "blog_yoast-google-site", children: [_jsx("span", { className: "blog_yoast-google-favicon", "aria-hidden": "true", children: siteName.charAt(0).toUpperCase() }), _jsxs("div", { className: "blog_yoast-google-site-meta", children: [_jsx("div", { className: "blog_yoast-google-site-name", children: siteName }), _jsxs("div", { className: "blog_serp-url blog_mono", children: [previewHost, " \u203A blog \u203A ", slugDisplay] })] })] }), _jsx("div", { className: "blog_serp-title blog_yoast-google-title", children: highlightPhrase(seoTitle || title || 'Your post title', seo.focusKeyphrase) }), _jsx("div", { className: "blog_serp-desc blog_yoast-google-desc", children: highlightPhrase(metaDesc || 'Please provide a meta description by editing the snippet below.', seo.focusKeyphrase) })] }), _jsxs("div", { className: "blog_yoast-snippet-fields blog_stack", children: [_jsx(YoastSnippetField, { id: "yoast-seo-title", label: "SEO title", value: seo.metaTitle, placeholder: title || 'Falls back to the post title', maxLength: SEO_FIELD_LIMITS.metaTitle, expandedLength: seoTitle.length, meterGoodMin: 30, meterGoodMax: 60, meterMax: SEO_FIELD_LIMITS.metaTitle, variables: SEO_TITLE_VARIABLES, quickVariables: seoTitleQuickVars, generateLabel: "Generate SEO title", error: fieldErrors['seo.metaTitle'], onChange: (v) => {
|
|
80
80
|
onClearFieldError('seo.metaTitle');
|
|
81
81
|
onSeoChange('metaTitle', v);
|
|
82
|
-
}, onGenerate: () => onSeoChange('metaTitle', generateSeoTitleSnippet(titleTemplate)) }), _jsxs("div", { className: "
|
|
82
|
+
}, onGenerate: () => onSeoChange('metaTitle', generateSeoTitleSnippet(titleTemplate)) }), _jsxs("div", { className: "blog_yoast-field", children: [_jsx("label", { className: "blog_yoast-label", htmlFor: "yoast-slug", children: "Slug" }), _jsx("input", { id: "yoast-slug", className: "blog_fld blog_yoast-input blog_mono", value: slug, placeholder: slugify(title) || 'post-slug', onChange: (e) => onSlugChange(e.target.value), onBlur: onSlugBlur })] }), _jsx(YoastSnippetField, { id: "yoast-meta-description", label: "Meta description", value: seo.metaDescription, placeholder: "Falls back to the excerpt. Aim for 140\u2013160 characters.", multiline: true, maxLength: SEO_FIELD_LIMITS.metaDescription, expandedLength: metaDesc.length, meterGoodMin: 120, meterGoodMax: 156, meterMax: SEO_FIELD_LIMITS.metaDescription, variables: META_DESCRIPTION_VARIABLES, quickVariables: META_DESCRIPTION_VARIABLES.slice(0, 2), generateLabel: "Generate meta description", error: fieldErrors['seo.metaDescription'], onChange: (v) => {
|
|
83
83
|
onClearFieldError('seo.metaDescription');
|
|
84
84
|
onSeoChange('metaDescription', v);
|
|
85
|
-
}, onGenerate: () => onSeoChange('metaDescription', generateMetaDescriptionSnippet(snippetCtx)) })] })] }) }), _jsx(YoastCollapsible, { title: "SEO analysis", defaultOpen: false, status: _jsx(Dot, { tone: hasKeyphrase ? seoTone : 'bad' }), children: _jsx(YoastSeoAnalysisPanel, { checks: seoChecks, tone: seoTone, hasKeyphrase: hasKeyphrase }) }), _jsx(YoastCollapsible, { title: "Track SEO performance", defaultOpen: false, children: _jsxs("div", { className: "
|
|
85
|
+
}, onGenerate: () => onSeoChange('metaDescription', generateMetaDescriptionSnippet(snippetCtx)) })] })] }) }), _jsx(YoastCollapsible, { title: "SEO analysis", defaultOpen: false, status: _jsx(Dot, { tone: hasKeyphrase ? seoTone : 'bad' }), children: _jsx(YoastSeoAnalysisPanel, { checks: seoChecks, tone: seoTone, hasKeyphrase: hasKeyphrase }) }), _jsx(YoastCollapsible, { title: "Track SEO performance", defaultOpen: false, children: _jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsx("p", { className: "blog_yoast-help", children: "Track your rankings and see how your content performs in search." }), _jsxs("button", { type: "button", className: "blog_yoast-premium-inline-btn", disabled: true, children: [_jsx("span", { className: "blog_yoast-footer-badge", children: "Wincher" }), "Track SEO performance"] })] }) }), _jsx(YoastCollapsible, { title: "Cornerstone content", defaultOpen: false, children: _jsxs("div", { className: "blog_yoast-accordion-panel", children: [_jsxs("label", { className: "blog_yoast-toggle-row", children: [_jsx("input", { type: "checkbox", checked: cornerstone, onChange: (e) => setCornerstone(e.target.checked) }), _jsx("span", { children: "Mark as cornerstone content" })] }), _jsx("p", { className: "blog_yoast-help", children: "Cornerstone articles should be the most important on your site." })] }) }), _jsx(YoastCollapsible, { title: "Advanced", defaultOpen: false, children: _jsx("div", { className: "blog_yoast-accordion-panel", children: _jsxs("div", { className: "blog_stack", children: [_jsxs("label", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Allow search engines to show this Post in search results?" }), _jsxs("select", { className: "blog_fld", value: seo.noindex || visibility === 'private' ? 'no' : 'default', onChange: (e) => onSeoChange('noindex', e.target.value === 'no'), children: [_jsx("option", { value: "default", children: "Default for Posts (Yes)" }), _jsx("option", { value: "yes", children: "Yes" }), _jsx("option", { value: "no", children: "No" })] })] }), _jsxs("fieldset", { className: "blog_yoast-radio-fieldset", children: [_jsx("legend", { children: "Should search engines follow links on this Post?" }), _jsxs("label", { children: [_jsx("input", { type: "radio", name: "yoast-nofollow", checked: !seo.nofollow, onChange: () => onSeoChange('nofollow', false) }), "Yes"] }), _jsxs("label", { children: [_jsx("input", { type: "radio", name: "yoast-nofollow", checked: seo.nofollow, onChange: () => onSeoChange('nofollow', true) }), "No"] })] }), _jsxs("label", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Meta robots advanced" }), _jsxs("select", { className: "blog_fld", value: metaRobots, onChange: (e) => setMetaRobots(e.target.value), children: [_jsx("option", { value: "", children: "\u2014 None \u2014" }), _jsx("option", { value: "noimageindex", children: "No Image Index" }), _jsx("option", { value: "noarchive", children: "No Archive" }), _jsx("option", { value: "nosnippet", children: "No Snippet" })] })] }), _jsxs("label", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Breadcrumbs title" }), _jsx("input", { className: "blog_fld", value: seo.breadcrumbTitle, placeholder: title || 'Same as post title', onChange: (e) => onSeoChange('breadcrumbTitle', e.target.value) })] }), _jsxs("label", { className: "blog_fld-row", id: "seo-canonical", children: [_jsx("span", { className: "blog_fld-lbl", children: "Canonical URL" }), _jsx("input", { className: `blog_fld blog_mono${fieldErrors['seo.canonicalOverride'] ? ' blog_is-invalid' : ''}`, type: "url", inputMode: "url", autoComplete: "off", spellCheck: false, value: seo.canonicalOverride, placeholder: "https://brand.com/blog/post", onChange: (e) => {
|
|
86
86
|
onSeoChange('canonicalOverride', e.target.value);
|
|
87
87
|
onClearFieldError('seo.canonicalOverride');
|
|
88
88
|
}, onBlur: (e) => {
|
|
89
89
|
const check = validateCanonicalOverride(e.target.value);
|
|
90
90
|
if (check !== true)
|
|
91
91
|
onSetFieldError('seo.canonicalOverride', check);
|
|
92
|
-
} }), fieldErrors['seo.canonicalOverride'] ? (_jsx("span", { className: "
|
|
92
|
+
} }), fieldErrors['seo.canonicalOverride'] ? (_jsx("span", { className: "blog_fld-error", children: fieldErrors['seo.canonicalOverride'] })) : (_jsx("span", { className: "blog_fld-hint", children: CANONICAL_HINT }))] })] }) }) }), _jsx(YoastCollapsible, { title: "Insights", defaultOpen: false, children: _jsx(YoastInsightsPanel, { contentText: contentText }) }), _jsx(YoastCollapsible, { title: "Internal linking suggestions", defaultOpen: false, children: _jsx(YoastInternalLinksPanel, { contentHtml: contentHtml }) })] })] })) : null, tab === 'readability' ? (_jsxs("div", { className: "blog_yoast-panel", role: "tabpanel", id: "yoast-panel-readability", "aria-labelledby": "yoast-tab-readability", children: [_jsx("p", { className: "blog_yoast-intro", children: "Make your content easy to read. Yoast SEO checks sentence length, passive voice, and more." }), _jsx("div", { className: "blog_yoast-accordion", children: _jsx(YoastCollapsible, { title: "Readability analysis", status: _jsx(Dot, { tone: readTone }), defaultOpen: false, children: _jsx(YoastReadabilityPanel, { checks: readChecks, tone: readTone }) }) })] })) : null, tab === 'schema' ? (_jsxs("div", { className: "blog_yoast-panel", role: "tabpanel", id: "yoast-panel-schema", "aria-labelledby": "yoast-tab-schema", children: [_jsx("p", { className: "blog_yoast-intro", children: "Yoast SEO automatically describes your pages using schema.org. You can change the article type below." }), _jsxs("label", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Page type" }), _jsx("input", { className: "blog_fld", value: "Web Page", readOnly: true, disabled: true }), _jsx("span", { className: "blog_fld-hint", children: "Fixed for blog posts." })] }), _jsxs("label", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Article type" }), _jsxs("select", { className: "blog_fld", value: seo.schemaType, onChange: (e) => onSeoChange('schemaType', e.target.value), children: [_jsx("option", { value: "Article", children: "Article" }), _jsx("option", { value: "BlogPosting", children: "Blog posting" }), _jsx("option", { value: "NewsArticle", children: "News article" })] })] }), _jsxs("div", { className: "blog_yoast-schema-preview", children: [_jsx("p", { className: "blog_yoast-section-title", children: "Structured data preview" }), _jsxs("ul", { className: "blog_yoast-schema-list", children: [_jsxs("li", { children: [_jsx("strong", { children: seo.schemaType }), " \u2014 headline, dates, authors, publisher"] }), _jsxs("li", { children: [_jsx("strong", { children: "BreadcrumbList" }), " \u2014 Home \u203A Blog \u203A ", categoryName || 'category', " \u203A post"] }), _jsxs("li", { children: [_jsx("strong", { children: "Organization" }), " \u2014 ", siteName] })] })] })] })) : null, tab === 'social' ? (_jsxs("div", { className: "blog_yoast-panel", role: "tabpanel", id: "yoast-panel-social", "aria-labelledby": "yoast-tab-social", children: [_jsx("p", { className: "blog_yoast-intro", children: "Determine how your post should look on social media and in messaging apps." }), _jsxs("div", { className: "blog_yoast-social-preview", children: [socialImage ? (_jsx("img", { className: "blog_yoast-social-img", src: socialImage.url, alt: socialImage.alt || '' })) : (_jsx("div", { className: "blog_yoast-social-img blog_yoast-social-img-empty", children: "No image set" })), _jsxs("div", { className: "blog_yoast-social-text", children: [_jsx("div", { className: "blog_yoast-social-site", children: siteName.toUpperCase() }), _jsx("div", { className: "blog_yoast-social-title", children: socialTitle || 'Post title' }), _jsx("div", { className: "blog_yoast-social-desc", children: socialDesc || 'Description preview…' })] })] }), _jsxs("label", { className: "blog_fld-row", children: [_jsxs("span", { className: "blog_fld-lbl", children: ["Social title ", _jsxs("em", { children: [socialTitle.length, "/", SEO_FIELD_LIMITS.ogTitle] })] }), _jsx("input", { className: `blog_fld${fieldErrors['seo.ogTitle'] ? ' blog_is-invalid' : ''}`, maxLength: SEO_FIELD_LIMITS.ogTitle, value: seo.ogTitle, placeholder: seoTitle || title || 'Falls back to SEO title', onChange: (e) => {
|
|
93
93
|
onClearFieldError('seo.ogTitle');
|
|
94
94
|
onSeoChange('ogTitle', e.target.value);
|
|
95
|
-
} }), fieldErrors['seo.ogTitle'] ? _jsx("span", { className: "
|
|
95
|
+
} }), fieldErrors['seo.ogTitle'] ? _jsx("span", { className: "blog_fld-error", children: fieldErrors['seo.ogTitle'] }) : null] }), _jsxs("label", { className: "blog_fld-row", children: [_jsxs("span", { className: "blog_fld-lbl", children: ["Social description ", _jsxs("em", { children: [seo.ogDescription.length, "/", SEO_FIELD_LIMITS.ogDescription] })] }), _jsx("textarea", { className: `blog_fld${fieldErrors['seo.ogDescription'] ? ' blog_is-invalid' : ''}`, rows: 3, maxLength: SEO_FIELD_LIMITS.ogDescription, value: seo.ogDescription, placeholder: metaDesc || 'Falls back to meta description', onChange: (e) => {
|
|
96
96
|
onClearFieldError('seo.ogDescription');
|
|
97
97
|
onSeoChange('ogDescription', e.target.value);
|
|
98
|
-
} }), fieldErrors['seo.ogDescription'] ? _jsx("span", { className: "
|
|
98
|
+
} }), fieldErrors['seo.ogDescription'] ? _jsx("span", { className: "blog_fld-error", children: fieldErrors['seo.ogDescription'] }) : null] }), _jsxs("div", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Social image" }), seo.ogImage ? (_jsxs("div", { className: "blog_thumb-row", children: [_jsx("img", { className: "blog_thumb", src: seo.ogImage.url, alt: seo.ogImage.alt }), _jsxs("div", { className: "blog_btn-row", children: [_jsx("button", { type: "button", className: "blog_btn blog_btn-tiny", onClick: onPickOgImage, children: "Replace" }), _jsx("button", { type: "button", className: "blog_btn blog_btn-tiny", onClick: () => onSeoChange('ogImage', null), children: "Remove" })] })] })) : (_jsxs("div", { className: "blog_stack", children: [_jsx("button", { type: "button", className: "blog_btn blog_btn-tiny", onClick: onPickOgImage, children: "Choose image" }), _jsx("span", { className: "blog_fld-hint", children: featuredImage
|
|
99
99
|
? 'Falls back to the featured image when blank. 1200×630 recommended.'
|
|
100
100
|
: 'Set a featured image or choose a social image. 1200×630 recommended.' })] }))] })] })) : null] })] }));
|
|
101
101
|
};
|
|
@@ -4,7 +4,7 @@ import { useEffect, useId, useRef, useState } from 'react';
|
|
|
4
4
|
const LengthMeter = ({ length, goodMin, goodMax, max, }) => {
|
|
5
5
|
const pct = Math.min(100, Math.round((length / max) * 100));
|
|
6
6
|
const tone = length === 0 ? 'bad' : length < goodMin || length > goodMax ? 'ok' : 'good';
|
|
7
|
-
return (_jsx("div", { className: "
|
|
7
|
+
return (_jsx("div", { className: "blog_yoast-meter", "aria-hidden": "true", children: _jsx("div", { className: "blog_yoast-meter-track", children: _jsx("div", { className: `blog_yoast-meter-fill blog_yoast-meter-${tone}`, style: { width: `${pct}%` } }) }) }));
|
|
8
8
|
};
|
|
9
9
|
export const YoastSnippetField = ({ id, label, value, placeholder, multiline, maxLength, expandedLength, meterGoodMin, meterGoodMax, meterMax, variables, quickVariables = [], generateLabel, error, onChange, onGenerate, }) => {
|
|
10
10
|
const listId = useId();
|
|
@@ -47,5 +47,5 @@ export const YoastSnippetField = ({ id, label, value, placeholder, multiline, ma
|
|
|
47
47
|
maxLength,
|
|
48
48
|
onChange: (e) => onChange(e.target.value),
|
|
49
49
|
};
|
|
50
|
-
return (_jsxs("div", { className: "
|
|
50
|
+
return (_jsxs("div", { className: "blog_yoast-snippet-field", children: [_jsxs("div", { className: "blog_yoast-snippet-label-row", children: [_jsx("label", { className: "blog_yoast-label", htmlFor: id, children: label }), _jsxs("div", { className: "blog_yoast-snippet-actions blog_yoast-snippet-actions-top blog_btn-row", children: [_jsxs("div", { className: "blog_yoast-var-picker", ref: pickerRef, children: [_jsx("button", { type: "button", className: "blog_btn blog_btn-tiny", "aria-expanded": varsOpen, "aria-controls": listId, onClick: () => setVarsOpen((v) => !v), children: "Insert variable" }), varsOpen ? (_jsx("ul", { className: "blog_yoast-var-menu", id: listId, role: "listbox", children: variables.map((v) => (_jsx("li", { children: _jsxs("button", { type: "button", role: "option", className: "blog_yoast-var-option", onClick: () => insertToken(v.token), children: [_jsx("span", { className: "blog_yoast-var-option-label", children: v.label }), _jsx("span", { className: "blog_yoast-var-option-token blog_mono", children: v.token })] }) }, v.label))) })) : null] }), _jsx("button", { type: "button", className: "blog_btn blog_btn-tiny", onClick: onGenerate, children: generateLabel })] })] }), _jsxs("div", { className: "blog_yoast-composite-field", children: [quickVariables.length ? (_jsx("div", { className: "blog_yoast-var-chips blog_yoast-var-chips-inset", "aria-label": `${label} variables`, children: quickVariables.map((v) => (_jsx("button", { type: "button", className: "blog_yoast-var-chip blog_token", onClick: () => insertToken(v.token), children: v.label }, v.label))) })) : null, multiline ? _jsx("textarea", { ...fieldProps, ref: textareaRef, rows: 3 }) : _jsx("input", { ...fieldProps, ref: inputRef, type: "text" })] }), _jsxs("div", { className: "blog_yoast-field-foot", children: [_jsx(LengthMeter, { length: expandedLength, goodMin: meterGoodMin, goodMax: meterGoodMax, max: meterMax }), _jsxs("span", { className: "blog_yoast-char-count", children: [expandedLength, " / ", meterMax] })] }), error ? _jsx("span", { className: "blog_fld-error", children: error }) : null] }));
|
|
51
51
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
export function LoadingState({ label = "Loading..." }) {
|
|
3
|
-
return (_jsx("div", { className: "
|
|
3
|
+
return (_jsx("div", { className: "blog_bp-state blog_bp-state--loading", role: "status", children: label }));
|
|
4
4
|
}
|
|
5
5
|
export function ErrorState({ message, authError, }) {
|
|
6
|
-
return (_jsx("div", { className: "
|
|
6
|
+
return (_jsx("div", { className: "blog_bp-state blog_bp-state--error", role: "alert", children: authError
|
|
7
7
|
? "Authentication failed. Check the admin API key. Never use an admin key in a public website."
|
|
8
8
|
: message || "Something went wrong." }));
|
|
9
9
|
}
|
|
10
10
|
export function EmptyState({ label = "Nothing here yet." }) {
|
|
11
|
-
return _jsx("div", { className: "
|
|
11
|
+
return _jsx("div", { className: "blog_bp-state blog_bp-state--empty", children: label });
|
|
12
12
|
}
|
|
13
13
|
export function Field({ label, children, }) {
|
|
14
14
|
return (_jsxs("label", { style: { display: "grid", gap: "0.35rem", marginBottom: "0.85rem" }, children: [_jsx("span", { style: { fontSize: "0.85rem", color: "var(--bp-color-muted)" }, children: label }), children] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../app/components/admin/mock/store.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../app/components/admin/mock/store.tsx"],"names":[],"mappings":"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"}
|
|
@@ -42,6 +42,7 @@ const AdminMockContext = createContext(null);
|
|
|
42
42
|
const matchesPostFilter = (post, state) => {
|
|
43
43
|
switch (state) {
|
|
44
44
|
case "all":
|
|
45
|
+
// Every non-trashed post: drafts, in-review, scheduled, and published (not live-only).
|
|
45
46
|
return !post.trashed;
|
|
46
47
|
case "trash":
|
|
47
48
|
return post.trashed;
|
|
@@ -52,7 +53,7 @@ const matchesPostFilter = (post, state) => {
|
|
|
52
53
|
case "review":
|
|
53
54
|
return !post.trashed && post.status === "draft" && post.reviewState === "in-review";
|
|
54
55
|
case "scheduled":
|
|
55
|
-
return !post.trashed && !!post.scheduledFor && post.status
|
|
56
|
+
return !post.trashed && !!post.scheduledFor && post.status !== "published";
|
|
56
57
|
case "attention":
|
|
57
58
|
return (!post.trashed &&
|
|
58
59
|
post.status === "draft" &&
|
|
@@ -95,7 +96,7 @@ export function AdminMockProvider({ children, config, }) {
|
|
|
95
96
|
const [me, brandsPage, postsPage, catsPage, tagsPage, authorsPage, mediaPage, commentsPage] = await Promise.all([
|
|
96
97
|
api.me(),
|
|
97
98
|
api.listBrands({ pageSize: 100 }),
|
|
98
|
-
api.
|
|
99
|
+
api.listPostsAll({ pageSize: 100, includeTrash: true }),
|
|
99
100
|
api.listCategories({ pageSize: 100 }),
|
|
100
101
|
api.listTags({ pageSize: 100 }),
|
|
101
102
|
api.listAuthors({ pageSize: 100 }),
|
|
@@ -23,9 +23,9 @@ export function Ga4Settings({ brandId, canEdit = true }) {
|
|
|
23
23
|
setFlash("Google Analytics settings saved.");
|
|
24
24
|
});
|
|
25
25
|
};
|
|
26
|
-
return (_jsxs("fieldset", { className: "
|
|
26
|
+
return (_jsxs("fieldset", { className: "blog_seo-module", disabled: !canEdit, children: [!canEdit ? _jsxs("p", { className: "blog_explain", children: ["Only platform admins can change analytics for ", brandName, "."] }) : null, error ? (_jsx("p", { className: "blog_form-error", role: "alert", children: error })) : null, flash ? (_jsx("p", { className: "blog_form-ok", role: "status", children: flash })) : null, _jsx("div", { className: "blog_grid blog_grid-2 blog_seo-grid", children: _jsxs("section", { className: "blog_panel", children: [_jsx("div", { className: "blog_panel-head", children: _jsx("h2", { children: "GA4 measurement" }) }), _jsxs("div", { className: "blog_panel-body blog_stack", children: [_jsx(SeoStatus, { ok: connected, label: connected ? "Measurement ID ready" : "Not connected", detail: connected
|
|
27
27
|
? "ID is saved in the mock store for this session."
|
|
28
|
-
: "Paste a GA4 Measurement ID to start collecting traffic." }), _jsxs("label", { className: "
|
|
28
|
+
: "Paste a GA4 Measurement ID to start collecting traffic." }), _jsxs("label", { className: "blog_fld-row", children: [_jsx("span", { className: "blog_fld-lbl", children: "Measurement ID" }), _jsx("input", { className: "blog_fld blog_mono", placeholder: "G-XXXXXXXXXX", value: value, onChange: (e) => setValue(e.target.value) })] }), canEdit ? (_jsx("button", { type: "button", className: "blog_btn blog_btn-primary", disabled: pending, onClick: save, children: pending ? "Saving…" : "Save" })) : null] })] }) })] }));
|
|
29
29
|
}
|
|
30
30
|
export function SearchConsoleSettings({ brandId, canEdit = true }) {
|
|
31
31
|
const store = useAdminMock();
|
|
@@ -49,9 +49,9 @@ export function SearchConsoleSettings({ brandId, canEdit = true }) {
|
|
|
49
49
|
setFlash("Search Console verification saved.");
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
|
-
return (_jsxs("fieldset", { className: "
|
|
52
|
+
return (_jsxs("fieldset", { className: "blog_seo-module", disabled: !canEdit, children: [!canEdit ? _jsxs("p", { className: "blog_explain", children: ["Only platform admins can change verification for ", brandName, "."] }) : null, error ? (_jsx("p", { className: "blog_form-error", role: "alert", children: error })) : null, flash ? (_jsx("p", { className: "blog_form-ok", role: "status", children: flash })) : null, _jsx("div", { className: "blog_grid blog_grid-2 blog_seo-grid", children: _jsxs("section", { className: "blog_panel", children: [_jsx("div", { className: "blog_panel-head", children: _jsx("h2", { children: "HTML tag verification" }) }), _jsxs("div", { className: "blog_panel-body blog_stack", children: [_jsx(SeoStatus, { ok: connected, label: connected ? "Meta tag will publish" : "Not verified yet", detail: connected
|
|
53
53
|
? `Emitted as google-site-verification on ${primaryDomain}.`
|
|
54
|
-
: "Paste the content value from Search Console’s HTML tag method." }), _jsxs("label", { className: "
|
|
54
|
+
: "Paste the content value from Search Console’s HTML tag method." }), _jsxs("label", { className: "blog_fld-row", children: [_jsxs("span", { className: "blog_fld-lbl", children: ["Verification token ", _jsx("em", { children: "content=\u2026 only, not the full meta tag" })] }), _jsx("input", { className: "blog_fld blog_mono", value: value, onChange: (e) => setValue(e.target.value) })] }), canEdit ? (_jsx("button", { type: "button", className: "blog_btn blog_btn-primary", disabled: pending, onClick: save, children: pending ? "Saving…" : "Save" })) : null] })] }) })] }));
|
|
55
55
|
}
|
|
56
56
|
export function SeoBrandList({ rows, onOpen, canEdit = true, canClear, onClear, clearLabel = "Clear", }) {
|
|
57
57
|
const [pending, start] = useTransition();
|
|
@@ -66,14 +66,14 @@ export function SeoBrandList({ rows, onOpen, canEdit = true, canClear, onClear,
|
|
|
66
66
|
alert(res.error);
|
|
67
67
|
});
|
|
68
68
|
};
|
|
69
|
-
return (_jsxs("section", { className: "
|
|
69
|
+
return (_jsxs("section", { className: "blog_panel", children: [_jsxs("div", { className: "blog_panel-head", children: [_jsx("h2", { children: "All brands" }), _jsx("span", { className: "blog_hint", children: rows.length })] }), _jsx("div", { className: "blog_tw", children: _jsxs("table", { className: "blog_tbl", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Brand" }), _jsx("th", { children: "Status" }), _jsx("th", { children: "Summary" })] }) }), _jsx("tbody", { children: rows.map((row) => (_jsxs("tr", { children: [_jsxs("td", { children: [_jsx("button", { type: "button", className: "blog_row-title", onClick: () => onOpen(row.slug), children: row.name }), _jsx("span", { className: "blog_cell-sub blog_mono", children: row.primaryDomain }), _jsxs("div", { className: "blog_row-actions", children: [_jsx("button", { type: "button", onClick: () => onOpen(row.slug), children: "View" }), canEdit ? (_jsx("button", { type: "button", onClick: () => onOpen(row.slug), children: "Edit" })) : null, canClear && onClear && row.status !== "missing" && row.status !== "default" ? (_jsx("button", { type: "button", className: "blog_danger", disabled: pending, onClick: () => clear(row), children: clearLabel })) : null] })] }), _jsx("td", { children: _jsx("span", { className: `blog_chip ${row.status === "configured" ? "blog_chip-approved" : row.status === "default" ? "blog_chip-writing" : "blog_chip-draft"}`, children: row.statusLabel }) }), _jsx("td", { className: "blog_muted", children: row.summary })] }, row.id))) })] }) })] }));
|
|
70
70
|
}
|
|
71
71
|
export function SitemapPanel({ brandId }) {
|
|
72
72
|
const store = useAdminMock();
|
|
73
73
|
const brand = store.brands.find((b) => b.id === brandId);
|
|
74
74
|
const url = store.data.sitemapNotes[brandId] ?? `https://${brand?.primaryDomain ?? "example.com"}/sitemap.xml`;
|
|
75
75
|
const postCount = store.filterPosts({ state: "live", brandId }).length;
|
|
76
|
-
return (_jsxs("section", { className: "
|
|
76
|
+
return (_jsxs("section", { className: "blog_panel", children: [_jsxs("div", { className: "blog_panel-head", children: [_jsx("h2", { children: "XML Sitemap" }), _jsx("span", { className: "blog_hint", children: brand?.name })] }), _jsxs("div", { className: "blog_panel-body blog_stack", children: [_jsxs("p", { className: "blog_note", style: { marginTop: 0 }, children: ["Mock sitemap for ", brand?.name, ". ", postCount, " published posts would be included."] }), _jsx("p", { className: "blog_mono", children: url }), _jsx("button", { type: "button", className: "blog_btn", onClick: () => {
|
|
77
77
|
void navigator.clipboard?.writeText(url);
|
|
78
78
|
alert("Sitemap URL copied.");
|
|
79
79
|
}, children: "Copy URL" })] })] }));
|
|
@@ -20,5 +20,5 @@ const logTime = (iso) => {
|
|
|
20
20
|
};
|
|
21
21
|
export const RedirectAnalyticsDashboard = ({ data }) => {
|
|
22
22
|
const hasSeries = data.series.some((d) => d.views > 0);
|
|
23
|
-
return (_jsxs("div", { className: "
|
|
23
|
+
return (_jsxs("div", { className: "blog_redir-analytics", children: [_jsxs("section", { className: "blog_kpis", children: [_jsxs("div", { className: "blog_kpi", children: [_jsx("span", { className: "blog_kpi-l", children: "Total Redirects" }), _jsx("div", { className: "blog_kpi-row", children: _jsx("span", { className: "blog_kpi-n", children: nf.format(data.totalRules) }) }), _jsx("span", { className: "blog_kpi-sub", children: "Active rules in this scope" })] }), _jsxs("div", { className: "blog_kpi", children: [_jsx("span", { className: "blog_kpi-l", children: "Today" }), _jsx("div", { className: "blog_kpi-row", children: _jsx("span", { className: "blog_kpi-n", children: nf.format(data.hitsToday) }) }), _jsx("span", { className: "blog_kpi-sub", children: "Hits since midnight UTC" })] }), _jsxs("div", { className: "blog_kpi", children: [_jsx("span", { className: "blog_kpi-l", children: "This Week" }), _jsx("div", { className: "blog_kpi-row", children: _jsx("span", { className: "blog_kpi-n", children: nf.format(data.hitsWeek) }) }), _jsx("span", { className: "blog_kpi-sub", children: "Last 7 days" })] }), _jsxs("div", { className: "blog_kpi", children: [_jsx("span", { className: "blog_kpi-l", children: "This Month" }), _jsx("div", { className: "blog_kpi-row", children: _jsx("span", { className: "blog_kpi-n", children: nf.format(data.hitsMonth) }) }), _jsx("span", { className: "blog_kpi-sub", children: "Last 30 days" })] })] }), _jsxs("div", { className: "blog_redir-analytics-grid", children: [_jsxs("section", { className: "blog_panel", children: [_jsxs("div", { className: "blog_panel-head", children: [_jsx("h2", { children: "Top Redirects" }), _jsx("span", { className: "blog_hint", children: "30 days" })] }), _jsx("div", { className: "blog_panel-body", children: _jsx(BarList, { items: data.topRedirects, unit: " hits", colorVar: "var(--viz-1)" }) })] }), _jsxs("section", { className: "blog_panel", children: [_jsxs("div", { className: "blog_panel-head", children: [_jsx("h2", { children: "Broken URLs" }), _jsx("span", { className: "blog_hint", children: "404 / 410 / 451" })] }), _jsx("div", { className: "blog_panel-body", children: _jsx(BarList, { items: data.brokenUrls, unit: " hits", colorVar: "var(--viz-4)" }) })] })] }), _jsxs("section", { className: "blog_panel", children: [_jsxs("div", { className: "blog_panel-head", children: [_jsx("h2", { children: "Last 30 Days" }), _jsx("span", { className: "blog_hint", children: "Daily redirect hits" })] }), _jsx("div", { className: "blog_panel-body", children: hasSeries ? (_jsx(TrendArea, { data: data.series, height: 200 })) : (_jsx("p", { className: "blog_d-empty", style: { margin: 0 }, children: "No redirect traffic recorded yet." })) })] }), _jsxs("section", { className: "blog_panel", children: [_jsx("div", { className: "blog_panel-head", children: _jsx("h2", { children: "Recent hits" }) }), _jsx("div", { className: "blog_tw", children: _jsxs("table", { className: "blog_tbl", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "When" }), _jsx("th", { children: "From" }), _jsx("th", { children: "To" }), _jsx("th", { children: "Type" })] }) }), _jsx("tbody", { children: data.recentLogs.map((log) => (_jsxs("tr", { children: [_jsx("td", { className: "blog_mono blog_muted", children: logTime(log.at) }), _jsx("td", { className: "blog_mono", children: log.from }), _jsx("td", { className: "blog_mono blog_muted", children: log.to || "—" }), _jsx("td", { children: _jsx("span", { className: `blog_chip ${log.ok ? "blog_chip-approved" : "blog_chip-draft"}`, children: log.type }) })] }, log.id))) })] }) })] })] }));
|
|
24
24
|
};
|
|
@@ -7,7 +7,7 @@ export function RedirectDetail({ redirectId, onEdit, onBack, canEdit = true, })
|
|
|
7
7
|
const row = store.getRedirect(redirectId);
|
|
8
8
|
const [pending, start] = useTransition();
|
|
9
9
|
if (!row) {
|
|
10
|
-
return (_jsx("section", { className: "
|
|
10
|
+
return (_jsx("section", { className: "blog_panel", children: _jsxs("div", { className: "blog_panel-body", children: [_jsx("p", { className: "blog_d-empty", children: "Redirect not found." }), _jsx("button", { type: "button", className: "blog_btn", onClick: onBack, children: "Back to list" })] }) }));
|
|
11
11
|
}
|
|
12
12
|
const remove = () => {
|
|
13
13
|
if (!confirm(`Delete redirect “${row.from}”?`))
|
|
@@ -21,10 +21,10 @@ export function RedirectDetail({ redirectId, onEdit, onBack, canEdit = true, })
|
|
|
21
21
|
onBack();
|
|
22
22
|
});
|
|
23
23
|
};
|
|
24
|
-
return (_jsxs(_Fragment, { children: [_jsx(RedirectDetailCard, { row: row }), _jsxs("div", { className: "
|
|
24
|
+
return (_jsxs(_Fragment, { children: [_jsx(RedirectDetailCard, { row: row }), _jsxs("div", { className: "blog_btn-row", children: [canEdit ? (_jsx("button", { type: "button", className: "blog_btn blog_btn-primary", onClick: onEdit, children: "Edit" })) : null, canEdit ? (_jsx("button", { type: "button", className: "blog_btn blog_btn-ghost", disabled: pending, onClick: remove, children: pending ? "Deleting…" : "Delete" })) : null, _jsx("button", { type: "button", className: "blog_btn", onClick: onBack, children: "Back to list" })] })] }));
|
|
25
25
|
}
|
|
26
|
-
export const RedirectDetailCard = ({ row }) => (_jsxs("section", { className: "
|
|
27
|
-
? "
|
|
26
|
+
export const RedirectDetailCard = ({ row }) => (_jsxs("section", { className: "blog_panel", children: [_jsxs("div", { className: "blog_panel-head", children: [_jsx("h2", { children: "Redirect details" }), _jsx("span", { className: `blog_chip ${row.type === "301" || row.type === "308"
|
|
27
|
+
? "blog_chip-approved"
|
|
28
28
|
: row.type === "404" || row.type === "410" || row.type === "451"
|
|
29
|
-
? "
|
|
30
|
-
: "
|
|
29
|
+
? "blog_chip-draft"
|
|
30
|
+
: "blog_chip-writing"}`, children: row.type })] }), _jsx("div", { className: "blog_panel-body", children: _jsxs("dl", { className: "blog_seo-dl", children: [_jsxs("div", { children: [_jsx("dt", { children: "From" }), _jsx("dd", { className: "blog_mono", children: row.from })] }), _jsxs("div", { children: [_jsx("dt", { children: "Target URL" }), _jsx("dd", { className: "blog_mono", children: row.to || "—" })] }), _jsxs("div", { children: [_jsx("dt", { children: "Origin" }), _jsx("dd", { children: SOURCE_LABEL[row.source] ?? row.source })] }), _jsxs("div", { children: [_jsx("dt", { children: "Brand" }), _jsx("dd", { children: row.brandName ?? "—" })] }), _jsxs("div", { children: [_jsx("dt", { children: "Active" }), _jsx("dd", { children: row.active === false ? "No" : "Yes" })] }), row.note ? (_jsxs("div", { children: [_jsx("dt", { children: "Note" }), _jsx("dd", { children: row.note })] })) : null] }) })] }));
|