@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.
Files changed (61) hide show
  1. package/dist/blog-client.iife.js +1 -1
  2. package/dist/components/admin/AdminPostDetail.js +5 -5
  3. package/dist/components/admin/BrandSettings.js +5 -5
  4. package/dist/components/admin/BrandSwitcher.js +1 -1
  5. package/dist/components/admin/Chips.js +5 -5
  6. package/dist/components/admin/CommentsManager.js +6 -6
  7. package/dist/components/admin/Dashboard.js +1 -1
  8. package/dist/components/admin/MediaLibrary.js +5 -5
  9. package/dist/components/admin/MediaPicker.js +4 -4
  10. package/dist/components/admin/PostList.d.ts.map +1 -1
  11. package/dist/components/admin/PostList.js +13 -4
  12. package/dist/components/admin/PostsTable.d.ts +6 -1
  13. package/dist/components/admin/PostsTable.d.ts.map +1 -1
  14. package/dist/components/admin/PostsTable.js +15 -9
  15. package/dist/components/admin/Shell.js +3 -3
  16. package/dist/components/admin/TermManager.js +4 -4
  17. package/dist/components/admin/UsersManager.js +3 -3
  18. package/dist/components/admin/charts.js +7 -7
  19. package/dist/components/admin/editor/PostEditor.js +16 -16
  20. package/dist/components/admin/editor/RichTextEditor.js +8 -8
  21. package/dist/components/admin/editor/YoastCollapsible.js +2 -2
  22. package/dist/components/admin/editor/YoastInsightsPanel.js +1 -1
  23. package/dist/components/admin/editor/YoastInternalLinksPanel.js +1 -1
  24. package/dist/components/admin/editor/YoastSeoAnalysisPanel.js +6 -6
  25. package/dist/components/admin/editor/YoastSeoMetabox.js +8 -8
  26. package/dist/components/admin/editor/YoastSnippetField.js +2 -2
  27. package/dist/components/admin/internal/States.js +3 -3
  28. package/dist/components/admin/mock/store.d.ts.map +1 -1
  29. package/dist/components/admin/mock/store.js +3 -2
  30. package/dist/components/admin/seo/Ga4Settings.js +6 -6
  31. package/dist/components/admin/seo/RedirectAnalyticsDashboard.js +1 -1
  32. package/dist/components/admin/seo/RedirectDetail.js +6 -6
  33. package/dist/components/admin/seo/RedirectForm.js +1 -1
  34. package/dist/components/admin/seo/RedirectList.js +4 -4
  35. package/dist/components/admin/seo/RobotsEditor.js +1 -1
  36. package/dist/components/admin/seo/shared.js +2 -2
  37. package/dist/components/admin/tools/ToolsHub.js +4 -4
  38. package/dist/components/user/BlogCard.js +3 -3
  39. package/dist/components/user/BlogCategories.js +1 -1
  40. package/dist/components/user/BlogDetail.js +1 -1
  41. package/dist/components/user/BlogList.js +1 -1
  42. package/dist/components/user/BlogSearch.js +2 -2
  43. package/dist/components/user/BlogTags.js +1 -1
  44. package/dist/components/user/FeaturedBlogs.js +1 -1
  45. package/dist/components/user/RelatedBlogs.js +1 -1
  46. package/dist/components/user/SiteMediaHero.js +1 -1
  47. package/dist/components/user/detail/ArticleDetailHero.js +5 -5
  48. package/dist/components/user/detail/ArticleRailDetails.js +2 -2
  49. package/dist/components/user/detail/CommentSection.js +2 -2
  50. package/dist/components/user/detail/HeroFadeSlide.js +1 -1
  51. package/dist/components/user/detail/ReadingProgress.js +1 -1
  52. package/dist/components/user/detail/ShareRow.js +1 -1
  53. package/dist/components/user/internal/States.js +4 -4
  54. package/dist/lib/lexical-doc.js +1 -1
  55. package/dist/pages/admin/BlogAdmin.d.ts.map +1 -1
  56. package/dist/pages/admin/BlogAdmin.js +23 -11
  57. package/dist/services/admin-sdk-client.d.ts +9 -0
  58. package/dist/services/admin-sdk-client.d.ts.map +1 -1
  59. package/dist/services/admin-sdk-client.js +17 -0
  60. package/dist/style.css +1023 -1016
  61. 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: "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: "ed-link-selection", children: ["Linking: \u201C", linkSelection, "\u201D"] }) : null, _jsxs("div", { className: "ed-link-row", children: [_jsx("input", { className: "fld", placeholder: "Paste URL or type to search", value: linkUrl || linkQuery, onChange: (e) => {
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: "btn btn-primary btn-tiny", onMouseDown: (e) => e.preventDefault(), onClick: applyExternalLink, disabled: !linkUrl.trim(), children: "Apply" })] }), _jsxs("label", { className: "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: "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: "hit-label", children: hit.label }), _jsx("span", { className: "hit-path mono", children: hit.path })] }) }, `${hit.collection}-${hit.id}`))) })) : linkQuery.trim() ? (_jsx("p", { className: "ed-link-note", children: "No posts or categories match." })) : null, _jsxs("div", { className: "ed-link-actions", children: [marks.link ? (_jsx("button", { type: "button", className: "linkish", onMouseDown: (e) => e.preventDefault(), onClick: removeLink, children: "Remove link" })) : null, _jsx("button", { type: "button", className: "linkish", onClick: closeLinkDialog, children: "Cancel" })] })] })) : null;
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="ed-figure" contenteditable="false" data-media-id="${escapeAttr(picked.id)}">` +
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: `tb-btn${btnActive ? ' 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: `ed${active ? ' is-active' : ''}`, onFocusCapture: () => setActive(true), onBlurCapture: (e) => {
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: "ed-chrome", children: [_jsxs("div", { className: "ed-mode-tabs", role: "tablist", "aria-label": "Editor mode", children: [_jsx("button", { type: "button", role: "tab", className: mode === 'visual' ? 'is-on' : undefined, "aria-selected": mode === 'visual', onClick: () => switchMode('visual'), children: "Visual" }), _jsx("button", { type: "button", role: "tab", className: mode === 'code' ? 'is-on' : undefined, "aria-selected": mode === 'code', onClick: () => switchMode('code'), children: "Code" })] }), mode === 'visual' ? (_jsxs("div", { className: "ed-toolbar", role: "toolbar", "aria-label": "Formatting", children: [_jsx("button", { type: "button", className: "tb-btn tb-media", title: "Add Media", onMouseDown: (e) => e.preventDefault(), onClick: () => void insertImage(), children: "Add Media" }), _jsx("select", { className: "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: "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: "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: "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: "tb-sep" }), _jsx(Btn, { label: "\uD83D\uDD17", title: "Link (\u2318K)", onClick: () => {
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: "tb-sep" }), _jsx(Btn, { label: "\u25BE", title: "Toolbar toggle", active: moreTools, onClick: () => setMoreTools((v) => !v) }), _jsxs("span", { className: "tb-count", children: [words, " words"] }), moreTools ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "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: "tb-color", title: "Text colour", children: [_jsx("span", { "aria-hidden": "true", children: "A" }), _jsx("input", { type: "color", value: foreColor, onChange: (e) => {
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: "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: "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: "ed-code mono", value: codeHtml, onChange: (e) => setCodeHtml(e.target.value), "aria-label": "HTML source", spellCheck: false })) : !mounted ? (_jsx("div", { className: "ed-surface", ref: surfaceRef, children: _jsx("div", { className: "ed-input prose ed-skeleton", "aria-hidden": "true" }) })) : (_jsxs("div", { className: "ed-surface", ref: surfaceRef, children: [empty ? _jsx("div", { className: "ed-placeholder", children: "Tell the story\u2026" }) : null, _jsx("div", { ref: editorRef, className: "ed-input 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] }));
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: "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" }) }) }));
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: `yoast-collapse${className ? ` ${className}` : ''}`, open: defaultOpen, children: [_jsxs("summary", { className: "yoast-collapse-summary", children: [_jsx(AccChevron, {}), _jsx("span", { className: "yoast-collapse-title", children: title }), status ? _jsx("span", { className: "yoast-collapse-status", children: status }) : null] }), _jsx("div", { className: "yoast-collapse-body", children: children })] }));
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: "yoast-accordion-panel", children: [_jsx("p", { className: "yoast-help", children: "See word count and prominent terms used in your post content." }), _jsxs("div", { className: "yoast-link-section", children: [_jsx("h4", { className: "yoast-link-section-title", children: "Word count" }), _jsx("p", { className: "yoast-insight-value", children: wordCount })] }), _jsxs("div", { className: "yoast-link-section", children: [_jsx("h4", { className: "yoast-link-section-title", children: "Prominent words" }), prominent.length === 0 ? (_jsx("p", { className: "yoast-result-empty", children: "Add body content to see prominent words." })) : (_jsx("ul", { className: "yoast-link-list", children: prominent.map(([word, count]) => (_jsxs("li", { children: [_jsx("span", { className: "yoast-link-label", children: word }), _jsxs("span", { className: "yoast-link-href", children: [count, " occurrences"] })] }, word))) }))] })] }));
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: "yoast-accordion-panel", children: [_jsx("p", { className: "yoast-help", children: "Internal links help visitors and search engines navigate your site. Outbound links add context." }), _jsxs("div", { className: "yoast-link-section", children: [_jsx("h4", { className: "yoast-link-section-title", children: "Outgoing internal links" }), outgoing.length === 0 ? (_jsx("p", { className: "yoast-result-empty", children: "No internal links in this post yet." })) : (_jsx("ul", { className: "yoast-link-list", children: outgoing.map((l, i) => (_jsxs("li", { children: [_jsx("span", { className: "yoast-link-label", children: l.label }), _jsx("span", { className: "yoast-link-href mono", children: l.href })] }, `${l.href}-${i}`))) }))] }), _jsxs("div", { className: "yoast-link-section", children: [_jsx("h4", { className: "yoast-link-section-title", children: "Outgoing external links" }), external.length === 0 ? (_jsx("p", { className: "yoast-result-empty", children: "No external links in this post yet." })) : (_jsx("ul", { className: "yoast-link-list", children: external.map((l, i) => (_jsxs("li", { children: [_jsx("span", { className: "yoast-link-label", children: l.label }), _jsx("span", { className: "yoast-link-href mono", children: l.href })] }, `${l.href}-${i}`))) }))] })] }));
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: `yoast-dot yoast-dot-${tone}`, "aria-hidden": "true" }));
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: "yoast-result-empty", children: "No items in this group." });
7
+ return _jsx("p", { className: "blog_yoast-result-empty", children: "No items in this group." });
8
8
  }
9
- return (_jsx("ul", { className: "yoast-link-list", children: items.map((c) => (_jsxs("li", { children: [_jsxs("span", { className: "yoast-link-label", children: [_jsx(Dot, { tone: c.tone }), " ", c.label] }), _jsx("span", { className: "yoast-link-href", children: c.detail })] }, c.id))) }));
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: "yoast-link-section", children: [_jsxs("h4", { className: "yoast-link-section-title", children: [title, " (", items.length, ")"] }), _jsx(CheckList, { items: items })] }));
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: "yoast-accordion-panel", children: [_jsx("p", { className: "yoast-help", children: "Review SEO recommendations for your focus keyphrase, title, meta description, and content." }), !hasKeyphrase ? (_jsx("p", { className: "yoast-result-empty", role: "status", children: "Please enter a focus keyphrase to see your SEO score." })) : (_jsxs("div", { className: "yoast-analysis-results-head", children: [_jsx("h4", { className: "yoast-link-section-title", children: "Overall score" }), _jsxs("span", { className: `seo-pill 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 })] }));
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: "yoast-accordion-panel", children: [_jsx("p", { className: "yoast-help", children: "Yoast SEO checks sentence length, passive voice, subheading distribution, and more." }), _jsxs("div", { className: "yoast-analysis-results-head", children: [_jsx("h4", { className: "yoast-link-section-title", children: "Overall score" }), _jsxs("span", { className: `seo-pill 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 })] }));
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: `yoast-dot yoast-dot-${tone}`, "aria-hidden": "true" }));
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: "seo-group", children: [title ? (_jsxs("p", { className: "seo-group-title", children: [title, count ? _jsxs("span", { className: "yoast-count", children: [" (", items.length, ")"] }) : null] })) : null, _jsx("ul", { className: "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))) })] }));
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: "box yoast-box", id: "wpseo_meta", children: [_jsx("div", { className: "box-head", children: _jsx("h3", { children: "Yoast SEO" }) }), _jsx("div", { className: "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: `yoast-tab${tab === id ? ' is-active' : ''}`, onClick: () => setTab(id), children: [_jsx(Dot, { tone: tabTone[id] }), label] }, id))) }), _jsxs("div", { className: "box-body yoast-inside wpseo-metabox-content", children: [tab === 'seo' ? (_jsxs("div", { className: "yoast-panel yoast-panel-seo", role: "tabpanel", id: "yoast-panel-seo", "aria-labelledby": "yoast-tab-seo", children: [_jsx("p", { className: "yoast-intro", children: "Optimize your content for discovery." }), _jsxs("div", { className: "yoast-accordion", children: [_jsx(YoastCollapsible, { title: "Focus keyphrase", defaultOpen: false, status: !hasKeyphrase ? _jsx("span", { className: "yoast-status-bad", title: "Missing focus keyphrase", children: "!" }) : _jsx(Dot, { tone: seoTone }), children: _jsx("div", { className: "yoast-accordion-panel", children: _jsxs("div", { className: "yoast-field", children: [_jsx("input", { id: "yoast-focus-keyphrase", className: "fld yoast-input", value: seo.focusKeyphrase, "aria-label": "Focus keyphrase", onChange: (e) => onSeoChange('focusKeyphrase', e.target.value) }), _jsxs("p", { className: "yoast-help", children: ["Use the main word or phrase you want your content found for across search, AI, and beyond.", ' ', _jsx("a", { className: "yoast-learn-more", href: "https://yoast.com/focus-keyword/", target: "_blank", rel: "noreferrer", children: "Learn more about keyword research" })] }), _jsx("button", { type: "button", className: "yoast-link-btn", disabled: true, title: "Requires Yoast SEO Premium", children: "Get related keyphrases" })] }) }) }), !hasKeyphrase ? (_jsx("p", { className: "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: "yoast-accordion-panel", children: [_jsxs("div", { className: "yoast-preview-toolbar", children: [_jsx("span", { className: "yoast-preview-label", children: "Preview as:" }), _jsxs("div", { className: "yoast-preview-modes", role: "group", "aria-label": "Preview device", children: [_jsx("button", { type: "button", className: `yoast-preview-mode${previewMode === 'mobile' ? ' is-active' : ''}`, "aria-pressed": previewMode === 'mobile', onClick: () => setPreviewMode('mobile'), children: "Mobile result" }), _jsx("button", { type: "button", className: `yoast-preview-mode${previewMode === 'desktop' ? ' is-active' : ''}`, "aria-pressed": previewMode === 'desktop', onClick: () => setPreviewMode('desktop'), children: "Desktop result" })] })] }), _jsxs("div", { className: `yoast-google-card yoast-google-${previewMode}`, children: [_jsxs("div", { className: "yoast-google-site", children: [_jsx("span", { className: "yoast-google-favicon", "aria-hidden": "true", children: siteName.charAt(0).toUpperCase() }), _jsxs("div", { className: "yoast-google-site-meta", children: [_jsx("div", { className: "yoast-google-site-name", children: siteName }), _jsxs("div", { className: "serp-url mono", children: [previewHost, " \u203A blog \u203A ", slugDisplay] })] })] }), _jsx("div", { className: "serp-title yoast-google-title", children: highlightPhrase(seoTitle || title || 'Your post title', seo.focusKeyphrase) }), _jsx("div", { className: "serp-desc yoast-google-desc", children: highlightPhrase(metaDesc || 'Please provide a meta description by editing the snippet below.', seo.focusKeyphrase) })] }), _jsxs("div", { className: "yoast-snippet-fields 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) => {
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: "yoast-field", children: [_jsx("label", { className: "yoast-label", htmlFor: "yoast-slug", children: "Slug" }), _jsx("input", { id: "yoast-slug", className: "fld yoast-input 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) => {
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: "yoast-accordion-panel", children: [_jsx("p", { className: "yoast-help", children: "Track your rankings and see how your content performs in search." }), _jsxs("button", { type: "button", className: "yoast-premium-inline-btn", disabled: true, children: [_jsx("span", { className: "yoast-footer-badge", children: "Wincher" }), "Track SEO performance"] })] }) }), _jsx(YoastCollapsible, { title: "Cornerstone content", defaultOpen: false, children: _jsxs("div", { className: "yoast-accordion-panel", children: [_jsxs("label", { className: "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: "yoast-help", children: "Cornerstone articles should be the most important on your site." })] }) }), _jsx(YoastCollapsible, { title: "Advanced", defaultOpen: false, children: _jsx("div", { className: "yoast-accordion-panel", children: _jsxs("div", { className: "stack", children: [_jsxs("label", { className: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Allow search engines to show this Post in search results?" }), _jsxs("select", { className: "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: "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: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Meta robots advanced" }), _jsxs("select", { className: "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: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Breadcrumbs title" }), _jsx("input", { className: "fld", value: seo.breadcrumbTitle, placeholder: title || 'Same as post title', onChange: (e) => onSeoChange('breadcrumbTitle', e.target.value) })] }), _jsxs("label", { className: "fld-row", id: "seo-canonical", children: [_jsx("span", { className: "fld-lbl", children: "Canonical URL" }), _jsx("input", { className: `fld mono${fieldErrors['seo.canonicalOverride'] ? ' is-invalid' : ''}`, type: "url", inputMode: "url", autoComplete: "off", spellCheck: false, value: seo.canonicalOverride, placeholder: "https://brand.com/blog/post", onChange: (e) => {
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: "fld-error", children: fieldErrors['seo.canonicalOverride'] })) : (_jsx("span", { className: "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: "yoast-panel", role: "tabpanel", id: "yoast-panel-readability", "aria-labelledby": "yoast-tab-readability", children: [_jsx("p", { className: "yoast-intro", children: "Make your content easy to read. Yoast SEO checks sentence length, passive voice, and more." }), _jsx("div", { className: "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: "yoast-panel", role: "tabpanel", id: "yoast-panel-schema", "aria-labelledby": "yoast-tab-schema", children: [_jsx("p", { className: "yoast-intro", children: "Yoast SEO automatically describes your pages using schema.org. You can change the article type below." }), _jsxs("label", { className: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Page type" }), _jsx("input", { className: "fld", value: "Web Page", readOnly: true, disabled: true }), _jsx("span", { className: "fld-hint", children: "Fixed for blog posts." })] }), _jsxs("label", { className: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Article type" }), _jsxs("select", { className: "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: "yoast-schema-preview", children: [_jsx("p", { className: "yoast-section-title", children: "Structured data preview" }), _jsxs("ul", { className: "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: "yoast-panel", role: "tabpanel", id: "yoast-panel-social", "aria-labelledby": "yoast-tab-social", children: [_jsx("p", { className: "yoast-intro", children: "Determine how your post should look on social media and in messaging apps." }), _jsxs("div", { className: "yoast-social-preview", children: [socialImage ? (_jsx("img", { className: "yoast-social-img", src: socialImage.url, alt: socialImage.alt || '' })) : (_jsx("div", { className: "yoast-social-img yoast-social-img-empty", children: "No image set" })), _jsxs("div", { className: "yoast-social-text", children: [_jsx("div", { className: "yoast-social-site", children: siteName.toUpperCase() }), _jsx("div", { className: "yoast-social-title", children: socialTitle || 'Post title' }), _jsx("div", { className: "yoast-social-desc", children: socialDesc || 'Description preview…' })] })] }), _jsxs("label", { className: "fld-row", children: [_jsxs("span", { className: "fld-lbl", children: ["Social title ", _jsxs("em", { children: [socialTitle.length, "/", SEO_FIELD_LIMITS.ogTitle] })] }), _jsx("input", { className: `fld${fieldErrors['seo.ogTitle'] ? ' is-invalid' : ''}`, maxLength: SEO_FIELD_LIMITS.ogTitle, value: seo.ogTitle, placeholder: seoTitle || title || 'Falls back to SEO title', onChange: (e) => {
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: "fld-error", children: fieldErrors['seo.ogTitle'] }) : null] }), _jsxs("label", { className: "fld-row", children: [_jsxs("span", { className: "fld-lbl", children: ["Social description ", _jsxs("em", { children: [seo.ogDescription.length, "/", SEO_FIELD_LIMITS.ogDescription] })] }), _jsx("textarea", { className: `fld${fieldErrors['seo.ogDescription'] ? ' is-invalid' : ''}`, rows: 3, maxLength: SEO_FIELD_LIMITS.ogDescription, value: seo.ogDescription, placeholder: metaDesc || 'Falls back to meta description', onChange: (e) => {
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: "fld-error", children: fieldErrors['seo.ogDescription'] }) : null] }), _jsxs("div", { className: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Social image" }), seo.ogImage ? (_jsxs("div", { className: "thumb-row", children: [_jsx("img", { className: "thumb", src: seo.ogImage.url, alt: seo.ogImage.alt }), _jsxs("div", { className: "btn-row", children: [_jsx("button", { type: "button", className: "btn btn-tiny", onClick: onPickOgImage, children: "Replace" }), _jsx("button", { type: "button", className: "btn btn-tiny", onClick: () => onSeoChange('ogImage', null), children: "Remove" })] })] })) : (_jsxs("div", { className: "stack", children: [_jsx("button", { type: "button", className: "btn btn-tiny", onClick: onPickOgImage, children: "Choose image" }), _jsx("span", { className: "fld-hint", children: featuredImage
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: "yoast-meter", "aria-hidden": "true", children: _jsx("div", { className: "yoast-meter-track", children: _jsx("div", { className: `yoast-meter-fill yoast-meter-${tone}`, style: { width: `${pct}%` } }) }) }));
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: "yoast-snippet-field", children: [_jsxs("div", { className: "yoast-snippet-label-row", children: [_jsx("label", { className: "yoast-label", htmlFor: id, children: label }), _jsxs("div", { className: "yoast-snippet-actions yoast-snippet-actions-top btn-row", children: [_jsxs("div", { className: "yoast-var-picker", ref: pickerRef, children: [_jsx("button", { type: "button", className: "btn btn-tiny", "aria-expanded": varsOpen, "aria-controls": listId, onClick: () => setVarsOpen((v) => !v), children: "Insert variable" }), varsOpen ? (_jsx("ul", { className: "yoast-var-menu", id: listId, role: "listbox", children: variables.map((v) => (_jsx("li", { children: _jsxs("button", { type: "button", role: "option", className: "yoast-var-option", onClick: () => insertToken(v.token), children: [_jsx("span", { className: "yoast-var-option-label", children: v.label }), _jsx("span", { className: "yoast-var-option-token mono", children: v.token })] }) }, v.label))) })) : null] }), _jsx("button", { type: "button", className: "btn btn-tiny", onClick: onGenerate, children: generateLabel })] })] }), _jsxs("div", { className: "yoast-composite-field", children: [quickVariables.length ? (_jsx("div", { className: "yoast-var-chips yoast-var-chips-inset", "aria-label": `${label} variables`, children: quickVariables.map((v) => (_jsx("button", { type: "button", className: "yoast-var-chip 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: "yoast-field-foot", children: [_jsx(LengthMeter, { length: expandedLength, goodMin: meterGoodMin, goodMax: meterGoodMax, max: meterMax }), _jsxs("span", { className: "yoast-char-count", children: [expandedLength, " / ", meterMax] })] }), error ? _jsx("span", { className: "fld-error", children: error }) : null] }));
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: "bp-state bp-state--loading", role: "status", children: label }));
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: "bp-state bp-state--error", role: "alert", children: authError
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: "bp-state bp-state--empty", children: label });
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 === "draft";
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.listPosts({ pageSize: 100, includeTrash: true }),
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: "seo-module", disabled: !canEdit, children: [!canEdit ? _jsxs("p", { className: "explain", children: ["Only platform admins can change analytics for ", brandName, "."] }) : null, error ? (_jsx("p", { className: "form-error", role: "alert", children: error })) : null, flash ? (_jsx("p", { className: "form-ok", role: "status", children: flash })) : null, _jsx("div", { className: "grid grid-2 seo-grid", children: _jsxs("section", { className: "panel", children: [_jsx("div", { className: "panel-head", children: _jsx("h2", { children: "GA4 measurement" }) }), _jsxs("div", { className: "panel-body stack", children: [_jsx(SeoStatus, { ok: connected, label: connected ? "Measurement ID ready" : "Not connected", detail: connected
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: "fld-row", children: [_jsx("span", { className: "fld-lbl", children: "Measurement ID" }), _jsx("input", { className: "fld mono", placeholder: "G-XXXXXXXXXX", value: value, onChange: (e) => setValue(e.target.value) })] }), canEdit ? (_jsx("button", { type: "button", className: "btn btn-primary", disabled: pending, onClick: save, children: pending ? "Saving…" : "Save" })) : null] })] }) })] }));
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: "seo-module", disabled: !canEdit, children: [!canEdit ? _jsxs("p", { className: "explain", children: ["Only platform admins can change verification for ", brandName, "."] }) : null, error ? (_jsx("p", { className: "form-error", role: "alert", children: error })) : null, flash ? (_jsx("p", { className: "form-ok", role: "status", children: flash })) : null, _jsx("div", { className: "grid grid-2 seo-grid", children: _jsxs("section", { className: "panel", children: [_jsx("div", { className: "panel-head", children: _jsx("h2", { children: "HTML tag verification" }) }), _jsxs("div", { className: "panel-body stack", children: [_jsx(SeoStatus, { ok: connected, label: connected ? "Meta tag will publish" : "Not verified yet", detail: connected
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: "fld-row", children: [_jsxs("span", { className: "fld-lbl", children: ["Verification token ", _jsx("em", { children: "content=\u2026 only, not the full meta tag" })] }), _jsx("input", { className: "fld mono", value: value, onChange: (e) => setValue(e.target.value) })] }), canEdit ? (_jsx("button", { type: "button", className: "btn btn-primary", disabled: pending, onClick: save, children: pending ? "Saving…" : "Save" })) : null] })] }) })] }));
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: "panel", children: [_jsxs("div", { className: "panel-head", children: [_jsx("h2", { children: "All brands" }), _jsx("span", { className: "hint", children: rows.length })] }), _jsx("div", { className: "tw", children: _jsxs("table", { className: "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: "row-title", onClick: () => onOpen(row.slug), children: row.name }), _jsx("span", { className: "cell-sub mono", children: row.primaryDomain }), _jsxs("div", { className: "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: "danger", disabled: pending, onClick: () => clear(row), children: clearLabel })) : null] })] }), _jsx("td", { children: _jsx("span", { className: `chip ${row.status === "configured" ? "chip-approved" : row.status === "default" ? "chip-writing" : "chip-draft"}`, children: row.statusLabel }) }), _jsx("td", { className: "muted", children: row.summary })] }, row.id))) })] }) })] }));
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: "panel", children: [_jsxs("div", { className: "panel-head", children: [_jsx("h2", { children: "XML Sitemap" }), _jsx("span", { className: "hint", children: brand?.name })] }), _jsxs("div", { className: "panel-body stack", children: [_jsxs("p", { className: "note", style: { marginTop: 0 }, children: ["Mock sitemap for ", brand?.name, ". ", postCount, " published posts would be included."] }), _jsx("p", { className: "mono", children: url }), _jsx("button", { type: "button", className: "btn", onClick: () => {
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: "redir-analytics", children: [_jsxs("section", { className: "kpis", children: [_jsxs("div", { className: "kpi", children: [_jsx("span", { className: "kpi-l", children: "Total Redirects" }), _jsx("div", { className: "kpi-row", children: _jsx("span", { className: "kpi-n", children: nf.format(data.totalRules) }) }), _jsx("span", { className: "kpi-sub", children: "Active rules in this scope" })] }), _jsxs("div", { className: "kpi", children: [_jsx("span", { className: "kpi-l", children: "Today" }), _jsx("div", { className: "kpi-row", children: _jsx("span", { className: "kpi-n", children: nf.format(data.hitsToday) }) }), _jsx("span", { className: "kpi-sub", children: "Hits since midnight UTC" })] }), _jsxs("div", { className: "kpi", children: [_jsx("span", { className: "kpi-l", children: "This Week" }), _jsx("div", { className: "kpi-row", children: _jsx("span", { className: "kpi-n", children: nf.format(data.hitsWeek) }) }), _jsx("span", { className: "kpi-sub", children: "Last 7 days" })] }), _jsxs("div", { className: "kpi", children: [_jsx("span", { className: "kpi-l", children: "This Month" }), _jsx("div", { className: "kpi-row", children: _jsx("span", { className: "kpi-n", children: nf.format(data.hitsMonth) }) }), _jsx("span", { className: "kpi-sub", children: "Last 30 days" })] })] }), _jsxs("div", { className: "redir-analytics-grid", children: [_jsxs("section", { className: "panel", children: [_jsxs("div", { className: "panel-head", children: [_jsx("h2", { children: "Top Redirects" }), _jsx("span", { className: "hint", children: "30 days" })] }), _jsx("div", { className: "panel-body", children: _jsx(BarList, { items: data.topRedirects, unit: " hits", colorVar: "var(--viz-1)" }) })] }), _jsxs("section", { className: "panel", children: [_jsxs("div", { className: "panel-head", children: [_jsx("h2", { children: "Broken URLs" }), _jsx("span", { className: "hint", children: "404 / 410 / 451" })] }), _jsx("div", { className: "panel-body", children: _jsx(BarList, { items: data.brokenUrls, unit: " hits", colorVar: "var(--viz-4)" }) })] })] }), _jsxs("section", { className: "panel", children: [_jsxs("div", { className: "panel-head", children: [_jsx("h2", { children: "Last 30 Days" }), _jsx("span", { className: "hint", children: "Daily redirect hits" })] }), _jsx("div", { className: "panel-body", children: hasSeries ? (_jsx(TrendArea, { data: data.series, height: 200 })) : (_jsx("p", { className: "d-empty", style: { margin: 0 }, children: "No redirect traffic recorded yet." })) })] }), _jsxs("section", { className: "panel", children: [_jsx("div", { className: "panel-head", children: _jsx("h2", { children: "Recent hits" }) }), _jsx("div", { className: "tw", children: _jsxs("table", { className: "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: "mono muted", children: logTime(log.at) }), _jsx("td", { className: "mono", children: log.from }), _jsx("td", { className: "mono muted", children: log.to || "—" }), _jsx("td", { children: _jsx("span", { className: `chip ${log.ok ? "chip-approved" : "chip-draft"}`, children: log.type }) })] }, log.id))) })] }) })] })] }));
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: "panel", children: _jsxs("div", { className: "panel-body", children: [_jsx("p", { className: "d-empty", children: "Redirect not found." }), _jsx("button", { type: "button", className: "btn", onClick: onBack, children: "Back to list" })] }) }));
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: "btn-row", children: [canEdit ? (_jsx("button", { type: "button", className: "btn btn-primary", onClick: onEdit, children: "Edit" })) : null, canEdit ? (_jsx("button", { type: "button", className: "btn btn-ghost", disabled: pending, onClick: remove, children: pending ? "Deleting…" : "Delete" })) : null, _jsx("button", { type: "button", className: "btn", onClick: onBack, children: "Back to list" })] })] }));
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: "panel", children: [_jsxs("div", { className: "panel-head", children: [_jsx("h2", { children: "Redirect details" }), _jsx("span", { className: `chip ${row.type === "301" || row.type === "308"
27
- ? "chip-approved"
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
- ? "chip-draft"
30
- : "chip-writing"}`, children: row.type })] }), _jsx("div", { className: "panel-body", children: _jsxs("dl", { className: "seo-dl", children: [_jsxs("div", { children: [_jsx("dt", { children: "From" }), _jsx("dd", { className: "mono", children: row.from })] }), _jsxs("div", { children: [_jsx("dt", { children: "Target URL" }), _jsx("dd", { className: "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] }) })] }));
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] }) })] }));