diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 084f112cf2..29b2f82abe 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,6 @@ version: 2 updates: - package-ecosystem: 'npm' - reviewers: - - 'Parsely/wp-parsely' directory: '/' schedule: interval: 'daily' @@ -12,8 +10,6 @@ updates: - 'Deps: JavaScript' - package-ecosystem: 'composer' - reviewers: - - 'Parsely/wp-parsely' directory: '/' schedule: interval: 'daily' @@ -22,8 +18,6 @@ updates: - 'Deps: PHP' - package-ecosystem: 'github-actions' - reviewers: - - 'Parsely/wp-parsely' directory: '/' schedule: interval: 'daily' diff --git a/.husky/pre-commit b/.husky/pre-commit index 25a129c695..d5920c8a29 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ php lint.php npm run lint composer cs -vendor/bin/phpstan analyse --memory-limit=1G +vendor/bin/phpstan analyse --memory-limit=2G diff --git a/.wordpress-org/screenshot-10.png b/.wordpress-org/screenshot-10.png new file mode 100644 index 0000000000..5188a06293 Binary files /dev/null and b/.wordpress-org/screenshot-10.png differ diff --git a/.wordpress-org/screenshot-3.png b/.wordpress-org/screenshot-3.png index 33b0823931..37566882a1 100644 Binary files a/.wordpress-org/screenshot-3.png and b/.wordpress-org/screenshot-3.png differ diff --git a/.wordpress-org/screenshot-4.png b/.wordpress-org/screenshot-4.png index 47df9bd647..33b0823931 100644 Binary files a/.wordpress-org/screenshot-4.png and b/.wordpress-org/screenshot-4.png differ diff --git a/.wordpress-org/screenshot-5.png b/.wordpress-org/screenshot-5.png index dc22029ad5..47df9bd647 100644 Binary files a/.wordpress-org/screenshot-5.png and b/.wordpress-org/screenshot-5.png differ diff --git a/.wordpress-org/screenshot-6.png b/.wordpress-org/screenshot-6.png index 03f6845908..dc22029ad5 100644 Binary files a/.wordpress-org/screenshot-6.png and b/.wordpress-org/screenshot-6.png differ diff --git a/.wordpress-org/screenshot-7.png b/.wordpress-org/screenshot-7.png index a0084417a9..03f6845908 100644 Binary files a/.wordpress-org/screenshot-7.png and b/.wordpress-org/screenshot-7.png differ diff --git a/.wordpress-org/screenshot-8.png b/.wordpress-org/screenshot-8.png index 64773b69e7..a0084417a9 100644 Binary files a/.wordpress-org/screenshot-8.png and b/.wordpress-org/screenshot-8.png differ diff --git a/.wordpress-org/screenshot-9.png b/.wordpress-org/screenshot-9.png index 5188a06293..64773b69e7 100644 Binary files a/.wordpress-org/screenshot-9.png and b/.wordpress-org/screenshot-9.png differ diff --git a/CHANGELOG.md b/CHANGELOG.md index d593cb879a..7364bfbe00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.19.0](https://github.com/Parsely/wp-parsely/compare/3.18.1...3.19.0) - 2025-05-20 + +### Added + +- Implement Traffic Boost feature ([#3344](https://github.com/Parsely/wp-parsely/pull/3344)) +- Settings page: Add Content Helper messages ([#3341](https://github.com/Parsely/wp-parsely/pull/3341)) + +### Dependency Updates + +- The list of all dependency updates for this release is available [here](https://github.com/Parsely/wp-parsely/pulls?q=is%3Apr+is%3Amerged+milestone%3A3.19.0+label%3ADeps). + ## [3.18.1](https://github.com/Parsely/wp-parsely/compare/3.18.0...3.18.1) - 2025-04-23 ### Dependency Updates diff --git a/README.md b/README.md index 9f383bc321..c9a30e5c9b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Parse.ly -Stable tag: 3.18.1 -Requires at least: 5.2 +Stable tag: 3.19.0 +Requires at least: 6.0 Tested up to: 6.8 Requires PHP: 7.2 License: GPLv2 or later @@ -39,6 +39,7 @@ The plugin automatically inserts the Parse.ly metadata and JavaScript in all pub The [Content Helper](https://docs.parse.ly/plugin-content-helper/) is a set of content insight tools including: - The [Parse.ly Dashboard Widget](https://docs.parse.ly/plugin-content-helper/#h-dashboard) - Displays the site's top posts in the WordPress Dashboard. - The [Parse.ly Stats Column](https://docs.parse.ly/plugin-content-helper/#h-posts) - Displays published post performance for the last 7 days in Post Lists. +- The [Traffic Boost](https://docs.wpvip.com/parse-ly/wp-parsely-features/traffic-boost/) feature - Helps you increase page views and engagement by strategically placing links to key content within high-performing articles on your site. - The [Parse.ly Editor Sidebar](https://docs.parse.ly/plugin-content-helper/#h-editor) - This sidebar is integrated into the WordPress Editor and offers insights about the content currently being edited such as: - [Title Suggestions](https://docs.wpvip.com/parse-ly/wp-parsely-features/title-suggestions/) - Generates title suggestions for the post/page currently being edited. - [Excerpt Suggestions](https://docs.wpvip.com/parse-ly/wp-parsely-features/excerpt-suggestions/) - Generates an excerpt suggestion for the post/page currently being edited. @@ -116,17 +117,19 @@ Please visit the [changelog](https://github.com/parsely/wp-parsely/blob/trunk/CH ![Parse.ly Dashboard Widget](.wordpress-org/screenshot-1.png) 2. The Parse.ly Stats Column (on the right), showing information about content that is being tracked as Posts. ![Parse.ly List Column](.wordpress-org/screenshot-2.png) -3. The Parse.ly Editor Sidebar, featuring the Title Suggestions panel. - ![Parse.ly Editor Sidebar - Title Suggestions](.wordpress-org/screenshot-3.png) -4. The Parse.ly Editor Sidebar, featuring the Smart Linking panel. - ![Parse.ly Editor Sidebar - Smart Linking](.wordpress-org/screenshot-4.png) -5. The Parse.ly Editor Sidebar, featuring the Related Posts panel. - ![Parse.ly Editor Sidebar - Related Posts](.wordpress-org/screenshot-5.png) -6. The Parse.ly Editor Sidebar, featuring the Performance Stats panel. - ![Parse.ly Editor Sidebar - Performance Stats](.wordpress-org/screenshot-6.png) -7. The Parse.ly Excerpt Suggestions in the Post Editor's settings. Also available in the Parse.ly Editor Sidebar. - ![Parse.ly Excerpt Suggestions](.wordpress-org/screenshot-7.png) -8. The Recommendations Block, showcasing links to related content on your site. - ![Parse.ly Recommendations Block](.wordpress-org/screenshot-8.png) -9. A view of the Parse.ly Dashboard Overview. Parse.ly offers analytics that empower you to better understand how your content is performing. - ![Parse.ly Dashboard Overview](.wordpress-org/screenshot-9.png) +3. The Parse.ly Traffic Boost feature. + ![Parse.ly Traffic Boost](.wordpress-org/screenshot-3.png) +4. The Parse.ly Editor Sidebar, featuring the Title Suggestions panel. + ![Parse.ly Editor Sidebar - Title Suggestions](.wordpress-org/screenshot-4.png) +5. The Parse.ly Editor Sidebar, featuring the Smart Linking panel. + ![Parse.ly Editor Sidebar - Smart Linking](.wordpress-org/screenshot-5.png) +6. The Parse.ly Editor Sidebar, featuring the Related Posts panel. + ![Parse.ly Editor Sidebar - Related Posts](.wordpress-org/screenshot-6.png) +7. The Parse.ly Editor Sidebar, featuring the Performance Stats panel. + ![Parse.ly Editor Sidebar - Performance Stats](.wordpress-org/screenshot-7.png) +8. The Parse.ly Excerpt Suggestions in the Post Editor's settings. Also available in the Parse.ly Editor Sidebar. + ![Parse.ly Excerpt Suggestions](.wordpress-org/screenshot-8.png) +9. The Recommendations Block, showcasing links to related content on your site. + ![Parse.ly Recommendations Block](.wordpress-org/screenshot-9.png) +10. A view of the Parse.ly Dashboard Overview. Parse.ly offers analytics that empower you to better understand how your content is performing. + ![Parse.ly Dashboard Overview](.wordpress-org/screenshot-10.png) diff --git a/build/admin-settings-rtl.css b/build/admin-settings-rtl.css index 8ecde47685..6945eb2b11 100644 --- a/build/admin-settings-rtl.css +++ b/build/admin-settings-rtl.css @@ -1 +1 @@ -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-350:#e1e3e5;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.settings_page_parsely{--padding-default:15px}.settings_page_parsely fieldset.user-role-permissions label{margin-left:1rem!important}.settings_page_parsely .disabled-before-posting label:not(.prevent-disable),.settings_page_parsely .disabled-before-posting p,.settings_page_parsely .disabled-before-posting th,.settings_page_parsely fieldset:disabled label:not(.prevent-disable),.settings_page_parsely fieldset:disabled p,.settings_page_parsely fieldset:disabled th,.settings_page_parsely tr:has(fieldset:disabled) label:not(.prevent-disable),.settings_page_parsely tr:has(fieldset:disabled) p,.settings_page_parsely tr:has(fieldset:disabled) th{color:var(--gray-500);cursor:default}.settings_page_parsely #track-post-types{max-width:550px;width:100%}.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.settings_page_parsely #track-post-types td{padding:0}.settings_page_parsely #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.settings_page_parsely #track-post-types thead th:nth-child(3){word-break:break-word}.settings_page_parsely .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.settings_page_parsely a.managed-option-badge{cursor:pointer!important}.settings_page_parsely a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{padding-right:10px;padding-left:10px}.settings_page_parsely #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parse-ly_page_parsely-settings{--padding-default:15px}.parse-ly_page_parsely-settings fieldset.user-role-permissions label{margin-left:1rem!important}.parse-ly_page_parsely-settings .content-helper-message{margin-top:1.5rem}.parse-ly_page_parsely-settings .content-helper-message p{padding:.5rem}.parse-ly_page_parsely-settings .disabled-before-posting label:not(.prevent-disable),.parse-ly_page_parsely-settings .disabled-before-posting p,.parse-ly_page_parsely-settings .disabled-before-posting th,.parse-ly_page_parsely-settings fieldset:disabled label:not(.prevent-disable),.parse-ly_page_parsely-settings fieldset:disabled p,.parse-ly_page_parsely-settings fieldset:disabled th,.parse-ly_page_parsely-settings tr:has(fieldset:disabled) label:not(.prevent-disable),.parse-ly_page_parsely-settings tr:has(fieldset:disabled) p,.parse-ly_page_parsely-settings tr:has(fieldset:disabled) th{color:var(--gray-500);cursor:default}.parse-ly_page_parsely-settings #track-post-types{max-width:550px;width:100%}.parse-ly_page_parsely-settings #track-post-types td,.parse-ly_page_parsely-settings #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.parse-ly_page_parsely-settings #track-post-types td{padding:0}.parse-ly_page_parsely-settings #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.parse-ly_page_parsely-settings #track-post-types thead th:nth-child(3){word-break:break-word}.parse-ly_page_parsely-settings .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.parse-ly_page_parsely-settings a.managed-option-badge{cursor:pointer!important}.parse-ly_page_parsely-settings a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.parse-ly_page_parsely-settings #track-post-types td,.parse-ly_page_parsely-settings #track-post-types th{padding-right:10px;padding-left:10px}.parse-ly_page_parsely-settings #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} diff --git a/build/admin-settings.asset.php b/build/admin-settings.asset.php index b43a738425..4ee8433554 100644 --- a/build/admin-settings.asset.php +++ b/build/admin-settings.asset.php @@ -1 +1 @@ - array(), 'version' => '7ead7aa6d2ed1321b20c'); + array('react', 'wp-api-fetch', 'wp-data', 'wp-escape-html', 'wp-i18n', 'wp-url'), 'version' => '094ef7b234cad83c0a56'); diff --git a/build/admin-settings.css b/build/admin-settings.css index 4d0c44ca9e..77a2b2041b 100644 --- a/build/admin-settings.css +++ b/build/admin-settings.css @@ -1 +1 @@ -#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-350:#e1e3e5;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--black:#000;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0}.settings_page_parsely{--padding-default:15px}.settings_page_parsely fieldset.user-role-permissions label{margin-right:1rem!important}.settings_page_parsely .disabled-before-posting label:not(.prevent-disable),.settings_page_parsely .disabled-before-posting p,.settings_page_parsely .disabled-before-posting th,.settings_page_parsely fieldset:disabled label:not(.prevent-disable),.settings_page_parsely fieldset:disabled p,.settings_page_parsely fieldset:disabled th,.settings_page_parsely tr:has(fieldset:disabled) label:not(.prevent-disable),.settings_page_parsely tr:has(fieldset:disabled) p,.settings_page_parsely tr:has(fieldset:disabled) th{color:var(--gray-500);cursor:default}.settings_page_parsely #track-post-types{max-width:550px;width:100%}.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.settings_page_parsely #track-post-types td{padding:0}.settings_page_parsely #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.settings_page_parsely #track-post-types thead th:nth-child(3){word-break:break-word}.settings_page_parsely .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.settings_page_parsely a.managed-option-badge{cursor:pointer!important}.settings_page_parsely a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.settings_page_parsely #track-post-types td,.settings_page_parsely #track-post-types th{padding-left:10px;padding-right:10px}.settings_page_parsely #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parse-ly_page_parsely-settings{--padding-default:15px}.parse-ly_page_parsely-settings fieldset.user-role-permissions label{margin-right:1rem!important}.parse-ly_page_parsely-settings .content-helper-message{margin-top:1.5rem}.parse-ly_page_parsely-settings .content-helper-message p{padding:.5rem}.parse-ly_page_parsely-settings .disabled-before-posting label:not(.prevent-disable),.parse-ly_page_parsely-settings .disabled-before-posting p,.parse-ly_page_parsely-settings .disabled-before-posting th,.parse-ly_page_parsely-settings fieldset:disabled label:not(.prevent-disable),.parse-ly_page_parsely-settings fieldset:disabled p,.parse-ly_page_parsely-settings fieldset:disabled th,.parse-ly_page_parsely-settings tr:has(fieldset:disabled) label:not(.prevent-disable),.parse-ly_page_parsely-settings tr:has(fieldset:disabled) p,.parse-ly_page_parsely-settings tr:has(fieldset:disabled) th{color:var(--gray-500);cursor:default}.parse-ly_page_parsely-settings #track-post-types{max-width:550px;width:100%}.parse-ly_page_parsely-settings #track-post-types td,.parse-ly_page_parsely-settings #track-post-types th{display:table-cell;padding:var(--padding-default);text-align:center;vertical-align:middle}.parse-ly_page_parsely-settings #track-post-types td{padding:0}.parse-ly_page_parsely-settings #track-post-types td label{display:inline-block;margin:0!important;padding-bottom:var(--padding-default);padding-top:var(--padding-default);width:100%}.parse-ly_page_parsely-settings #track-post-types thead th:nth-child(3){word-break:break-word}.parse-ly_page_parsely-settings .managed-option-badge{border:.0625rem solid var(--green-500);border-radius:.25rem;color:var(--green-500)!important;display:inline-block;font-size:.625rem;padding:.125rem .25rem;text-decoration:none}.parse-ly_page_parsely-settings a.managed-option-badge{cursor:pointer!important}.parse-ly_page_parsely-settings a.managed-option-badge:hover{background-color:var(--green-500);color:#fff!important}@media only screen and (max-width:380px){.parse-ly_page_parsely-settings #track-post-types td,.parse-ly_page_parsely-settings #track-post-types th{padding-left:10px;padding-right:10px}.parse-ly_page_parsely-settings #track-post-types th:first-child{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}} diff --git a/build/admin-settings.js b/build/admin-settings.js index 9922fcdbee..5cda900cca 100644 --- a/build/admin-settings.js +++ b/build/admin-settings.js @@ -1 +1 @@ -!function(){"use strict";!function(){function e(){var e,t,n=""!==location.hash?location.hash.substring(1):"basic-section";null===(e=document.querySelectorAll(".nav-tab"))||void 0===e||e.forEach((function(e){e.classList.contains(n+"-tab")?e.classList.add("nav-tab-active"):e.classList.remove("nav-tab-active")})),null===(t=document.querySelectorAll(".tab-content"))||void 0===t||t.forEach((function(e){e.classList.contains(n)?e.setAttribute("style","display: initial"):e.setAttribute("style","display: none")}));var i=document.querySelector('form[name="parsely"]');i&&(i.removeAttribute("hidden"),i.setAttribute("action","options.php#".concat(n)))}function t(e){var t=e.target.dataset.option,n=window.wp.media({multiple:!1,library:{type:"image"}});n.on("select",(function(){var e=n.state().get("selection").first().toJSON().url,i="#media-single-image-"+t+" input.file-path",o=document.querySelector(i);o&&(o.value=e)})),n.open()}document.addEventListener("DOMContentLoaded",(function(){var n;!function(){var e=document.querySelector("input#content_helper_ai_features_enabled"),t=document.querySelectorAll("input#content_helper_smart_linking_enabled, input#content_helper_title_suggestions_enabled, input#content_helper_excerpt_suggestions_enabled"),n=document.querySelectorAll("div.content-helper-section fieldset");function i(){e&&(e.checked?n.forEach((function(e){c(e,!1),t.forEach((function(e){o(e)}))})):(n.forEach((function(t){t.querySelector("#".concat(e.id))||c(t)})),document.querySelectorAll("label.prevent-disable").forEach((function(e){a(e,!1)}))))}function o(e){var t,n,i=null===(n=null===(t=e.closest("fieldset"))||void 0===t?void 0:t.nextSibling)||void 0===n?void 0:n.nextSibling;e.checked?c([e,i],!1):(c(i),a(e.parentElement))}function a(e,t){void 0===t&&(t=!0),t?e.classList.add("prevent-disable"):e.classList.remove("prevent-disable")}function c(e,t){void 0===t&&(t=!0),Array.isArray(e)||(e=[e]),e.forEach((function(e){t?e.setAttribute("disabled","disabled"):e.removeAttribute("disabled")}))}(function(){var e;null===(e=document.querySelector('.wp-admin form[name="parsely"]'))||void 0===e||e.addEventListener("submit",(function(){var e=".wp-admin .content-helper-section fieldset";document.querySelectorAll("".concat(e,"[disabled]")).forEach((function(t){var n,i;null===(i=null===(n=t.parentElement)||void 0===n?void 0:n.parentElement)||void 0===i||i.classList.add("disabled-before-posting"),t.querySelectorAll("".concat(e,' label input[type="checkbox"]')).forEach((function(e){e.classList.add("disabled")})),t.removeAttribute("disabled")}))}))})(),i(),null==e||e.addEventListener("change",(function(){i()})),t.forEach((function(e){e.addEventListener("change",(function(){o(e)}))}))}(),e(),window.addEventListener("hashchange",e),null===(n=document.querySelector(".media-single-image button.browse"))||void 0===n||n.addEventListener("click",t)}))}()}(); \ No newline at end of file +!function(){"use strict";var e={20:function(e,t,n){var r=n(609),o=Symbol.for("react.element"),a=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),s=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,i={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,n){var r,l={},c=null,u=null;for(r in void 0!==n&&(c=""+n),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)a.call(t,r)&&!i.hasOwnProperty(r)&&(l[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===l[r]&&(l[r]=t[r]);return{$$typeof:o,type:e,key:c,ref:u,props:l,_owner:s.current}}},848:function(e,t,n){e.exports=n(20)},609:function(e){e.exports=window.React}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var a=t[r]={exports:{}};return e[r](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e,t,r=window.wp.escapeHtml,o=window.wp.i18n,a=n(848),s=window.wp.data,i=function(e){void 0===e&&(e=null);var t="";(null==e?void 0:e.children)&&(t=e.children);var n="content-helper-error-message";return(null==e?void 0:e.className)&&(n+=" "+e.className),(0,a.jsx)("div",{className:n,"data-testid":null==e?void 0:e.testId,dangerouslySetInnerHTML:{__html:t}})},l=(e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)},function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function __(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(__.prototype=n.prototype,new __)});!function(e){e.AccessToFeatureDisabled="ch_access_to_feature_disabled",e.CannotFormulateApiQuery="ch_cannot_formulate_api_query",e.FetchError="fetch_error",e.HttpRequestFailed="http_request_failed",e.ParselyAborted="ch_parsely_aborted",e[e.ParselyApiForbidden=403]="ParselyApiForbidden",e.ParselyApiResponseContainsError="ch_response_contains_error",e.ParselyApiReturnedNoData="ch_parsely_api_returned_no_data",e.ParselyApiReturnedTooManyResults="ch_parsely_api_returned_too_many_results",e.PluginCredentialsNotSetMessageDetected="parsely_credentials_not_set_message_detected",e.PluginSettingsApiSecretNotSet="parsely_api_secret_not_set",e.PluginSettingsSiteIdNotSet="parsely_site_id_not_set",e.PostIsNotPublished="ch_post_not_published",e.UnknownError="ch_unknown_error",e.ParselySuggestionsApiAuthUnavailable="AUTH_UNAVAILABLE",e.ParselySuggestionsApiNoAuthentication="NO_AUTHENTICATION",e.ParselySuggestionsApiNoAuthorization="NO_AUTHORIZATION",e.ParselySuggestionsApiNoData="NO_DATA",e.ParselySuggestionsApiOpenAiError="OPENAI_ERROR",e.ParselySuggestionsApiOpenAiSchema="OPENAI_SCHEMA",e.ParselySuggestionsApiOpenAiUnavailable="OPENAI_UNAVAILABLE",e.ParselySuggestionsApiSchemaError="SCHEMA_ERROR",e.TrafficBoostInboundLinkNotFound="tb_inbound_link_not_found"}(t||(t={}));var c=function(e){function n(r,a,s){void 0===s&&(s=(0,o.__)("Error:","wp-parsely"));var i=this;r.startsWith(s)&&(s=""),(i=e.call(this,s.length>0?"".concat(s," ").concat(r):r)||this).hint=null,i.name=i.constructor.name,i.code=a;var l=[t.AccessToFeatureDisabled,t.ParselyApiForbidden,t.ParselyApiResponseContainsError,t.ParselyApiReturnedNoData,t.ParselyApiReturnedTooManyResults,t.PluginCredentialsNotSetMessageDetected,t.PluginSettingsApiSecretNotSet,t.PluginSettingsSiteIdNotSet,t.PostIsNotPublished,t.UnknownError,t.ParselySuggestionsApiAuthUnavailable,t.ParselySuggestionsApiNoAuthentication,t.ParselySuggestionsApiNoAuthorization,t.ParselySuggestionsApiNoData,t.ParselySuggestionsApiSchemaError];return i.retryFetch=!l.includes(i.code),Object.setPrototypeOf(i,n.prototype),i.code===t.AccessToFeatureDisabled?i.message=(0,o.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):i.code===t.ParselySuggestionsApiNoAuthorization?i.message=(0,o.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):i.code===t.ParselySuggestionsApiOpenAiError||i.code===t.ParselySuggestionsApiOpenAiUnavailable?i.message=(0,o.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):i.code===t.HttpRequestFailed&&i.message.includes("cURL error 28")?i.message=(0,o.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):i.code===t.ParselySuggestionsApiSchemaError?i.message=(0,o.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):i.code===t.ParselySuggestionsApiNoData?i.message=(0,o.__)("The Parse.ly API couldn't find any relevant data to fulfill the request. Please retry with a different input.","wp-parsely"):i.code===t.ParselySuggestionsApiOpenAiSchema?i.message=(0,o.__)("The Parse.ly API returned an incorrect response. Please try again later.","wp-parsely"):i.code===t.ParselySuggestionsApiAuthUnavailable&&(i.message=(0,o.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),i}return l(n,e),n.prototype.Message=function(e){return void 0===e&&(e=null),[t.PluginCredentialsNotSetMessageDetected,t.PluginSettingsSiteIdNotSet,t.PluginSettingsApiSecretNotSet].includes(this.code)?function(e){var t;return void 0===e&&(e=null),(0,a.jsx)(i,{className:null==e?void 0:e.className,testId:"empty-credentials-message",children:null!==(t=window.wpParselyEmptyCredentialsMessage)&&void 0!==t?t:(0,o.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely")})}(e):(this.code===t.FetchError&&(this.hint=this.Hint((0,o.__)("This error can sometimes be caused by ad-blockers or browser tracking protections. Please add this site to any applicable allow lists and try again.","wp-parsely"))),this.code!==t.ParselyApiForbidden&&this.code!==t.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,o.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===t.HttpRequestFailed&&(this.hint=this.Hint((0,o.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely"))),(0,a.jsx)(i,{className:null==e?void 0:e.className,testId:"error",children:"

".concat(this.message,"

").concat(this.hint?this.hint:"")}))},n.prototype.Hint=function(e){return'

'.concat((0,o.__)("Hint:","wp-parsely")," ").concat(e,"

")},n.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,s.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},n}(Error),u=window.wp.url,p=window.wp.apiFetch,d=n.n(p),f=function(){function e(){this.abortControllers=new Map}return e.prototype.cancelRequest=function(e){if(e)(t=this.abortControllers.get(e))&&(t.abort(),this.abortControllers.delete(e));else{var t,n=Array.from(this.abortControllers.keys()).pop();n&&(t=this.abortControllers.get(n))&&(t.abort(),this.abortControllers.delete(n))}},e.prototype.cancelAll=function(){this.abortControllers.forEach((function(e){return e.abort()})),this.abortControllers.clear()},e.prototype.getOrCreateController=function(e){if(e&&this.abortControllers.has(e))return{abortController:this.abortControllers.get(e),abortId:e};var t=null!=e?e:"auto-"+Date.now(),n=new AbortController;return this.abortControllers.set(t,n),{abortController:n,abortId:t}},e.prototype.fetch=function(e,n){return r=this,a=void 0,i=function(){var r,a,s,i,l,u;return function(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},s=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return s.next=i(0),s.throw=i(1),s.return=i(2),"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function i(i){return function(l){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s&&(s=0,i[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]%s

",(0,r.escapeHTML)((0,o.__)("All Content Helper AI functionality is disabled because an API Secret has not been set.","wp-parsely")))),[3,5];case 4:return n&&(200!==n.api.code?(u=(0,o.sprintf)('%2$s',"https://wpvip.com/content-helper/#content-helper-form",(0,o.__)("Request access here","wp-parsely")),d=(0,o.sprintf)((0,r.escapeHTML)((0,o.__)("All Content Helper AI functionality is disabled for this website. %s.","wp-parsely")),u),e=(0,o.sprintf)("

%s

",d)):200===n.api.code&&200!==n.traffic_boost.code&&(p=(0,o.sprintf)('%2$s',"mailto:support@parsely.com","support@parsely.com"),d=(0,o.sprintf)((0,r.escapeHTML)((0,o.__)("Traffic Boost functionality is disabled for this website. To enable it, contact %s.","wp-parsely")),p),e=(0,o.sprintf)("

%s

",d))),e&&((f=document.createElement("div")).className="content-helper-message notice notice-error",f.innerHTML=e,(h=document.querySelector(".content-helper-section"))&&h.insertBefore(f,h.firstChild)),[7];case 5:return[2]}}))},new((a=void 0)||(a=Promise))((function(t,r){function o(e){try{l(s.next(e))}catch(e){r(e)}}function i(e){try{l(s.throw(e))}catch(e){r(e)}}function l(e){var n;e.done?t(e.value):(n=e.value,n instanceof a?n:new a((function(e){e(n)}))).then(o,i)}l((s=s.apply(e,n||[])).next())}))}(),function(){var e=document.querySelector("input#content_helper_ai_features_enabled"),t=document.querySelectorAll("input#content_helper_smart_linking_enabled, input#content_helper_title_suggestions_enabled, input#content_helper_excerpt_suggestions_enabled, input#content_helper_traffic_boost_enabled"),n=document.querySelectorAll("div.content-helper-section fieldset");function r(){e&&(e.checked?n.forEach((function(e){s(e,!1),t.forEach((function(e){o(e)}))})):(n.forEach((function(t){t.querySelector("#".concat(e.id))||s(t)})),document.querySelectorAll("label.prevent-disable").forEach((function(e){a(e,!1)}))))}function o(e){var t,n,r=null===(n=null===(t=e.closest("fieldset"))||void 0===t?void 0:t.nextSibling)||void 0===n?void 0:n.nextSibling;e.checked?s([e,r],!1):(s(r),a(e.parentElement))}function a(e,t){void 0===t&&(t=!0),t?e.classList.add("prevent-disable"):e.classList.remove("prevent-disable")}function s(e,t){void 0===t&&(t=!0),Array.isArray(e)||(e=[e]),e.forEach((function(e){t?e.setAttribute("disabled","disabled"):e.removeAttribute("disabled")}))}(function(){var e;null===(e=document.querySelector('.wp-admin form[name="parsely"]'))||void 0===e||e.addEventListener("submit",(function(){var e=".wp-admin .content-helper-section fieldset";document.querySelectorAll("".concat(e,"[disabled]")).forEach((function(t){var n,r;null===(r=null===(n=t.parentElement)||void 0===n?void 0:n.parentElement)||void 0===r||r.classList.add("disabled-before-posting"),t.querySelectorAll("".concat(e,' label input[type="checkbox"]')).forEach((function(e){e.classList.add("disabled")})),t.removeAttribute("disabled")}))}))})(),r(),null==e||e.addEventListener("change",(function(){r()})),t.forEach((function(e){e.addEventListener("change",(function(){o(e)}))}))}(),g(),window.addEventListener("hashchange",g),null===(e=document.querySelector(".media-single-image button.browse"))||void 0===e||e.addEventListener("click",_)}))}()}(); \ No newline at end of file diff --git a/build/content-helper/dashboard-page-rtl.css b/build/content-helper/dashboard-page-rtl.css new file mode 100644 index 0000000000..296e193495 --- /dev/null +++ b/build/content-helper/dashboard-page-rtl.css @@ -0,0 +1,6 @@ +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parsely-menu-page-dashboard .parsely-dashboard-page-body,.parsely-menu-page-dashboard .parsely-dashboard-page-header{padding:var(--grid-unit-40) var(--grid-unit-40) var(--grid-unit-60) var(--grid-unit-40)}.parsely-menu-page-dashboard .dashboard-header-background{background:linear-gradient(-303deg,#000 30.51%,#487006 133.77%)}.parsely-menu-page-dashboard .dashboard-header{align-items:flex-start;display:flex;flex-wrap:wrap;gap:var(--grid-unit-25);justify-content:space-between}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary{align-items:flex-start;color:var(--sidebar-white);display:flex;flex-direction:column;gap:var(--grid-unit-30);width:18.75rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-info{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-info .summary-title{align-self:stretch;font-size:var(--font-size--bigger);font-style:normal;font-weight:600;line-height:2.8125rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-info .summary-text{align-self:stretch;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:var(--font-size--large)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-button button{background:transparent;border:1px solid var(--sidebar-white);box-shadow:none;color:var(--sidebar-white);cursor:pointer;margin-top:var(--grid-unit-20);padding:var(--grid-unit-10) var(--grid-unit-20)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-button button:hover{background:var(--sidebar-white);box-shadow:none;color:var(--sidebar-black)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats{align-content:flex-start;align-items:flex-start;align-self:stretch;display:flex;flex-wrap:wrap;gap:var(--grid-unit-30);justify-content:flex-end;width:31.25rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card{align-items:flex-start;color:var(--sidebar-white);display:flex;flex-direction:column;gap:var(--grid-unit-05);height:var(--grid-unit-60);justify-content:center;width:9.375rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-title{align-items:center;display:flex;font-size:var(--font-size--small);font-style:normal;font-weight:400;gap:var(--grid-unit-05);line-height:var(--font-size--large)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-title svg{fill:var(--sidebar-white)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-value{align-items:center;display:flex;font-size:1.5rem;font-style:normal;font-weight:600;gap:var(--grid-unit-05);letter-spacing:-.48px;line-height:2rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-value .card-change{font-size:var(--font-size--medium);font-style:normal;font-weight:500;line-height:var(--font-size--large)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top{align-items:flex-start;border-bottom:1px solid var(--sidebar-white);display:flex;gap:var(--grid-unit-30);padding-bottom:var(--grid-unit-30)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .card-title{color:var(--dashboard-accent)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .card-title svg{fill:var(--dashboard-accent)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .card-value{color:var(--dashboard-accent)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .stat-intro{justify-content:flex-start}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .stat-intro .card-title{color:var(--sidebar-white);font-size:var(--font-size--medium);font-style:normal;font-weight:500;line-height:var(--font-size--extra-large)} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parsely-menu-page-traffic-boost .parsely-dashboard-page-header{padding:var(--grid-unit-30)}.parsely-menu-page-traffic-boost .traffic-boost-search-container{border-radius:2px;margin-bottom:0;padding:var(--grid-unit-15) 0}.parsely-menu-page-traffic-boost-single-post{align-items:flex-start;align-self:stretch;display:flex;flex:1 0 0;gap:var(--grid-unit-20);padding:var(--grid-unit-20) 0 var(--grid-unit-20) var(--grid-unit-20);position:relative}.wp-parsely-snackbar-notices.traffic-boost-snackbar-notices{padding-right:30rem} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.traffic-boost-preview{align-self:stretch;background-color:var(--sidebar-white);border-radius:.5rem;display:flex;flex:1 0 0;flex-direction:column;min-width:18.75rem;overflow:hidden;padding:0}.traffic-boost-preview .wp-parsely-preview{background:var(--sidebar-white);display:flex;flex:1;height:100%;overflow:hidden}.traffic-boost-preview .wp-parsely-preview .preview-iframe-wrapper{height:100%;overflow:hidden;position:relative;width:100%}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-iframe{background:var(--sidebar-white);border:none;height:100%;right:0;overflow-x:hidden;overflow-y:auto;position:absolute;top:0;transition:all .5s ease;width:100%;z-index:0}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-iframe.is-loading{filter:blur(4px);opacity:.7}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading{align-items:center;background-color:var(--sidebar-white);display:flex;inset:0;justify-content:center;opacity:0;pointer-events:none;position:absolute;transition:opacity .1s ease-in-out,visibility .1s ease-in-out;visibility:hidden;z-index:3}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading.is-loading{align-items:center;display:flex;flex-direction:column;font-size:var(--font-size--extra-large);font-weight:500;gap:var(--grid-unit-30);justify-content:center;line-height:var(--font-size--extra-large);opacity:1;visibility:visible}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading.is-loading .wp-parsely-loading{width:90%}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading.is-loading .wp-parsely-loading .wp-parsely-loading-message{max-width:37.5rem;text-align:center}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading .components-spinner{height:var(--grid-unit-40);margin:0;width:var(--grid-unit-40)}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-generating-placement{align-items:center;display:flex;inset:0;justify-content:center;pointer-events:none;position:absolute;z-index:3}.traffic-boost-preview-header{align-items:center;background:var(--white);border-bottom:1px solid var(--gray-400);display:flex;justify-content:space-between;padding:var(--grid-unit-15) var(--grid-unit-20);z-index:5}.traffic-boost-preview-header .traffic-boost-preview-actions{display:flex;gap:var(--grid-unit-10)}.traffic-boost-preview-header .traffic-boost-preview-actions button{border-radius:.25rem;height:1.875rem;min-width:1.875rem;padding:var(--grid-unit-5)}.traffic-boost-preview-header .traffic-boost-preview-actions button:hover{color:var(--wp-admin-theme-color)}.traffic-boost-preview-header .traffic-boost-preview-actions .components-button.is-pressed:focus:not(:disabled){box-shadow:none}.traffic-boost-preview-header .traffic-boost-preview-info{align-items:flex-start;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-5);min-width:0}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-title{color:var(--gray-900);font-size:var(--font-size--large);font-weight:500;line-height:var(--font-size--extra-large);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links{align-items:center;align-self:stretch;display:flex;font-size:var(--font-size--medium);font-weight:400;gap:var(--grid-unit-10);line-height:var(--font-size--extra-large);min-height:var(--grid-unit-30)}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10)}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button{height:1.375rem;padding:var(--grid-unit-5) var(--grid-unit-10)}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button.is-pressed,.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button:focus{box-shadow:0 0 0 1px var(--black);outline:none}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button:not(.is-pressed):focus{box-shadow:inset 0 0 0 1px var(--wp-admin-theme-color);color:var(--wp-admin-theme-color)}.wp-parsely-traffic-boost-preview-settings-popover{margin-top:var(--grid-unit-20);width:17.1875rem}.wp-parsely-traffic-boost-preview-settings-popover-content{min-width:13.75rem;padding:var(--grid-unit-20);width:17.1875rem}.traffic-boost-preview-footer{align-items:center;background:var(--white);border-top:1px solid var(--gray-400);display:flex;justify-content:space-between;padding:var(--grid-unit-10) var(--grid-unit-20)}.traffic-boost-preview-footer .traffic-boost-preview-footer-next,.traffic-boost-preview-footer .traffic-boost-preview-footer-previous{min-width:2.25rem}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions{align-items:center;display:flex;flex-wrap:wrap;gap:var(--grid-unit-10);justify-content:center}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions .components-button{height:2.25rem}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions .traffic-boost-preview-footer-navigation{align-items:center;display:flex;font-size:var(--font-size--small);font-weight:500;gap:var(--grid-unit-5);line-height:var(--font-size--medium);text-transform:uppercase}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions .traffic-boost-preview-footer-navigation select{border:none;font-size:var(--font-size--small);font-weight:500;line-height:var(--font-size--medium);margin-bottom:2px} +.traffic-boost-links{display:flex;flex:1;flex-direction:column;height:100%;min-height:0}.traffic-boost-links .traffic-boost-links-list{display:flex;flex:1 1 auto;flex-direction:column;height:0;min-height:0;overflow-y:auto;overscroll-behavior:contain}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link{align-items:center;border-bottom:1px solid var(--gray-350);cursor:pointer;display:flex;flex:0 0 auto;gap:var(--grid-unit-15);padding:var(--grid-unit-20) var(--grid-unit-30)}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link.active{background:var(--Scales-Theme-theme-alpha-04,rgba(56,88,233,.04));border-bottom:1px solid var(--traffic-boost-header-background)}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link:focus{box-shadow:none;outline:2px solid var(--wp-admin-theme-color);outline-offset:-2px}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link .single-link-title{color:var(--sidebar-black);font-size:var(--font-size--medium);font-style:normal;font-weight:400;line-height:var(--grid-unit-30);overflow:hidden;text-overflow:ellipsis}.traffic-boost-links .links-pagination{align-items:center;color:var(--sidebar-black);display:flex;flex:0 0 auto;font-size:var(--font-size--smaller);font-style:normal;font-weight:500;justify-content:space-between;line-height:var(--grid-unit-20);margin-top:auto;padding:var(--grid-unit-15) var(--grid-unit-30);text-transform:uppercase}.traffic-boost-links .links-pagination .links-pagination-children{margin-left:auto}.traffic-boost-links .links-pagination .links-pagination-children .traffic-boost-add-suggestion{box-shadow:none}.traffic-boost-links .links-pagination .page-selector{align-items:center;display:flex;gap:var(--grid-unit-5)}.traffic-boost-links .links-pagination .page-selector select{background-color:transparent;border:none;cursor:pointer;font-size:var(--font-size--smaller);font-weight:500}.traffic-boost-links .links-pagination .page-selector select:focus{outline:2px solid var(--wp-admin-theme-color);outline-offset:1px}.traffic-boost-links .links-pagination .page-navigation{display:flex;gap:var(--grid-unit-5);margin-right:var(--grid-unit-30)}.traffic-boost-links .traffic-boost-links-list-loading{align-items:center;display:flex;gap:var(--grid-unit-10);height:100%;justify-content:center;padding:var(--grid-unit-20)} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.traffic-boost-sidebar{align-items:flex-start;background:var(--white);border-bottom:1px solid var(--gray-200);border-radius:var(--grid-unit-10);box-shadow:0 1px 1px 0 rgba(0,0,0,.03),0 1px 2px 0 rgba(0,0,0,.02),0 .1875rem .1875rem 0 rgba(0,0,0,.02),0 .25rem .25rem 0 rgba(0,0,0,.01);display:flex;flex-direction:column;height:calc(100vh - 4.0625rem);max-width:28.125rem;min-width:20rem}.traffic-boost-sidebar .traffic-boost-sidebar-header{align-items:center;align-self:stretch;background:var(--traffic-boost-header-background);display:flex;flex-direction:column;gap:var(--grid-unit-20);min-height:var(--grid-unit-50);padding:var(--grid-unit-20) var(--grid-unit-30)}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-sidebar-header-nav{align-items:center;align-self:stretch;display:flex;justify-content:space-between}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-sidebar-header-nav .components-button{font-size:var(--font-size--medium);font-weight:400;line-height:var(--grid-unit-25);padding-right:0;padding-left:0}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10);justify-content:flex-end}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-label{color:var(--gray-900);font-size:var(--font-size--small);font-style:normal;font-weight:500;line-height:var(--grid-unit-20);overflow:hidden;text-transform:uppercase}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-content{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10)}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-content .post-title{color:var(--gray-900);font-size:var(--font-size--large);font-style:normal;font-weight:500;line-height:var(--grid-unit-25)}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-divider{background:var(--gray-400);height:1px;margin:var(--grid-unit-10) 0;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-description{font-size:var(--font-size--medium);font-style:normal;font-weight:400;line-height:var(--grid-unit-20)}.traffic-boost-sidebar .traffic-boost-sidebar-content{display:flex;flex:1;flex-direction:column;gap:var(--grid-unit-20);min-height:0;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-settings .components-panel__body{border-bottom:0;border-top:0}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-empty-state{align-items:center;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:var(--grid-unit-20)}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-generating-footer{align-items:center;display:flex;gap:var(--grid-unit-10);justify-content:center;min-height:2.25rem;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-generating-footer span{margin-top:.3125rem}.traffic-boost-sidebar .traffic-boost-sidebar-tabs{display:flex;flex:1;flex-direction:column;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tab-content{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs{border-bottom:1px solid var(--gray-400);border-top:1px solid var(--gray-400);display:flex;margin:0;padding:0;position:relative;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item{flex:1;height:var(--grid-unit-60);justify-content:center;margin:0;padding:var(--grid-unit-15)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.is-active{box-shadow:inset 0 0 0 var(--wp-admin-border-width-focus) transparent,inset 0 -1.5px 0 0 var(--wp-admin-theme-color)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item .tab-count{align-items:center;background:var(--gray-400);border-radius:2px;display:inline-flex;gap:var(--grid-unit-10);justify-content:center;margin-right:var(--grid-unit-20);padding:var(--grid-unit-5) var(--grid-unit-10)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab{flex:0 0 var(--grid-unit-50);justify-content:center!important;min-width:var(--grid-unit-60)!important;padding:var(--grid-unit-10)!important;width:var(--grid-unit-60)!important}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab .icon{color:var(--gray-600);height:var(--grid-unit-30)!important;width:var(--grid-unit-30)!important}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab .icon svg{height:var(--grid-unit-30)!important;width:var(--grid-unit-30)!important}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab:hover .icon{color:var(--gray-900)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item .suggestions-tab{order:1}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item .inbound-links-tab{order:2}.traffic-boost-sidebar .traffic-boost-suggestions-loading-generating{align-items:center;display:flex;flex-direction:column;gap:var(--grid-unit-15);height:100%;justify-content:center;padding:var(--grid-unit-20)}.wp-parsely-traffic-boost-add-new-link-popover{width:25rem}.wp-parsely-traffic-boost-add-new-link-popover .components-popover__content{display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:var(--grid-unit-20);width:100%}.wp-parsely-traffic-boost-add-new-link-popover .traffic-boost-add-link-table.no-results{text-align:right}.wp-parsely-traffic-boost-add-new-link-popover .traffic-boost-add-link-table tr{cursor:pointer} +.parsely-tone-selector-dropdown{align-items:center;align-self:stretch;background:var(--Gutenberg-White,#fff);border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-tone-selector-dropdown button{height:2.0625rem}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-tone-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle svg:first-of-type path{transform:scale(1.4);transform-origin:center}.parsely-tone-selector-dropdown .parsely-tone-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:right}.parsely-tone-selector-dropdown .parsely-tone-selector-label:first-letter{text-transform:uppercase}.parsely-persona-selector-custom{width:100%}.parsely-persona-selector-custom .components-base-control__field input{display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-persona-selector-custom .components-base-control__field input,.parsely-persona-selector-dropdown{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px}.parsely-persona-selector-dropdown{background:var(--Gutenberg-White,#fff);height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-persona-selector-dropdown button{height:2.0625rem}.parsely-persona-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-persona-selector-dropdown .parsely-persona-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:right}.parsely-persona-selector-dropdown .parsely-persona-selector-label:first-letter{text-transform:uppercase}.parsely-tone-selector-custom{width:100%}.parsely-tone-selector-custom .components-base-control__field input{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-inputrange-control{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-inputrange-control .parsely-inputrange-control__label{margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-20);height:2.5rem}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control{display:flex;flex:1 0 0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-inner-spin-button,.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]{-moz-appearance:textfield}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-base-control__field{flex-grow:1}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-input-control__suffix{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control{flex:1 0 0;height:36px}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control .components-range-control__root{height:2.5rem}#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parsely-thumbnail{border-radius:3px;flex-shrink:0;overflow:hidden}.parsely-thumbnail img{border-radius:3px;height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.parsely-thumbnail .parsely-thumbnail-icon-container{align-items:center;background:var(--gray-500);border-radius:3px;display:flex;height:100%;justify-content:center;width:100%}.parsely-thumbnail .parsely-thumbnail-icon-container svg{fill:var(--sidebar-white);height:60%;width:60%}.wp-parsely-snackbar-notices{bottom:4rem;display:flex;flex-direction:column-reverse;gap:.375rem;padding:1rem;position:fixed;width:100%;z-index:999999}.wp-parsely-snackbar-notices svg{fill:currentcolor}.wp-parsely-loading{align-items:center;border-radius:.25rem;color:var(--sidebar-black);display:flex;gap:var(--grid-unit-20);justify-content:center;min-height:1.5rem;min-width:25rem;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-loading .components-spinner{flex-shrink:0;margin:0}.wp-parsely-loading .wp-parsely-loading-message{flex-grow:1;font-size:var(--font-size--medium);line-height:1.4;margin:0;max-width:25rem}.wp-parsely-loading .wp-parsely-typewriter-text{display:inline-block;min-height:1.4em;min-width:1ch}.wp-parsely-loading .wp-parsely-typewriter-cursor{animation:blink 1s step-end infinite;display:inline-block;font-weight:400;margin-right:2px;opacity:.7}@keyframes blink{0%,to{opacity:0}50%{opacity:1}}.parsely-panel-settings{width:100%}.parsely-panel-settings .parsely-panel-settings-header{display:flex;margin:.625rem 0;width:100%}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label{flex-grow:2;margin:0 .3125rem 0 0;text-align:right}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field{align-items:center;display:flex;justify-content:space-between}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field .components-base-control__label{margin-bottom:0}.parsely-panel-settings .parsely-panel-settings-body{align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-dropdown-label{align-self:stretch;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-content-helper-error{align-self:flex-start;margin:0}.wp-parsely-content-helper-error p{margin:0}.wp-parsely-content-helper-error .content-helper-error-message{margin:0!important}.wp-parsely-collapsible-panel{align-items:flex-start;align-self:stretch;border-bottom:none;border-radius:2px;border-top:none;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:0 0 .5rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title{align-items:center;align-self:stretch;display:flex;margin:0 -1rem .375rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title .components-panel__icon,.wp-parsely-collapsible-panel .components-panel__body-title svg{margin-right:0;margin-left:var(--grid-unit-10);order:-1}.wp-parsely-collapsible-panel .components-panel__body-title:hover{background-color:transparent}.wp-parsely-collapsible-panel.is-opened{padding:0}.wp-parsely-collapsible-panel.is-opened>div:first-of-type{margin-top:calc(var(--grid-unit-20)*-1)}.wp-parsely-collapsible-panel.is-opened .components-panel__body-title{margin:0 calc(var(--grid-unit-20)*-1) .375rem;padding-bottom:0}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button{color:var(--Gutenberg-Gray-900,#1e1e1e);font-size:.6875rem;font-style:normal;font-weight:600;line-height:1rem;padding:var(--grid-unit-20) var(--grid-unit-20);text-transform:uppercase}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button .components-panel__arrow{margin-left:0}.wp-parsely-collapsible-panel .components-panel__body.is-opened{padding:0}.parsely-table-container.is-loading{align-items:center;display:flex;justify-content:center;padding:var(--grid-unit-20)}.parsely-table-container table{border-collapse:collapse;border-spacing:0;width:100%}.parsely-table-container table tr{position:relative}.parsely-table-container table tr:after{background-color:var(--border);bottom:0;content:"";height:1px;right:50%;position:absolute;transform:translateX(50%);width:100vw}.parsely-table-container table tr td,.parsely-table-container table tr th{padding:var(--grid-unit-15) 0}.parsely-table-container table tr td.post-info,.parsely-table-container table tr th.post-info-header{text-align:right}.parsely-table-container table tr th{color:var(--sidebar-black);font-size:var(--font-size--small);font-style:normal;font-weight:600;line-height:var(--font-size--large);text-transform:uppercase}.parsely-table-container table tr th.views-header{min-width:3.75rem;text-align:center}.parsely-table-container table tr th.views-header .views-header-period{color:var(--gray-500);font-size:var(--font-size--smaller);font-weight:400;margin-right:var(--grid-unit-5)}.parsely-table-container table tr td.metrics{min-width:100px}.parsely-table-container table tr td.metrics .metrics-container{align-items:center;display:flex;flex-direction:column;gap:var(--grid-unit-5)}.parsely-table-container table tr td.metrics .metrics-container .metric-change{font-size:var(--font-size--small);font-weight:600;line-height:var(--font-size--large);margin-right:var(--grid-unit-5)}.parsely-table-container table tr td.metrics .metrics-container .metric-change-positive{color:var(--parsely-green)}.parsely-table-container table tr td.metrics .metrics-container .metric-change-negative{color:#900000}.parsely-table-container table tr td.metrics .metrics-container .metric-change-neutral{color:var(--gray-500)}.parsely-table-container table tr td.metrics .metrics-container .metric-boost-percentage{color:var(--parsely-green);font-size:var(--font-size--small);font-weight:600}.parsely-table-container table tr td.actions{align-items:center;display:flex;gap:var(--grid-unit-10);justify-content:flex-end;margin-right:var(--grid-unit-10);max-width:8.4375rem;min-height:2.5rem}.parsely-table-container table tr td.actions a{text-decoration:none}.parsely-table-container table tr td.actions .boost-link-container{display:flex;flex-direction:column;gap:.25rem;height:100%;text-align:center;width:100%}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status{display:flex;gap:.25rem;justify-content:center}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .hidden{opacity:0}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .boost-inbound,.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .boost-outbound{align-items:center;background-color:var(--gray-300);border-radius:.375rem;color:var(--sidebar-black);display:flex;flex-grow:1;font-size:var(--font-size--small);justify-content:center;line-height:var(--font-size--medium);padding:.25rem .5625rem}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .boost-link-status-icon-inbound{transform:rotate(-180deg)}.parsely-table-container.no-results{color:#757575;font-style:italic;padding:var(--grid-unit-15);text-align:center}.parsely-table-container .suggestion-bubble{background:var(--parsely-green);border:none;border-radius:1.25rem;box-shadow:none;color:var(--sidebar-white);cursor:pointer;display:inline-block;font-size:.8125rem;line-height:.875rem;margin-right:.375rem;min-width:1.75rem;padding:3px .375rem;text-align:center}.parsely-table-container.compact table tr td.post-info{max-width:100px}.parsely-table-container.compact tr:after{width:100%}.parsely-table-container.compact .post-title{display:-webkit-box!important;overflow:hidden;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical}.parsely-table-container.compact .post-title>span{white-space:normal!important}.parsely-table-container.hide-pagination table tr:last-child:after{display:none}.posts-table-post-info{align-items:flex-start;display:flex;flex:1 0 0;gap:var(--grid-unit-20);min-height:2.5rem}.posts-table-post-info .posts-table-thumbnail{align-self:center}.posts-table-post-info .post-details{align-items:flex-start;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-05,4px);justify-content:center;min-height:var(--grid-unit-40);min-width:0}.posts-table-post-info .post-details .post-title{align-items:center;align-self:stretch;display:flex;font-size:var(--font-size--medium);font-style:normal;font-weight:600;gap:var(--grid-unit-5);line-height:1.25rem;overflow:hidden;text-overflow:ellipsis}.posts-table-post-info .post-details .post-title>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.posts-table-post-info .post-details .post-meta{align-content:center;align-items:center;align-self:stretch;color:var(--gray-500);display:flex;flex-wrap:wrap;gap:var(--grid-unit-5) var(--grid-unit-10)}.posts-table-post-info .post-details .post-categories{display:flex;gap:var(--grid-unit-5)}.posts-table-post-info .post-details .post-categories span{background:var(--gray-400);border-radius:.375rem;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-weight:500;line-height:var(--font-size--large);padding:2px var(--grid-unit-10)}.posts-table-pagination-controls{align-items:center;align-self:stretch;display:flex;font-size:var(--font-size--smaller);font-style:normal;font-weight:600;gap:var(--grid-unit-30);justify-content:flex-end;line-height:var(--font-size--large);padding:var(--grid-unit-15);text-transform:uppercase}.posts-table-pagination-controls .page-selector{align-items:center;display:flex;gap:var(--grid-unit-10)}.posts-table-pagination-controls .page-navigation{align-items:center;display:flex;gap:var(--grid-unit-5);justify-content:flex-end}body{background:#fff}.parsely-dashboard-container{margin-right:-1.25rem;overflow:hidden}.parsely-dashboard-page-body,.parsely-dashboard-page-header{margin:0 auto;max-width:var(--dashboard-width);padding:var(--grid-unit-30)} diff --git a/build/content-helper/dashboard-page.asset.php b/build/content-helper/dashboard-page.asset.php new file mode 100644 index 0000000000..af43cd4756 --- /dev/null +++ b/build/content-helper/dashboard-page.asset.php @@ -0,0 +1 @@ + array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-escape-html', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url'), 'version' => '1417774194a1a7f2530a'); diff --git a/build/content-helper/dashboard-page.css b/build/content-helper/dashboard-page.css new file mode 100644 index 0000000000..0a6d59e657 --- /dev/null +++ b/build/content-helper/dashboard-page.css @@ -0,0 +1,6 @@ +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parsely-menu-page-dashboard .parsely-dashboard-page-body,.parsely-menu-page-dashboard .parsely-dashboard-page-header{padding:var(--grid-unit-40) var(--grid-unit-40) var(--grid-unit-60) var(--grid-unit-40)}.parsely-menu-page-dashboard .dashboard-header-background{background:linear-gradient(303deg,#000 30.51%,#487006 133.77%)}.parsely-menu-page-dashboard .dashboard-header{align-items:flex-start;display:flex;flex-wrap:wrap;gap:var(--grid-unit-25);justify-content:space-between}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary{align-items:flex-start;color:var(--sidebar-white);display:flex;flex-direction:column;gap:var(--grid-unit-30);width:18.75rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-info{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-info .summary-title{align-self:stretch;font-size:var(--font-size--bigger);font-style:normal;font-weight:600;line-height:2.8125rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-info .summary-text{align-self:stretch;font-size:var(--font-size--small);font-style:normal;font-weight:400;line-height:var(--font-size--large)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-button button{background:transparent;border:1px solid var(--sidebar-white);box-shadow:none;color:var(--sidebar-white);cursor:pointer;margin-top:var(--grid-unit-20);padding:var(--grid-unit-10) var(--grid-unit-20)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-summary .summary-button button:hover{background:var(--sidebar-white);box-shadow:none;color:var(--sidebar-black)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats{align-content:flex-start;align-items:flex-start;align-self:stretch;display:flex;flex-wrap:wrap;gap:var(--grid-unit-30);justify-content:flex-end;width:31.25rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card{align-items:flex-start;color:var(--sidebar-white);display:flex;flex-direction:column;gap:var(--grid-unit-05);height:var(--grid-unit-60);justify-content:center;width:9.375rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-title{align-items:center;display:flex;font-size:var(--font-size--small);font-style:normal;font-weight:400;gap:var(--grid-unit-05);line-height:var(--font-size--large)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-title svg{fill:var(--sidebar-white)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-value{align-items:center;display:flex;font-size:1.5rem;font-style:normal;font-weight:600;gap:var(--grid-unit-05);letter-spacing:-.48px;line-height:2rem}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .header-stat-card .card-value .card-change{font-size:var(--font-size--medium);font-style:normal;font-weight:500;line-height:var(--font-size--large)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top{align-items:flex-start;border-bottom:1px solid var(--sidebar-white);display:flex;gap:var(--grid-unit-30);padding-bottom:var(--grid-unit-30)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .card-title{color:var(--dashboard-accent)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .card-title svg{fill:var(--dashboard-accent)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .card-value{color:var(--dashboard-accent)}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .stat-intro{justify-content:flex-start}.parsely-menu-page-dashboard .dashboard-header .dashboard-header-stats .stats-top .stat-intro .card-title{color:var(--sidebar-white);font-size:var(--font-size--medium);font-style:normal;font-weight:500;line-height:var(--font-size--extra-large)} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parsely-menu-page-traffic-boost .parsely-dashboard-page-header{padding:var(--grid-unit-30)}.parsely-menu-page-traffic-boost .traffic-boost-search-container{border-radius:2px;margin-bottom:0;padding:var(--grid-unit-15) 0}.parsely-menu-page-traffic-boost-single-post{align-items:flex-start;align-self:stretch;display:flex;flex:1 0 0;gap:var(--grid-unit-20);padding:var(--grid-unit-20) var(--grid-unit-20) var(--grid-unit-20) 0;position:relative}.wp-parsely-snackbar-notices.traffic-boost-snackbar-notices{padding-left:30rem} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.traffic-boost-preview{align-self:stretch;background-color:var(--sidebar-white);border-radius:.5rem;display:flex;flex:1 0 0;flex-direction:column;min-width:18.75rem;overflow:hidden;padding:0}.traffic-boost-preview .wp-parsely-preview{background:var(--sidebar-white);display:flex;flex:1;height:100%;overflow:hidden}.traffic-boost-preview .wp-parsely-preview .preview-iframe-wrapper{height:100%;overflow:hidden;position:relative;width:100%}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-iframe{background:var(--sidebar-white);border:none;height:100%;left:0;overflow-x:hidden;overflow-y:auto;position:absolute;top:0;transition:all .5s ease;width:100%;z-index:0}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-iframe.is-loading{filter:blur(4px);opacity:.7}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading{align-items:center;background-color:var(--sidebar-white);display:flex;inset:0;justify-content:center;opacity:0;pointer-events:none;position:absolute;transition:opacity .1s ease-in-out,visibility .1s ease-in-out;visibility:hidden;z-index:3}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading.is-loading{align-items:center;display:flex;flex-direction:column;font-size:var(--font-size--extra-large);font-weight:500;gap:var(--grid-unit-30);justify-content:center;line-height:var(--font-size--extra-large);opacity:1;visibility:visible}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading.is-loading .wp-parsely-loading{width:90%}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading.is-loading .wp-parsely-loading .wp-parsely-loading-message{max-width:37.5rem;text-align:center}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-loading .components-spinner{height:var(--grid-unit-40);margin:0;width:var(--grid-unit-40)}.traffic-boost-preview .wp-parsely-preview .wp-parsely-preview-generating-placement{align-items:center;display:flex;inset:0;justify-content:center;pointer-events:none;position:absolute;z-index:3}.traffic-boost-preview-header{align-items:center;background:var(--white);border-bottom:1px solid var(--gray-400);display:flex;justify-content:space-between;padding:var(--grid-unit-15) var(--grid-unit-20);z-index:5}.traffic-boost-preview-header .traffic-boost-preview-actions{display:flex;gap:var(--grid-unit-10)}.traffic-boost-preview-header .traffic-boost-preview-actions button{border-radius:.25rem;height:1.875rem;min-width:1.875rem;padding:var(--grid-unit-5)}.traffic-boost-preview-header .traffic-boost-preview-actions button:hover{color:var(--wp-admin-theme-color)}.traffic-boost-preview-header .traffic-boost-preview-actions .components-button.is-pressed:focus:not(:disabled){box-shadow:none}.traffic-boost-preview-header .traffic-boost-preview-info{align-items:flex-start;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-5);min-width:0}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-title{color:var(--gray-900);font-size:var(--font-size--large);font-weight:500;line-height:var(--font-size--extra-large);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links{align-items:center;align-self:stretch;display:flex;font-size:var(--font-size--medium);font-weight:400;gap:var(--grid-unit-10);line-height:var(--font-size--extra-large);min-height:var(--grid-unit-30)}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10)}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button{height:1.375rem;padding:var(--grid-unit-5) var(--grid-unit-10)}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button.is-pressed,.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button:focus{box-shadow:0 0 0 1px var(--black);outline:none}.traffic-boost-preview-header .traffic-boost-preview-info .traffic-boost-preview-info-links .traffic-boost-preview-info-links-counter button:not(.is-pressed):focus{box-shadow:inset 0 0 0 1px var(--wp-admin-theme-color);color:var(--wp-admin-theme-color)}.wp-parsely-traffic-boost-preview-settings-popover{margin-top:var(--grid-unit-20);width:17.1875rem}.wp-parsely-traffic-boost-preview-settings-popover-content{min-width:13.75rem;padding:var(--grid-unit-20);width:17.1875rem}.traffic-boost-preview-footer{align-items:center;background:var(--white);border-top:1px solid var(--gray-400);display:flex;justify-content:space-between;padding:var(--grid-unit-10) var(--grid-unit-20)}.traffic-boost-preview-footer .traffic-boost-preview-footer-next,.traffic-boost-preview-footer .traffic-boost-preview-footer-previous{min-width:2.25rem}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions{align-items:center;display:flex;flex-wrap:wrap;gap:var(--grid-unit-10);justify-content:center}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions .components-button{height:2.25rem}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions .traffic-boost-preview-footer-navigation{align-items:center;display:flex;font-size:var(--font-size--small);font-weight:500;gap:var(--grid-unit-5);line-height:var(--font-size--medium);text-transform:uppercase}.traffic-boost-preview-footer .traffic-boost-preview-footer-actions .traffic-boost-preview-footer-navigation select{border:none;font-size:var(--font-size--small);font-weight:500;line-height:var(--font-size--medium);margin-bottom:2px} +.traffic-boost-links{display:flex;flex:1;flex-direction:column;height:100%;min-height:0}.traffic-boost-links .traffic-boost-links-list{display:flex;flex:1 1 auto;flex-direction:column;height:0;min-height:0;overflow-y:auto;overscroll-behavior:contain}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link{align-items:center;border-bottom:1px solid var(--gray-350);cursor:pointer;display:flex;flex:0 0 auto;gap:var(--grid-unit-15);padding:var(--grid-unit-20) var(--grid-unit-30)}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link.active{background:var(--Scales-Theme-theme-alpha-04,rgba(56,88,233,.04));border-bottom:1px solid var(--traffic-boost-header-background)}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link:focus{box-shadow:none;outline:2px solid var(--wp-admin-theme-color);outline-offset:-2px}.traffic-boost-links .traffic-boost-links-list .traffic-boost-single-link .single-link-title{color:var(--sidebar-black);font-size:var(--font-size--medium);font-style:normal;font-weight:400;line-height:var(--grid-unit-30);overflow:hidden;text-overflow:ellipsis}.traffic-boost-links .links-pagination{align-items:center;color:var(--sidebar-black);display:flex;flex:0 0 auto;font-size:var(--font-size--smaller);font-style:normal;font-weight:500;justify-content:space-between;line-height:var(--grid-unit-20);margin-top:auto;padding:var(--grid-unit-15) var(--grid-unit-30);text-transform:uppercase}.traffic-boost-links .links-pagination .links-pagination-children{margin-right:auto}.traffic-boost-links .links-pagination .links-pagination-children .traffic-boost-add-suggestion{box-shadow:none}.traffic-boost-links .links-pagination .page-selector{align-items:center;display:flex;gap:var(--grid-unit-5)}.traffic-boost-links .links-pagination .page-selector select{background-color:transparent;border:none;cursor:pointer;font-size:var(--font-size--smaller);font-weight:500}.traffic-boost-links .links-pagination .page-selector select:focus{outline:2px solid var(--wp-admin-theme-color);outline-offset:1px}.traffic-boost-links .links-pagination .page-navigation{display:flex;gap:var(--grid-unit-5);margin-left:var(--grid-unit-30)}.traffic-boost-links .traffic-boost-links-list-loading{align-items:center;display:flex;gap:var(--grid-unit-10);height:100%;justify-content:center;padding:var(--grid-unit-20)} +#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.traffic-boost-sidebar{align-items:flex-start;background:var(--white);border-bottom:1px solid var(--gray-200);border-radius:var(--grid-unit-10);box-shadow:0 1px 1px 0 rgba(0,0,0,.03),0 1px 2px 0 rgba(0,0,0,.02),0 .1875rem .1875rem 0 rgba(0,0,0,.02),0 .25rem .25rem 0 rgba(0,0,0,.01);display:flex;flex-direction:column;height:calc(100vh - 4.0625rem);max-width:28.125rem;min-width:20rem}.traffic-boost-sidebar .traffic-boost-sidebar-header{align-items:center;align-self:stretch;background:var(--traffic-boost-header-background);display:flex;flex-direction:column;gap:var(--grid-unit-20);min-height:var(--grid-unit-50);padding:var(--grid-unit-20) var(--grid-unit-30)}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-sidebar-header-nav{align-items:center;align-self:stretch;display:flex;justify-content:space-between}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-sidebar-header-nav .components-button{font-size:var(--font-size--medium);font-weight:400;line-height:var(--grid-unit-25);padding-left:0;padding-right:0}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10);justify-content:flex-end}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-label{color:var(--gray-900);font-size:var(--font-size--small);font-style:normal;font-weight:500;line-height:var(--grid-unit-20);overflow:hidden;text-transform:uppercase}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-content{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-10)}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-content .post-title{color:var(--gray-900);font-size:var(--font-size--large);font-style:normal;font-weight:500;line-height:var(--grid-unit-25)}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-divider{background:var(--gray-400);height:1px;margin:var(--grid-unit-10) 0;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-header .traffic-boost-post-details .traffic-boost-post-details-description{font-size:var(--font-size--medium);font-style:normal;font-weight:400;line-height:var(--grid-unit-20)}.traffic-boost-sidebar .traffic-boost-sidebar-content{display:flex;flex:1;flex-direction:column;gap:var(--grid-unit-20);min-height:0;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-settings .components-panel__body{border-bottom:0;border-top:0}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-empty-state{align-items:center;display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:var(--grid-unit-20)}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-generating-footer{align-items:center;display:flex;gap:var(--grid-unit-10);justify-content:center;min-height:2.25rem;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-content .traffic-boost-suggestions-generating-footer span{margin-top:.3125rem}.traffic-boost-sidebar .traffic-boost-sidebar-tabs{display:flex;flex:1;flex-direction:column;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tab-content{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs{border-bottom:1px solid var(--gray-400);border-top:1px solid var(--gray-400);display:flex;margin:0;padding:0;position:relative;width:100%}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item{flex:1;height:var(--grid-unit-60);justify-content:center;margin:0;padding:var(--grid-unit-15)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.is-active{box-shadow:inset 0 0 0 var(--wp-admin-border-width-focus) transparent,inset 0 -1.5px 0 0 var(--wp-admin-theme-color)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item .tab-count{align-items:center;background:var(--gray-400);border-radius:2px;display:inline-flex;gap:var(--grid-unit-10);justify-content:center;margin-left:var(--grid-unit-20);padding:var(--grid-unit-5) var(--grid-unit-10)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab{flex:0 0 var(--grid-unit-50);justify-content:center!important;min-width:var(--grid-unit-60)!important;padding:var(--grid-unit-10)!important;width:var(--grid-unit-60)!important}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab .icon{color:var(--gray-600);height:var(--grid-unit-30)!important;width:var(--grid-unit-30)!important}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab .icon svg{height:var(--grid-unit-30)!important;width:var(--grid-unit-30)!important}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item.icon-only-tab:hover .icon{color:var(--gray-900)}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item .suggestions-tab{order:1}.traffic-boost-sidebar .traffic-boost-sidebar-tabs .components-tab-panel__tabs .components-tab-panel__tabs-item .inbound-links-tab{order:2}.traffic-boost-sidebar .traffic-boost-suggestions-loading-generating{align-items:center;display:flex;flex-direction:column;gap:var(--grid-unit-15);height:100%;justify-content:center;padding:var(--grid-unit-20)}.wp-parsely-traffic-boost-add-new-link-popover{width:25rem}.wp-parsely-traffic-boost-add-new-link-popover .components-popover__content{display:flex;flex-direction:column;gap:var(--grid-unit-20);padding:var(--grid-unit-20);width:100%}.wp-parsely-traffic-boost-add-new-link-popover .traffic-boost-add-link-table.no-results{text-align:left}.wp-parsely-traffic-boost-add-new-link-popover .traffic-boost-add-link-table tr{cursor:pointer} +.parsely-tone-selector-dropdown{align-items:center;align-self:stretch;background:var(--Gutenberg-White,#fff);border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-tone-selector-dropdown button{height:2.0625rem}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-tone-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-tone-selector-dropdown .components-dropdown-menu__toggle svg:first-of-type path{transform:scale(1.4);transform-origin:center}.parsely-tone-selector-dropdown .parsely-tone-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:left}.parsely-tone-selector-dropdown .parsely-tone-selector-label:first-letter{text-transform:uppercase}.parsely-persona-selector-custom{width:100%}.parsely-persona-selector-custom .components-base-control__field input{display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-persona-selector-custom .components-base-control__field input,.parsely-persona-selector-dropdown{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px}.parsely-persona-selector-dropdown{background:var(--Gutenberg-White,#fff);height:2.25rem;overflow-wrap:break-word;width:100%;word-break:break-word}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle.has-icon svg:first-child{display:none}.parsely-persona-selector-dropdown button{height:2.0625rem}.parsely-persona-selector-dropdown.is-disabled{opacity:.5;pointer-events:none}.parsely-persona-selector-dropdown .components-dropdown-menu__toggle{display:flex;gap:.625rem;width:100%}.parsely-persona-selector-dropdown .parsely-persona-selector-label{flex-grow:2;padding:0 var(--grid-unit-10);text-align:left}.parsely-persona-selector-dropdown .parsely-persona-selector-label:first-letter{text-transform:uppercase}.parsely-tone-selector-custom{width:100%}.parsely-tone-selector-custom .components-base-control__field input{align-items:center;align-self:stretch;border:1px solid var(--Gutenberg-Gray-600,#949494);border-radius:2px;display:flex;height:2.5rem;padding:var(--grid-unit-15) var(--grid-unit-20)}.parsely-inputrange-control{align-items:flex-start;align-self:stretch;display:flex;flex-direction:column;gap:var(--grid-unit-10)}.parsely-inputrange-control .parsely-inputrange-control__label{margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls{align-items:center;align-self:stretch;display:flex;gap:var(--grid-unit-20);height:2.5rem}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control{display:flex;flex:1 0 0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-inner-spin-button,.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control input[type=number]{-moz-appearance:textfield}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-base-control__field{flex-grow:1}.parsely-inputrange-control .parsely-inputrange-control__controls .components-input-control .components-input-control__suffix{color:var(--wp-components-color-accent,var(--wp-admin-theme-color,#3858e9))}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control{flex:1 0 0;height:36px}.parsely-inputrange-control .parsely-inputrange-control__controls .components-range-control .components-range-control__root{height:2.5rem}#wp-parsely-dashboard-widget,.components-button[aria-controls="wp-parsely-block-editor-sidebar:wp-parsely-content-helper"],.editor-post-excerpt,.parsely-dashboard-container,.settings_page_parsely,.wp-parsely-block-overlay,.wp-parsely-content-helper,.wp-parsely-excerpt-generator,.wp-parsely-panel,.wp-parsely-popover,.wp-parsely-preview-editor,.wp-parsely-smart-linking-close-dialog,.wp-parsely-smart-linking-review-modal,.wp-parsely-suggested-title-modal,.wp-parsely-traffic-boost-add-new-link-popover,.wp-parsely-traffic-boost-preview-settings-popover{--base-font:"source-sans-pro",arial,sans-serif;--numeric-font:"ff-din-round-web",sans-serif;--parsely-green-components:107,42%,46%;--parsely-green:hsl(var(--parsely-green-components));--parsely-green-10:#c7ecb1;--parsely-green-65:#2a691b;--gray-200:#f7f8f9;--gray-300:#edeeef;--gray-400:#d7dbdf;--gray-500:#959da5;--gray-600:#586069;--gray-700:#444d56;--gray-900:#24292e;--blue-500:#44a8e5;--blue-550:#2596db;--green-500:#7bc01b;--green-900:#3d6307;--ref-direct:205,13%,52%;--ref-internal:161,91%,41%;--ref-social:210,72%,41%;--ref-search:42,100%,50%;--ref-other:3,76%,58%;--base-text:var(--gray-900);--base-text-2:var(--gray-600);--base-3:var(--gray-400);--border:var(--gray-400);--data:var(--green-500);--control:var(--blue-500);--grid-unit-5:0.25rem;--grid-unit-10:0.5rem;--grid-unit-15:0.75rem;--grid-unit-20:1rem;--grid-unit-25:1.25rem;--grid-unit-30:1.5rem;--grid-unit-40:2rem;--grid-unit-50:2.5rem;--grid-unit-60:3rem;--font-size--smaller:0.688rem;--font-size--small:0.75rem;--font-size--medium:0.875rem;--font-size--large:1rem;--font-size--extra-large:1.2rem;--font-size--bigger:2rem;--dashboard-width:64rem;--black:#000;--dashboard-accent:#b9f16b;--gray-350:#e1e3e5;--sidebar-black:#1e1e1e;--sidebar-white:#f0f0f0;--traffic-boost-header-background:rgba(56,88,233,.08);--white:#fff}.parsely-thumbnail{border-radius:3px;flex-shrink:0;overflow:hidden}.parsely-thumbnail img{border-radius:3px;height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.parsely-thumbnail .parsely-thumbnail-icon-container{align-items:center;background:var(--gray-500);border-radius:3px;display:flex;height:100%;justify-content:center;width:100%}.parsely-thumbnail .parsely-thumbnail-icon-container svg{fill:var(--sidebar-white);height:60%;width:60%}.wp-parsely-snackbar-notices{bottom:4rem;display:flex;flex-direction:column-reverse;gap:.375rem;padding:1rem;position:fixed;width:100%;z-index:999999}.wp-parsely-snackbar-notices svg{fill:currentcolor}.wp-parsely-loading{align-items:center;border-radius:.25rem;color:var(--sidebar-black);display:flex;gap:var(--grid-unit-20);justify-content:center;min-height:1.5rem;min-width:25rem;padding:var(--grid-unit-10) var(--grid-unit-15)}.wp-parsely-loading .components-spinner{flex-shrink:0;margin:0}.wp-parsely-loading .wp-parsely-loading-message{flex-grow:1;font-size:var(--font-size--medium);line-height:1.4;margin:0;max-width:25rem}.wp-parsely-loading .wp-parsely-typewriter-text{display:inline-block;min-height:1.4em;min-width:1ch}.wp-parsely-loading .wp-parsely-typewriter-cursor{animation:blink 1s step-end infinite;display:inline-block;font-weight:400;margin-left:2px;opacity:.7}@keyframes blink{0%,to{opacity:0}50%{opacity:1}}.parsely-panel-settings{width:100%}.parsely-panel-settings .parsely-panel-settings-header{display:flex;margin:.625rem 0;width:100%}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label{flex-grow:2;margin:0 0 0 .3125rem;text-align:left}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field{align-items:center;display:flex;justify-content:space-between}.parsely-panel-settings .parsely-panel-settings-header .parsely-panel-settings-header-label .components-base-control__field .components-base-control__label{margin-bottom:0}.parsely-panel-settings .parsely-panel-settings-body{align-self:stretch;display:flex;flex-direction:column;gap:.625rem;padding:.375rem 0 var(--grid-unit-20) 0}.wp-parsely-dropdown-label{align-self:stretch;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-style:normal;font-weight:600;line-height:var(--grid-unit-20);text-transform:uppercase}.wp-parsely-content-helper-error{align-self:flex-start;margin:0}.wp-parsely-content-helper-error p{margin:0}.wp-parsely-content-helper-error .content-helper-error-message{margin:0!important}.wp-parsely-collapsible-panel{align-items:flex-start;align-self:stretch;border-bottom:none;border-radius:2px;border-top:none;display:flex;flex-direction:column;gap:var(--grid-unit-20);margin:0 0 .5rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title{align-items:center;align-self:stretch;display:flex;margin:0 -1rem .375rem;padding:0}.wp-parsely-collapsible-panel .components-panel__body-title .components-panel__icon,.wp-parsely-collapsible-panel .components-panel__body-title svg{margin-left:0;margin-right:var(--grid-unit-10);order:-1}.wp-parsely-collapsible-panel .components-panel__body-title:hover{background-color:transparent}.wp-parsely-collapsible-panel.is-opened{padding:0}.wp-parsely-collapsible-panel.is-opened>div:first-of-type{margin-top:calc(var(--grid-unit-20)*-1)}.wp-parsely-collapsible-panel.is-opened .components-panel__body-title{margin:0 calc(var(--grid-unit-20)*-1) .375rem;padding-bottom:0}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button{color:var(--Gutenberg-Gray-900,#1e1e1e);font-size:.6875rem;font-style:normal;font-weight:600;line-height:1rem;padding:var(--grid-unit-20) var(--grid-unit-20);text-transform:uppercase}.wp-parsely-collapsible-panel .components-panel__body-toggle.components-button .components-panel__arrow{margin-right:0}.wp-parsely-collapsible-panel .components-panel__body.is-opened{padding:0}.parsely-table-container.is-loading{align-items:center;display:flex;justify-content:center;padding:var(--grid-unit-20)}.parsely-table-container table{border-collapse:collapse;border-spacing:0;width:100%}.parsely-table-container table tr{position:relative}.parsely-table-container table tr:after{background-color:var(--border);bottom:0;content:"";height:1px;left:50%;position:absolute;transform:translateX(-50%);width:100vw}.parsely-table-container table tr td,.parsely-table-container table tr th{padding:var(--grid-unit-15) 0}.parsely-table-container table tr td.post-info,.parsely-table-container table tr th.post-info-header{text-align:left}.parsely-table-container table tr th{color:var(--sidebar-black);font-size:var(--font-size--small);font-style:normal;font-weight:600;line-height:var(--font-size--large);text-transform:uppercase}.parsely-table-container table tr th.views-header{min-width:3.75rem;text-align:center}.parsely-table-container table tr th.views-header .views-header-period{color:var(--gray-500);font-size:var(--font-size--smaller);font-weight:400;margin-left:var(--grid-unit-5)}.parsely-table-container table tr td.metrics{min-width:100px}.parsely-table-container table tr td.metrics .metrics-container{align-items:center;display:flex;flex-direction:column;gap:var(--grid-unit-5)}.parsely-table-container table tr td.metrics .metrics-container .metric-change{font-size:var(--font-size--small);font-weight:600;line-height:var(--font-size--large);margin-left:var(--grid-unit-5)}.parsely-table-container table tr td.metrics .metrics-container .metric-change-positive{color:var(--parsely-green)}.parsely-table-container table tr td.metrics .metrics-container .metric-change-negative{color:#900000}.parsely-table-container table tr td.metrics .metrics-container .metric-change-neutral{color:var(--gray-500)}.parsely-table-container table tr td.metrics .metrics-container .metric-boost-percentage{color:var(--parsely-green);font-size:var(--font-size--small);font-weight:600}.parsely-table-container table tr td.actions{align-items:center;display:flex;gap:var(--grid-unit-10);justify-content:flex-end;margin-left:var(--grid-unit-10);max-width:8.4375rem;min-height:2.5rem}.parsely-table-container table tr td.actions a{text-decoration:none}.parsely-table-container table tr td.actions .boost-link-container{display:flex;flex-direction:column;gap:.25rem;height:100%;text-align:center;width:100%}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status{display:flex;gap:.25rem;justify-content:center}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .hidden{opacity:0}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .boost-inbound,.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .boost-outbound{align-items:center;background-color:var(--gray-300);border-radius:.375rem;color:var(--sidebar-black);display:flex;flex-grow:1;font-size:var(--font-size--small);justify-content:center;line-height:var(--font-size--medium);padding:.25rem .5625rem}.parsely-table-container table tr td.actions .boost-link-container .boost-link-status .boost-link-status-icon-inbound{transform:rotate(180deg)}.parsely-table-container.no-results{color:#757575;font-style:italic;padding:var(--grid-unit-15);text-align:center}.parsely-table-container .suggestion-bubble{background:var(--parsely-green);border:none;border-radius:1.25rem;box-shadow:none;color:var(--sidebar-white);cursor:pointer;display:inline-block;font-size:.8125rem;line-height:.875rem;margin-left:.375rem;min-width:1.75rem;padding:3px .375rem;text-align:center}.parsely-table-container.compact table tr td.post-info{max-width:100px}.parsely-table-container.compact tr:after{width:100%}.parsely-table-container.compact .post-title{display:-webkit-box!important;overflow:hidden;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical}.parsely-table-container.compact .post-title>span{white-space:normal!important}.parsely-table-container.hide-pagination table tr:last-child:after{display:none}.posts-table-post-info{align-items:flex-start;display:flex;flex:1 0 0;gap:var(--grid-unit-20);min-height:2.5rem}.posts-table-post-info .posts-table-thumbnail{align-self:center}.posts-table-post-info .post-details{align-items:flex-start;display:flex;flex:1 0 0;flex-direction:column;gap:var(--grid-unit-05,4px);justify-content:center;min-height:var(--grid-unit-40);min-width:0}.posts-table-post-info .post-details .post-title{align-items:center;align-self:stretch;display:flex;font-size:var(--font-size--medium);font-style:normal;font-weight:600;gap:var(--grid-unit-5);line-height:1.25rem;overflow:hidden;text-overflow:ellipsis}.posts-table-post-info .post-details .post-title>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.posts-table-post-info .post-details .post-meta{align-content:center;align-items:center;align-self:stretch;color:var(--gray-500);display:flex;flex-wrap:wrap;gap:var(--grid-unit-5) var(--grid-unit-10)}.posts-table-post-info .post-details .post-categories{display:flex;gap:var(--grid-unit-5)}.posts-table-post-info .post-details .post-categories span{background:var(--gray-400);border-radius:.375rem;color:var(--sidebar-black);font-size:var(--font-size--smaller);font-weight:500;line-height:var(--font-size--large);padding:2px var(--grid-unit-10)}.posts-table-pagination-controls{align-items:center;align-self:stretch;display:flex;font-size:var(--font-size--smaller);font-style:normal;font-weight:600;gap:var(--grid-unit-30);justify-content:flex-end;line-height:var(--font-size--large);padding:var(--grid-unit-15);text-transform:uppercase}.posts-table-pagination-controls .page-selector{align-items:center;display:flex;gap:var(--grid-unit-10)}.posts-table-pagination-controls .page-navigation{align-items:center;display:flex;gap:var(--grid-unit-5);justify-content:flex-end}body{background:#fff}.parsely-dashboard-container{margin-left:-1.25rem;overflow:hidden}.parsely-dashboard-page-body,.parsely-dashboard-page-header{margin:0 auto;max-width:var(--dashboard-width);padding:var(--grid-unit-30)} diff --git a/build/content-helper/dashboard-page.js b/build/content-helper/dashboard-page.js new file mode 100644 index 0000000000..b1df55ee36 --- /dev/null +++ b/build/content-helper/dashboard-page.js @@ -0,0 +1,9 @@ +!function(){"use strict";var e={69:function(e,t){Object.prototype.toString},20:function(e,t,n){var r=n(609),o=Symbol.for("react.element"),i=Symbol.for("react.fragment"),a=Object.prototype.hasOwnProperty,s=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,n){var r,i={},c=null,u=null;for(r in void 0!==n&&(c=""+n),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)a.call(t,r)&&!l.hasOwnProperty(r)&&(i[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===i[r]&&(i[r]=t[r]);return{$$typeof:o,type:e,key:c,ref:u,props:i,_owner:s.current}}t.Fragment=i,t.jsx=c,t.jsxs=c},848:function(e,t,n){e.exports=n(20)},609:function(e){e.exports=window.React}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e=n(848),t=n(609),r=(n(69),"popstate");function o(e={}){return function(e,t,n,o={}){let{window:a=document.defaultView,v5Compat:u=!1}=o,d=a.history,p="POP",f=null,h=g();function g(){return(d.state||{idx:null}).idx}function v(){p="POP";let e=g(),t=null==e?null:e-h;h=e,f&&f({action:p,location:y.location,delta:t})}function m(e){let t="null"!==a.location.origin?a.location.origin:a.location.href,n="string"==typeof e?e:c(e);return n=n.replace(/ $/,"%20"),i(t,`No window.location.(origin|href) available to create URL for href: ${n}`),new URL(n,t)}null==h&&(h=0,d.replaceState({...d.state,idx:h},""));let y={get action(){return p},get location(){return e(a,d)},listen(e){if(f)throw new Error("A history only accepts one active listener");return a.addEventListener(r,v),f=e,()=>{a.removeEventListener(r,v),f=null}},createHref(e){return t(a,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(e,t){p="PUSH";let r=l(y.location,e,t);n&&n(r,e),h=g()+1;let o=s(r,h),i=y.createHref(r);try{d.pushState(o,"",i)}catch(e){if(e instanceof DOMException&&"DataCloneError"===e.name)throw e;a.location.assign(i)}u&&f&&f({action:p,location:y.location,delta:1})},replace:function(e,t){p="REPLACE";let r=l(y.location,e,t);n&&n(r,e),h=g();let o=s(r,h),i=y.createHref(r);d.replaceState(o,"",i),u&&f&&f({action:p,location:y.location,delta:0})},go(e){return d.go(e)}};return y}((function(e,t){let{pathname:n="/",search:r="",hash:o=""}=u(e.location.hash.substring(1));return n.startsWith("/")||n.startsWith(".")||(n="/"+n),l("",{pathname:n,search:r,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){let n=e.document.querySelector("base"),r="";if(n&&n.getAttribute("href")){let t=e.location.href,n=t.indexOf("#");r=-1===n?t:t.slice(0,n)}return r+"#"+("string"==typeof t?t:c(t))}),(function(e,t){a("/"===e.pathname.charAt(0),`relative pathnames are not supported in hash history.push(${JSON.stringify(t)})`)}),e)}function i(e,t){if(!1===e||null==e)throw new Error(t)}function a(e,t){if(!e){"undefined"!=typeof console&&console.warn(t);try{throw new Error(t)}catch(e){}}}function s(e,t){return{usr:e.state,key:e.key,idx:t}}function l(e,t,n=null,r){return{pathname:"string"==typeof e?e:e.pathname,search:"",hash:"",..."string"==typeof t?u(t):t,state:n,key:t&&t.key||r||Math.random().toString(36).substring(2,10)}}function c({pathname:e="/",search:t="",hash:n=""}){return t&&"?"!==t&&(e+="?"===t.charAt(0)?t:"?"+t),n&&"#"!==n&&(e+="#"===n.charAt(0)?n:"#"+n),e}function u(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function d(e,t,n="/"){return function(e,t,n,r){let o=E(("string"==typeof t?u(t):t).pathname||"/",n);if(null==o)return null;let i=p(e);!function(e){e.sort(((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){return e.length===t.length&&e.slice(0,-1).every(((e,n)=>e===t[n]))?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map((e=>e.childrenIndex)),t.routesMeta.map((e=>e.childrenIndex)))))}(i);let a=null;for(let e=0;null==a&&e{let s={relativePath:void 0===a?e.path||"":a,caseSensitive:!0===e.caseSensitive,childrenIndex:o,route:e};s.relativePath.startsWith("/")&&(i(s.relativePath.startsWith(r),`Absolute route path "${s.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),s.relativePath=s.relativePath.slice(r.length));let l=T([r,s.relativePath]),c=n.concat(s);e.children&&e.children.length>0&&(i(!0!==e.index,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),p(e.children,t,c,l)),(null!=e.path||e.index)&&t.push({path:l,score:x(l,e.index),routesMeta:c})};return e.forEach(((e,t)=>{if(""!==e.path&&e.path?.includes("?"))for(let n of f(e.path))o(e,t,n);else o(e,t)})),t}function f(e){let t=e.split("/");if(0===t.length)return[];let[n,...r]=t,o=n.endsWith("?"),i=n.replace(/\?$/,"");if(0===r.length)return o?[i,""]:[i];let a=f(r.join("/")),s=[];return s.push(...a.map((e=>""===e?i:[i,e].join("/")))),o&&s.push(...a),s.map((t=>e.startsWith("/")&&""===t?"/":t))}new WeakMap;var h=/^:[\w-]+$/,g=3,v=2,m=1,y=10,b=-2,w=e=>"*"===e;function x(e,t){let n=e.split("/"),r=n.length;return n.some(w)&&(r+=b),t&&(r+=v),n.filter((e=>!w(e))).reduce(((e,t)=>e+(h.test(t)?g:""===t?m:y)),r)}function k(e,t,n=!1){let{routesMeta:r}=e,o={},i="/",a=[];for(let e=0;e(r.push({paramName:t,isOptional:null!=n}),n?"/?([^\\/]+)?":"/([^\\/]+)")));return e.endsWith("*")?(r.push({paramName:"*"}),o+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?o+="\\/*$":""!==e&&"/"!==e&&(o+="(?:(?=\\/|$))"),[new RegExp(o,t?void 0:"i"),r]}(e.path,e.caseSensitive,e.end),o=t.match(n);if(!o)return null;let i=o[0],s=i.replace(/(.)\/+$/,"$1"),l=o.slice(1);return{params:r.reduce(((e,{paramName:t,isOptional:n},r)=>{if("*"===t){let e=l[r]||"";s=i.slice(0,i.length-e.length).replace(/(.)\/+$/,"$1")}const o=l[r];return e[t]=n&&!o?void 0:(o||"").replace(/%2F/g,"/"),e}),{}),pathname:i,pathnameBase:s,pattern:e}}function S(e){try{return e.split("/").map((e=>decodeURIComponent(e).replace(/\//g,"%2F"))).join("/")}catch(t){return a(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function E(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&"/"!==r?null:e.slice(n)||"/"}function P(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function L(e){let t=function(e){return e.filter(((e,t)=>0===t||e.route.path&&e.route.path.length>0))}(e);return t.map(((e,n)=>n===t.length-1?e.pathname:e.pathnameBase))}function j(e,t,n,r=!1){let o;"string"==typeof e?o=u(e):(o={...e},i(!o.pathname||!o.pathname.includes("?"),P("?","pathname","search",o)),i(!o.pathname||!o.pathname.includes("#"),P("#","pathname","hash",o)),i(!o.search||!o.search.includes("#"),P("#","search","hash",o)));let a,s=""===e||""===o.pathname,l=s?"/":o.pathname;if(null==l)a=n;else{let e=t.length-1;if(!r&&l.startsWith("..")){let t=l.split("/");for(;".."===t[0];)t.shift(),e-=1;o.pathname=t.join("/")}a=e>=0?t[e]:"/"}let c=function(e,t="/"){let{pathname:n,search:r="",hash:o=""}="string"==typeof e?u(e):e,i=n?n.startsWith("/")?n:function(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach((e=>{".."===e?n.length>1&&n.pop():"."!==e&&n.push(e)})),n.length>1?n.join("/"):"/"}(n,t):t;return{pathname:i,search:C(r),hash:I(o)}}(o,a),d=l&&"/"!==l&&l.endsWith("/"),p=(s||"."===l)&&n.endsWith("/");return c.pathname.endsWith("/")||!d&&!p||(c.pathname+="/"),c}var T=e=>e.join("/").replace(/\/\/+/g,"/"),N=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),C=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",I=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";function A(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"boolean"==typeof e.internal&&"data"in e}var R=["POST","PUT","PATCH","DELETE"],O=(new Set(R),["GET",...R]);new Set(O),Symbol("ResetLoaderData");var D=t.createContext(null);D.displayName="DataRouter";var G=t.createContext(null);G.displayName="DataRouterState";var B=t.createContext({isTransitioning:!1});B.displayName="ViewTransition",t.createContext(new Map).displayName="Fetchers",t.createContext(null).displayName="Await";var M=t.createContext(null);M.displayName="Navigation";var F=t.createContext(null);F.displayName="Location";var U=t.createContext({outlet:null,matches:[],isDataRoute:!1});U.displayName="Route";var H=t.createContext(null);function V(){return null!=t.useContext(F)}function $(){return i(V(),"useLocation() may be used only in the context of a component."),t.useContext(F).location}H.displayName="RouteError";var W="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function z(e){t.useContext(M).static||t.useLayoutEffect(e)}function q(){let{isDataRoute:e}=t.useContext(U);return e?function(){let{router:e}=function(e){let n=t.useContext(D);return i(n,ee(e)),n}("useNavigate"),n=te("useNavigate"),r=t.useRef(!1);return z((()=>{r.current=!0})),t.useCallback((async(t,o={})=>{a(r.current,W),r.current&&("number"==typeof t?e.navigate(t):await e.navigate(t,{fromRouteId:n,...o}))}),[e,n])}():function(){i(V(),"useNavigate() may be used only in the context of a component.");let e=t.useContext(D),{basename:n,navigator:r}=t.useContext(M),{matches:o}=t.useContext(U),{pathname:s}=$(),l=JSON.stringify(L(o)),c=t.useRef(!1);return z((()=>{c.current=!0})),t.useCallback(((t,o={})=>{if(a(c.current,W),!c.current)return;if("number"==typeof t)return void r.go(t);let i=j(t,JSON.parse(l),s,"path"===o.relative);null==e&&"/"!==n&&(i.pathname="/"===i.pathname?n:T([n,i.pathname])),(o.replace?r.replace:r.push)(i,o.state,o)}),[n,r,l,s,e])}()}function K(e,{relative:n}={}){let{matches:r}=t.useContext(U),{pathname:o}=$(),i=JSON.stringify(L(r));return t.useMemo((()=>j(e,JSON.parse(i),o,"path"===n)),[e,i,o,n])}function Z(e,n,r,o){i(V(),"useRoutes() may be used only in the context of a component.");let{navigator:s,static:l}=t.useContext(M),{matches:c}=t.useContext(U),p=c[c.length-1],f=p?p.params:{},h=p?p.pathname:"/",g=p?p.pathnameBase:"/",v=p&&p.route;{let e=v&&v.path||"";re(h,!v||e.endsWith("*")||e.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${h}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.\n\nPlease change the parent to .`)}let m,y=$();if(n){let e="string"==typeof n?u(n):n;i("/"===g||e.pathname?.startsWith(g),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${g}" but pathname "${e.pathname}" was given in the \`location\` prop.`),m=e}else m=y;let b=m.pathname||"/",w=b;if("/"!==g){let e=g.replace(/^\//,"").split("/");w="/"+b.replace(/^\//,"").split("/").slice(e.length).join("/")}let x=!l&&r&&r.matches&&r.matches.length>0?r.matches:d(e,{pathname:w});a(v||null!=x,`No routes matched location "${m.pathname}${m.search}${m.hash}" `),a(null==x||void 0!==x[x.length-1].route.element||void 0!==x[x.length-1].route.Component||void 0!==x[x.length-1].route.lazy,`Matched leaf route at location "${m.pathname}${m.search}${m.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let k=function(e,n=[],r=null){if(null==e){if(!r)return null;if(r.errors)e=r.matches;else{if(0!==n.length||r.initialized||!(r.matches.length>0))return null;e=r.matches}}let o=e,a=r?.errors;if(null!=a){let e=o.findIndex((e=>e.route.id&&void 0!==a?.[e.route.id]));i(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(a).join(",")}`),o=o.slice(0,Math.min(o.length,e+1))}let s=!1,l=-1;if(r)for(let e=0;e=0?o.slice(0,l+1):[o[0]];break}}}return o.reduceRight(((e,i,c)=>{let u,d=!1,p=null,f=null;r&&(u=a&&i.route.id?a[i.route.id]:void 0,p=i.route.errorElement||J,s&&(l<0&&0===c?(re("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,f=null):l===c&&(d=!0,f=i.route.hydrateFallbackElement||null)));let h=n.concat(o.slice(0,c+1)),g=()=>{let n;return n=u?p:d?f:i.route.Component?t.createElement(i.route.Component,null):i.route.element?i.route.element:e,t.createElement(X,{match:i,routeContext:{outlet:e,matches:h,isDataRoute:null!=r},children:n})};return r&&(i.route.ErrorBoundary||i.route.errorElement||0===c)?t.createElement(Q,{location:r.location,revalidation:r.revalidation,component:p,error:u,children:g(),routeContext:{outlet:null,matches:h,isDataRoute:!0}}):g()}),null)}(x&&x.map((e=>Object.assign({},e,{params:Object.assign({},f,e.params),pathname:T([g,s.encodeLocation?s.encodeLocation(e.pathname).pathname:e.pathname]),pathnameBase:"/"===e.pathnameBase?g:T([g,s.encodeLocation?s.encodeLocation(e.pathnameBase).pathname:e.pathnameBase])}))),c,r,o);return n&&k?t.createElement(F.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...m},navigationType:"POP"}},k):k}function Y(){let e=function(){let e=t.useContext(H),n=function(e){let n=t.useContext(G);return i(n,ee(e)),n}("useRouteError"),r=te("useRouteError");return void 0!==e?e:n.errors?.[r]}(),n=A(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),r=e instanceof Error?e.stack:null,o="rgba(200,200,200, 0.5)",a={padding:"0.5rem",backgroundColor:o},s={padding:"2px 4px",backgroundColor:o},l=null;return console.error("Error handled by React Router default ErrorBoundary:",e),l=t.createElement(t.Fragment,null,t.createElement("p",null,"💿 Hey developer 👋"),t.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",t.createElement("code",{style:s},"ErrorBoundary")," or"," ",t.createElement("code",{style:s},"errorElement")," prop on your route.")),t.createElement(t.Fragment,null,t.createElement("h2",null,"Unexpected Application Error!"),t.createElement("h3",{style:{fontStyle:"italic"}},n),r?t.createElement("pre",{style:a},r):null,l)}t.createContext(null);var J=t.createElement(Y,null),Q=class extends t.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||"idle"!==t.revalidation&&"idle"===e.revalidation?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:void 0!==e.error?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){console.error("React Router caught the following error during render",e,t)}render(){return void 0!==this.state.error?t.createElement(U.Provider,{value:this.props.routeContext},t.createElement(H.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function X({routeContext:e,match:n,children:r}){let o=t.useContext(D);return o&&o.static&&o.staticContext&&(n.route.errorElement||n.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=n.route.id),t.createElement(U.Provider,{value:e},r)}function ee(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function te(e){let n=function(e){let n=t.useContext(U);return i(n,ee(e)),n}(e),r=n.matches[n.matches.length-1];return i(r.route.id,`${e} can only be used on routes that contain a unique "id"`),r.route.id}var ne={};function re(e,t,n){t||ne[e]||(ne[e]=!0,a(!1,n))}function oe({to:e,replace:n,state:r,relative:o}){i(V()," may be used only in the context of a component.");let{static:s}=t.useContext(M);a(!s," must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.");let{matches:l}=t.useContext(U),{pathname:c}=$(),u=q(),d=j(e,L(l),c,"path"===o),p=JSON.stringify(d);return t.useEffect((()=>{u(JSON.parse(p),{replace:n,state:r,relative:o})}),[u,p,o,n,r]),null}function ie(e){i(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function ae({basename:e="/",children:n=null,location:r,navigationType:o="POP",navigator:s,static:l=!1}){i(!V(),"You cannot render a inside another . You should never have more than one in your app.");let c=e.replace(/^\/*/,"/"),d=t.useMemo((()=>({basename:c,navigator:s,static:l,future:{}})),[c,s,l]);"string"==typeof r&&(r=u(r));let{pathname:p="/",search:f="",hash:h="",state:g=null,key:v="default"}=r,m=t.useMemo((()=>{let e=E(p,c);return null==e?null:{location:{pathname:e,search:f,hash:h,state:g,key:v},navigationType:o}}),[c,p,f,h,g,v,o]);return a(null!=m,` is not able to match the URL "${p}${f}${h}" because it does not start with the basename, so the won't render anything.`),null==m?null:t.createElement(M.Provider,{value:d},t.createElement(F.Provider,{children:n,value:m}))}function se({children:e,location:t}){return Z(le(e),t)}function le(e,n=[]){let r=[];return t.Children.forEach(e,((e,o)=>{if(!t.isValidElement(e))return;let a=[...n,o];if(e.type===t.Fragment)return void r.push.apply(r,le(e.props.children,a));i(e.type===ie,`[${"string"==typeof e.type?e.type:e.type.name}] is not a component. All component children of must be a or `),i(!e.props.index||!e.props.children,"An index route cannot have child routes.");let s={id:e.props.id||a.join("-"),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:!0===e.props.hasErrorBoundary||null!=e.props.ErrorBoundary||null!=e.props.errorElement,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(s.children=le(e.props.children,a)),r.push(s)})),r}t.memo((function({routes:e,future:t,state:n}){return Z(e,void 0,n,t)})),t.Component;var ce="get",ue="application/x-www-form-urlencoded";function de(e){return null!=e&&"string"==typeof e.tagName}var pe=null,fe=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function he(e){return null==e||fe.has(e)?e:(a(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${ue}"`),null)}function ge(e,t){if(!1===e||null==e)throw new Error(t)}function ve(e){return null!=e&&(null==e.href?"preload"===e.rel&&"string"==typeof e.imageSrcSet&&"string"==typeof e.imageSizes:"string"==typeof e.rel&&"string"==typeof e.href)}function me(e,t,n,r,o,i){let a=(e,t)=>!n[t]||e.route.id!==n[t].route.id,s=(e,t)=>n[t].pathname!==e.pathname||n[t].route.path?.endsWith("*")&&n[t].params["*"]!==e.params["*"];return"assets"===i?t.filter(((e,t)=>a(e,t)||s(e,t))):"data"===i?t.filter(((t,i)=>{let l=r.routes[t.route.id];if(!l||!l.hasLoader)return!1;if(a(t,i)||s(t,i))return!0;if(t.route.shouldRevalidate){let r=t.route.shouldRevalidate({currentUrl:new URL(o.pathname+o.search+o.hash,window.origin),currentParams:n[0]?.params||{},nextUrl:new URL(e,window.origin),nextParams:t.params,defaultShouldRevalidate:!0});if("boolean"==typeof r)return r}return!0})):[]}function ye(e,t,{includeHydrateFallback:n}={}){return r=e.map((e=>{let r=t.routes[e.route.id];if(!r)return[];let o=[r.module];return r.clientActionModule&&(o=o.concat(r.clientActionModule)),r.clientLoaderModule&&(o=o.concat(r.clientLoaderModule)),n&&r.hydrateFallbackModule&&(o=o.concat(r.hydrateFallbackModule)),r.imports&&(o=o.concat(r.imports)),o})).flat(1),[...new Set(r)];var r}Symbol("SingleFetchRedirect");function be(){let e=t.useContext(D);return ge(e,"You must render this element inside a element"),e}function we(){let e=t.useContext(G);return ge(e,"You must render this element inside a element"),e}t.Component;var xe=t.createContext(void 0);function ke(){let e=t.useContext(xe);return ge(e,"You must render this element inside a element"),e}function _e(e,t){return n=>{e&&e(n),n.defaultPrevented||t(n)}}function Se({page:e,...n}){let{router:r}=be(),o=t.useMemo((()=>d(r.routes,e,r.basename)),[r.routes,e,r.basename]);return o?t.createElement(Pe,{page:e,matches:o,...n}):null}function Ee(e){let{manifest:n,routeModules:r}=ke(),[o,i]=t.useState([]);return t.useEffect((()=>{let t=!1;return async function(e,t,n){return function(e,t){let n=new Set,r=new Set(t);return e.reduce(((e,o)=>{if(t&&(null==(i=o)||"string"!=typeof i.page)&&"script"===o.as&&o.href&&r.has(o.href))return e;var i;let a=JSON.stringify(function(e){let t={},n=Object.keys(e).sort();for(let r of n)t[r]=e[r];return t}(o));return n.has(a)||(n.add(a),e.push({key:a,link:o})),e}),[])}((await Promise.all(e.map((async e=>{let r=t.routes[e.route.id];if(r){let e=await async function(e,t){if(e.id in t)return t[e.id];try{let n=await import(e.module);return t[e.id]=n,n}catch(t){return console.error(`Error loading route module \`${e.module}\`, reloading page...`),console.error(t),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise((()=>{}))}}(r,n);return e.links?e.links():[]}return[]})))).flat(1).filter(ve).filter((e=>"stylesheet"===e.rel||"preload"===e.rel)).map((e=>"stylesheet"===e.rel?{...e,rel:"prefetch",as:"style"}:{...e,rel:"prefetch"})))}(e,n,r).then((e=>{t||i(e)})),()=>{t=!0}}),[e,n,r]),o}function Pe({page:e,matches:n,...r}){let o=$(),{manifest:i,routeModules:a}=ke(),{basename:s}=be(),{loaderData:l,matches:c}=we(),u=t.useMemo((()=>me(e,n,c,i,o,"data")),[e,n,c,i,o]),d=t.useMemo((()=>me(e,n,c,i,o,"assets")),[e,n,c,i,o]),p=t.useMemo((()=>{if(e===o.pathname+o.search+o.hash)return[];let t=new Set,r=!1;if(n.forEach((e=>{let n=i.routes[e.route.id];n&&n.hasLoader&&(!u.some((t=>t.route.id===e.route.id))&&e.route.id in l&&a[e.route.id]?.shouldRevalidate||n.hasClientLoader?r=!0:t.add(e.route.id))})),0===t.size)return[];let c=function(e,t){let n="string"==typeof e?new URL(e,"undefined"==typeof window?"server://singlefetch/":window.location.origin):e;return"/"===n.pathname?n.pathname="_root.data":t&&"/"===E(n.pathname,t)?n.pathname=`${t.replace(/\/$/,"")}/_root.data`:n.pathname=`${n.pathname.replace(/\/$/,"")}.data`,n}(e,s);return r&&t.size>0&&c.searchParams.set("_routes",n.filter((e=>t.has(e.route.id))).map((e=>e.route.id)).join(",")),[c.pathname+c.search]}),[s,l,o,i,u,n,e,a]),f=t.useMemo((()=>ye(d,i)),[d,i]),h=Ee(d);return t.createElement(t.Fragment,null,p.map((e=>t.createElement("link",{key:e,rel:"prefetch",as:"fetch",href:e,...r}))),f.map((e=>t.createElement("link",{key:e,rel:"modulepreload",href:e,...r}))),h.map((({key:e,link:n})=>t.createElement("link",{key:e,...n}))))}xe.displayName="FrameworkContext";function Le(...e){return t=>{e.forEach((e=>{"function"==typeof e?e(t):null!=e&&(e.current=t)}))}}var je="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement;try{je&&(window.__reactRouterVersion="7.5.2")}catch(e){}function Te({basename:e,children:n,window:r}){let i=t.useRef();null==i.current&&(i.current=o({window:r,v5Compat:!0}));let a=i.current,[s,l]=t.useState({action:a.action,location:a.location}),c=t.useCallback((e=>{t.startTransition((()=>l(e)))}),[l]);return t.useLayoutEffect((()=>a.listen(c)),[a,c]),t.createElement(ae,{basename:e,children:n,location:s.location,navigationType:s.action,navigator:a})}var Ne=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Ce=t.forwardRef((function({onClick:e,discover:n="render",prefetch:r="none",relative:o,reloadDocument:s,replace:l,state:u,target:d,to:p,preventScrollReset:f,viewTransition:h,...g},v){let m,{basename:y}=t.useContext(M),b="string"==typeof p&&Ne.test(p),w=!1;if("string"==typeof p&&b&&(m=p,je))try{let e=new URL(window.location.href),t=p.startsWith("//")?new URL(e.protocol+p):new URL(p),n=E(t.pathname,y);t.origin===e.origin&&null!=n?p=n+t.search+t.hash:w=!0}catch(e){a(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}let x=function(e,{relative:n}={}){i(V(),"useHref() may be used only in the context of a component.");let{basename:r,navigator:o}=t.useContext(M),{hash:a,pathname:s,search:l}=K(e,{relative:n}),c=s;return"/"!==r&&(c="/"===s?r:T([r,s])),o.createHref({pathname:c,search:l,hash:a})}(p,{relative:o}),[k,_,S]=function(e,n){let r=t.useContext(xe),[o,i]=t.useState(!1),[a,s]=t.useState(!1),{onFocus:l,onBlur:c,onMouseEnter:u,onMouseLeave:d,onTouchStart:p}=n,f=t.useRef(null);t.useEffect((()=>{if("render"===e&&s(!0),"viewport"===e){let e=new IntersectionObserver((e=>{e.forEach((e=>{s(e.isIntersecting)}))}),{threshold:.5});return f.current&&e.observe(f.current),()=>{e.disconnect()}}}),[e]),t.useEffect((()=>{if(o){let e=setTimeout((()=>{s(!0)}),100);return()=>{clearTimeout(e)}}}),[o]);let h=()=>{i(!0)},g=()=>{i(!1),s(!1)};return r?"intent"!==e?[a,f,{}]:[a,f,{onFocus:_e(l,h),onBlur:_e(c,g),onMouseEnter:_e(u,h),onMouseLeave:_e(d,g),onTouchStart:_e(p,h)}]:[!1,f,{}]}(r,g),P=function(e,{target:n,replace:r,state:o,preventScrollReset:i,relative:a,viewTransition:s}={}){let l=q(),u=$(),d=K(e,{relative:a});return t.useCallback((t=>{if(function(e,t){return!(0!==e.button||t&&"_self"!==t||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e))}(t,n)){t.preventDefault();let n=void 0!==r?r:c(u)===c(d);l(e,{replace:n,state:o,preventScrollReset:i,relative:a,viewTransition:s})}}),[u,l,d,r,o,n,e,i,a,s])}(p,{replace:l,state:u,target:d,preventScrollReset:f,relative:o,viewTransition:h}),L=t.createElement("a",{...g,...S,href:m||x,onClick:w||s?e:function(t){e&&e(t),t.defaultPrevented||P(t)},ref:Le(v,_),target:d,"data-discover":b||"render"!==n?void 0:"true"});return k&&!b?t.createElement(t.Fragment,null,L,t.createElement(Se,{page:x})):L}));function Ie(e){let n=t.useContext(D);return i(n,function(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}(e)),n}Ce.displayName="Link",t.forwardRef((function({"aria-current":e="page",caseSensitive:n=!1,className:r="",end:o=!1,style:a,to:s,viewTransition:l,children:c,...u},d){let p=K(s,{relative:u.relative}),f=$(),h=t.useContext(G),{navigator:g,basename:v}=t.useContext(M),m=null!=h&&function(e,n={}){let r=t.useContext(B);i(null!=r,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:o}=Ie("useViewTransitionState"),a=K(e,{relative:n.relative});if(!r.isTransitioning)return!1;let s=E(r.currentLocation.pathname,o)||r.currentLocation.pathname,l=E(r.nextLocation.pathname,o)||r.nextLocation.pathname;return null!=_(a.pathname,l)||null!=_(a.pathname,s)}(p)&&!0===l,y=g.encodeLocation?g.encodeLocation(p).pathname:p.pathname,b=f.pathname,w=h&&h.navigation&&h.navigation.location?h.navigation.location.pathname:null;n||(b=b.toLowerCase(),w=w?w.toLowerCase():null,y=y.toLowerCase()),w&&v&&(w=E(w,v)||w);const x="/"!==y&&y.endsWith("/")?y.length-1:y.length;let k,S=b===y||!o&&b.startsWith(y)&&"/"===b.charAt(x),P=null!=w&&(w===y||!o&&w.startsWith(y)&&"/"===w.charAt(y.length)),L={isActive:S,isPending:P,isTransitioning:m},j=S?e:void 0;k="function"==typeof r?r(L):[r,S?"active":null,P?"pending":null,m?"transitioning":null].filter(Boolean).join(" ");let T="function"==typeof a?a(L):a;return t.createElement(Ce,{...u,"aria-current":j,className:k,ref:d,style:T,to:s,viewTransition:l},"function"==typeof c?c(L):c)})).displayName="NavLink",t.forwardRef((({discover:e="render",fetcherKey:n,navigate:r,reloadDocument:o,replace:a,state:s,method:l=ce,action:u,onSubmit:d,relative:p,preventScrollReset:f,viewTransition:h,...g},v)=>{let m=function(){let{router:e}=Ie("useSubmit"),{basename:n}=t.useContext(M),r=te("useRouteId");return t.useCallback((async(t,o={})=>{let{action:i,method:a,encType:s,formData:l,body:c}=function(e,t){let n,r,o,i,a;if(de(s=e)&&"form"===s.tagName.toLowerCase()){let a=e.getAttribute("action");r=a?E(a,t):null,n=e.getAttribute("method")||ce,o=he(e.getAttribute("enctype"))||ue,i=new FormData(e)}else if(function(e){return de(e)&&"button"===e.tagName.toLowerCase()}(e)||function(e){return de(e)&&"input"===e.tagName.toLowerCase()}(e)&&("submit"===e.type||"image"===e.type)){let a=e.form;if(null==a)throw new Error('Cannot submit a + + ); +}; diff --git a/src/content-helper/dashboard-page/components/posts-table/style.scss b/src/content-helper/dashboard-page/components/posts-table/style.scss new file mode 100644 index 0000000000..c2769bdafc --- /dev/null +++ b/src/content-helper/dashboard-page/components/posts-table/style.scss @@ -0,0 +1,293 @@ +.parsely-table-container { + &.is-loading { + display: flex; + justify-content: center; + align-items: center; + padding: var(--grid-unit-20); + } + + table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + + tr { + position: relative; + + &::after { + content: ""; + position: absolute; + left: 50%; + transform: translateX(-50%); + width: 100vw; + height: 1px; + background-color: var(--border); + bottom: 0; + } + + th, + td { + padding: var(--grid-unit-15) 0; + } + + td.post-info, + th.post-info-header { + text-align: left; + } + + th { + font-size: var(--font-size--small); + font-weight: 600; + color: var(--sidebar-black); + font-style: normal; + line-height: var(--font-size--large); + text-transform: uppercase; + } + + th.views-header { + text-align: center; + min-width: to_rem(60px); + + .views-header-period { + font-size: var(--font-size--smaller); + font-weight: 400; + color: var(--gray-500); + margin-left: var(--grid-unit-5); + } + } + + td.metrics { + min-width: 100px; + + .metrics-container { + display: flex; + flex-direction: column; + gap: var(--grid-unit-5); + align-items: center; + + .metric-change { + font-size: var(--font-size--small); + font-weight: 600; + line-height: var(--font-size--large); + margin-left: var(--grid-unit-5); + } + + .metric-change-positive { + color: var(--parsely-green); + } + + .metric-change-negative { + color: #900000; + } + + .metric-change-neutral { + color: var(--gray-500); + } + + .metric-boost-percentage { + font-size: var(--font-size--small); + font-weight: 600; + color: var(--parsely-green); + } + } + } + + td.actions { + display: flex; + max-width: to_rem(135px); + min-height: to_rem(40px); + justify-content: flex-end; + align-items: center; + gap: var(--grid-unit-10); + margin-left: var(--grid-unit-10); + + a { + text-decoration: none; + } + + .boost-link-container { + display: flex; + flex-direction: column; + height: 100%; + gap: to_rem(4px); + text-align: center; + width: 100%; + + .boost-link-status { + display: flex; + justify-content: center; + gap: to_rem(4px); + + .hidden { + opacity: 0; + } + + .boost-inbound, + .boost-outbound { + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; + padding: to_rem(4px) to_rem(9px); + border-radius: to_rem(6px); + background-color: var(--gray-300); + font-size: var(--font-size--small); + line-height: var(--font-size--medium); + color: var(--sidebar-black); + } + + .boost-link-status-icon-inbound { + transform: rotate(180deg); + } + } + } + } + } + } + + &.no-results { + padding: var(--grid-unit-15); + text-align: center; + color: #757575; + font-style: italic; + } + + .suggestion-bubble { + background: var(--parsely-green); + border-radius: to_rem(20px); + display: inline-block; + text-align: center; + padding: 3px to_rem(6px); + color: var(--sidebar-white); + cursor: pointer; + margin-left: to_rem(6px); + box-shadow: none; + border: none; + line-height: to_rem(14px); + min-width: to_rem(28px); + font-size: to_rem(13px); + } +} + +.parsely-table-container.compact { + table tr td.post-info { + max-width: 100px; + } + + tr::after { + width: 100%; + } + + .post-title { + overflow: hidden; + display: -webkit-box !important; + -webkit-line-clamp: 2; + line-clamp: 2; + -webkit-box-orient: vertical; + + > span { + white-space: normal !important; + } + } +} + +.parsely-table-container.hide-pagination { + table tr:last-child::after { + display: none; + } +} + +.posts-table-post-info { + display: flex; + min-height: to_rem(40px); + align-items: flex-start; + gap: var(--grid-unit-20); + flex: 1 0 0; + + .posts-table-thumbnail { + align-self: center; + } + + .post-details { + display: flex; + min-height: var(--grid-unit-40); + min-width: 0; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: var(--grid-unit-05, 4px); + flex: 1 0 0; + + .post-title { + display: flex; + align-items: center; + gap: var(--grid-unit-5); + align-self: stretch; + overflow: hidden; + text-overflow: ellipsis; + font-size: var(--font-size--medium); + font-style: normal; + font-weight: 600; + line-height: to_rem(20px); + + > span { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + } + + .post-meta { + display: flex; + align-items: center; + align-content: center; + gap: var(--grid-unit-5) var(--grid-unit-10); + align-self: stretch; + flex-wrap: wrap; + color: var(--gray-500); + } + + .post-categories { + display: flex; + gap: var(--grid-unit-5); + + span { + background: var(--gray-400); + border-radius: to_rem(6px); + padding: 2px var(--grid-unit-10); + font-size: var(--font-size--smaller); + font-weight: 500; + line-height: var(--font-size--large); + color: var(--sidebar-black); + } + } + } +} + +.posts-table-pagination-controls { + display: flex; + padding: var(--grid-unit-15); + justify-content: flex-end; + align-items: center; + gap: var(--grid-unit-30); + align-self: stretch; + + font-size: var(--font-size--smaller); + font-style: normal; + font-weight: 600; + line-height: var(--font-size--large); + text-transform: uppercase; + + .page-selector { + display: flex; + align-items: center; + gap: var(--grid-unit-10); + } + + .page-navigation { + display: flex; + justify-content: flex-end; + align-items: center; + gap: var(--grid-unit-5); + } +} diff --git a/src/content-helper/dashboard-page/components/typography-components.tsx b/src/content-helper/dashboard-page/components/typography-components.tsx new file mode 100644 index 0000000000..5c3589c19c --- /dev/null +++ b/src/content-helper/dashboard-page/components/typography-components.tsx @@ -0,0 +1,35 @@ +/** + * WordPress dependencies + */ +import { __experimentalHeading as Heading } from '@wordpress/components'; +import { HeadingProps } from '@wordpress/components/build-types/heading/types'; + +/** + * The DashboardHeading component. + * + * @since 3.19.0 + */ +export type DashboardHeadingProps = { + children: React.ReactNode; + props?: HeadingProps +}; + +/** + * The DashboardHeading component. + * + * Can be used to render a heading in the dashboard. and it is a + * wrapper around the Heading component from the WordPress components package. + * + * @since 3.19.0 + * + * @param {DashboardHeadingProps} props The component props. + */ +export const DashboardHeading = ( { children, ...props }: DashboardHeadingProps ) => { + return ( + + { children } + + ); +}; diff --git a/src/content-helper/dashboard-page/dashboard-page.scss b/src/content-helper/dashboard-page/dashboard-page.scss new file mode 100644 index 0000000000..4bc817456b --- /dev/null +++ b/src/content-helper/dashboard-page/dashboard-page.scss @@ -0,0 +1,24 @@ +@import "../common/css/variables"; +@import "../common/css/functions"; +@import "../common/css/common"; + +/** + * Import styles for the components in the dashboard page. + */ +@import "./components/posts-table/style"; + +body { + background: #fff; +} + +.parsely-dashboard-container { + margin-left: to_rem(-20px); + overflow: hidden; +} + +.parsely-dashboard-page-body, +.parsely-dashboard-page-header { + max-width: var(--dashboard-width); + margin: 0 auto; + padding: var(--grid-unit-30); +} diff --git a/src/content-helper/dashboard-page/dashboard-page.tsx b/src/content-helper/dashboard-page/dashboard-page.tsx new file mode 100644 index 0000000000..90625761e2 --- /dev/null +++ b/src/content-helper/dashboard-page/dashboard-page.tsx @@ -0,0 +1,57 @@ +/** + * External dependencies + */ +import { + Navigate, + Route, + HashRouter as Router, + Routes, +} from 'react-router'; + +/** + * WordPress dependencies + */ +import domReady from '@wordpress/dom-ready'; +import { createRoot } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { SettingsPage, TrafficBoostPage } from './pages'; +import { TrafficBoostPostPage } from './pages/traffic-boost/single-post-component'; + +domReady( () => { + // Highlight the Traffic Boost menu item under the Parse.ly menu. + document.querySelector( + '#toplevel_page_parsely-dashboard-page .wp-submenu li.wp-first-item' + )?.classList.add( 'current' ); + + const root = createRoot( + document.getElementById( 'parsely-dashboard-page' ) as Element + ); + + root.render( + + + + ); +} ); + +/** + * Main component for the Parse.ly dashboard. + * + * @since 3.19.0 + * + * @class + */ +const ParselyDashboard = () => { + return ( + + } /> + } /> + } /> + } /> + + ); +}; + diff --git a/src/content-helper/dashboard-page/pages/dashboard/dashboard.scss b/src/content-helper/dashboard-page/pages/dashboard/dashboard.scss new file mode 100644 index 0000000000..34d8fcba7e --- /dev/null +++ b/src/content-helper/dashboard-page/pages/dashboard/dashboard.scss @@ -0,0 +1,160 @@ +@import "../../../common/css/functions"; +@import "../../../common/css/variables"; + +.parsely-menu-page-dashboard { + .parsely-dashboard-page-body, + .parsely-dashboard-page-header { + padding: var(--grid-unit-40) var(--grid-unit-40) var(--grid-unit-60) var(--grid-unit-40); + } + + .dashboard-header-background { + background: linear-gradient(303deg, #000 30.51%, #487006 133.77%); + } + + .dashboard-header { + display: flex; + flex-wrap: wrap; + gap: var(--grid-unit-25); + align-items: flex-start; + justify-content: space-between; + + .dashboard-header-summary { + display: flex; + width: to_rem(300px); + flex-direction: column; + align-items: flex-start; + gap: var(--grid-unit-30); + color: var(--sidebar-white); + + .summary-info { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--grid-unit-10); + align-self: stretch; + + .summary-title { + align-self: stretch; + font-size: var(--font-size--bigger); + font-style: normal; + font-weight: 600; + line-height: to_rem(45px); + } + + .summary-text { + align-self: stretch; + font-size: var(--font-size--small); + font-style: normal; + font-weight: 400; + line-height: var(--font-size--large); + } + } + + .summary-button { + button { + margin-top: var(--grid-unit-20); + padding: var(--grid-unit-10) var(--grid-unit-20); + background: transparent; + border: 1px solid var(--sidebar-white); + color: var(--sidebar-white); + cursor: pointer; + box-shadow: none; + + &:hover { + background: var(--sidebar-white); + color: var(--sidebar-black); + box-shadow: none; + } + } + } + } + + .dashboard-header-stats { + display: flex; + justify-content: flex-end; + align-items: flex-start; + align-content: flex-start; + gap: var(--grid-unit-30); + align-self: stretch; + flex-wrap: wrap; + width: to_rem(500px); + + .header-stat-card { + display: flex; + width: to_rem(150px); + align-items: flex-start; + gap: var(--grid-unit-05); + color: var(--sidebar-white); + height: var(--grid-unit-60); + flex-direction: column; + justify-content: center; + + .card-title { + display: flex; + align-items: center; + gap: var(--grid-unit-05); + + font-size: var(--font-size--small); + font-style: normal; + font-weight: 400; + line-height: var(--font-size--large); + + svg { + fill: var(--sidebar-white); + } + } + + .card-value { + display: flex; + align-items: center; + gap: var(--grid-unit-05); + font-size: to_rem(24px); + font-style: normal; + font-weight: 600; + line-height: to_rem(32px); + letter-spacing: -0.48px; + + .card-change { + font-size: var(--font-size--medium); + font-style: normal; + font-weight: 500; + line-height: var(--font-size--large); + } + } + } + + .stats-top { + display: flex; + padding-bottom: var(--grid-unit-30); + align-items: flex-start; + gap: var(--grid-unit-30); + border-bottom: 1px solid var(--sidebar-white); + + .card-title { + color: var(--dashboard-accent); + + svg { + fill: var(--dashboard-accent); + } + } + + .card-value { + color: var(--dashboard-accent); + } + + .stat-intro { + justify-content: flex-start; + + .card-title { + color: var(--sidebar-white); + font-size: var(--font-size--medium); + font-style: normal; + font-weight: 500; + line-height: var(--font-size--extra-large); + } + } + } + + } + } +} diff --git a/src/content-helper/dashboard-page/pages/dashboard/header-component.tsx b/src/content-helper/dashboard-page/pages/dashboard/header-component.tsx new file mode 100644 index 0000000000..bf8855a88b --- /dev/null +++ b/src/content-helper/dashboard-page/pages/dashboard/header-component.tsx @@ -0,0 +1,110 @@ +/** + * WordPress dependencies + */ +import { Button } from '@wordpress/components'; +import { Icon, link } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { PageHeader } from '../../components'; + +/** + * Header summary component. + * + * Renders a summary of the site performance. + * + * @since 3.19.0 + */ +const HeaderSummary = (): React.JSX.Element => { + return ( +
+
+
Today is an exceptional day.
+
75% more traffic than last week
+
Yesterday was the 33rd best Tuesday, 214th overall.
+
+
+ +
+
+ ); +}; + +/** + * Type definition for the HeaderCard component. + * + * @since 3.19.0 + */ +type HeaderCardProps = { + title?: string; + icon?: React.JSX.Element; + value?: string; + change?: string; + down?: boolean; + className?: string; +}; + +/** + * Single stat card component. + * + * @since 3.19.0 + * + * @param {HeaderCardProps} props The component's props. + */ +const StatCard = ( + { title, value, change, down = false, icon, className }: Readonly +): React.JSX.Element => { + const changeIcon = down ? '↓' : '↑'; + + return ( +
+ { title && +
+ { icon && } + { title } +
+ } + { value && +
+ { value } + { change &&
{ changeIcon }{ change }
} +
+ } +
+ ); +}; + +/** + * Dashboard header component. + * + * Renders the header of the main dashboard page. + * + * @since 3.19.0 + */ +export const DashboardHeader = (): React.JSX.Element => { + return ( +
+ + +
+
+ + + +
+ { [ + { title: 'Page Views', value: '4.6K', change: '24%' }, + { title: 'Visitors', value: '1.5K', change: '25%' }, + { title: 'Minutes', value: '32', change: '40%' }, + { title: 'Avg. Time', value: '32', change: '40%', down: true }, + { title: 'Soc. Interactions', value: '32', change: '40%' }, + { title: 'New Posts', value: '2', change: '40%' }, + ].map( ( metric, index ) => ( + + ) ) } +
+
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/dashboard/page-component.tsx b/src/content-helper/dashboard-page/pages/dashboard/page-component.tsx new file mode 100644 index 0000000000..b3af91533a --- /dev/null +++ b/src/content-helper/dashboard-page/pages/dashboard/page-component.tsx @@ -0,0 +1,96 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { SettingsProvider, TrafficBoostSettings } from '../../../common/settings'; +import { VerifyCredentials } from '../../../common/verify-credentials'; +import { PageBody, PageContainer, PostsTable } from '../../components'; +import { DashboardHeading } from '../../components/typography-components'; +import './dashboard.scss'; +import { DashboardHeader } from './header-component'; + +/** + * Gets the settings from the passed JSON. + * + * If missing settings or invalid values are detected, they get set to their + * defaults. + * + * @since 3.19.0 + * + * @param {string} settingsJson The JSON containing the settings. + * + * @return {TrafficBoostSettings} The resulting settings object. + */ +const getSettingsFromJson = ( settingsJson: string ): TrafficBoostSettings => { + // Default settings object. + const defaultSettings: TrafficBoostSettings = { + Setting1: 'Hello World!', + }; + + // If the settings are empty, try to get them from the global variable. + if ( '' === settingsJson ) { + settingsJson = window.wpParselyContentHelperSettings; + } + + let parsedSettings: TrafficBoostSettings; + + try { + parsedSettings = JSON.parse( settingsJson ); + } catch ( e ) { + // Return defaults when parsing failed or the string is empty. + return defaultSettings; + } + + // Merge parsed settings with default settings. + const mergedSettings = { ...defaultSettings, ...parsedSettings }; + + // Fix invalid values if any are found. + if ( typeof mergedSettings.Setting1 !== 'string' ) { + mergedSettings.Setting1 = defaultSettings.Setting1; + } + + return mergedSettings; +}; + +/** + * The main dashboard page component. + * + * @since 3.19.0 + */ +export const DashboardPage = (): React.JSX.Element => { + const [ currentPage, setCurrentPage ] = useState( 1 ); + return ( + + + + + + { __( 'Recent Posts', 'wp-parsely' ) } +

+ { __( + 'Here’s what you’ve published lately. Let’s see if we can improve its performance!', + 'wp-parsely' + ) } +

+ +
+
+
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/index.ts b/src/content-helper/dashboard-page/pages/index.ts new file mode 100644 index 0000000000..a60dc0c757 --- /dev/null +++ b/src/content-helper/dashboard-page/pages/index.ts @@ -0,0 +1,3 @@ +export { DashboardPage } from './dashboard/page-component'; +export { TrafficBoostPage } from './traffic-boost/page-component'; +export { SettingsPage } from './settings/page-component'; diff --git a/src/content-helper/dashboard-page/pages/settings/page-component.tsx b/src/content-helper/dashboard-page/pages/settings/page-component.tsx new file mode 100644 index 0000000000..0d2ed81ffd --- /dev/null +++ b/src/content-helper/dashboard-page/pages/settings/page-component.tsx @@ -0,0 +1,19 @@ +import { PageBody, PageContainer, PageHeader } from '../../components'; + +/** + * Settings page component. + * + * @since 3.19.0 + */ +export const SettingsPage = (): React.JSX.Element => { + return ( + + +

Parse.ly Settings

+
+ +

This is a page for settings.

+
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/traffic-boost/page-component.tsx b/src/content-helper/dashboard-page/pages/traffic-boost/page-component.tsx new file mode 100644 index 0000000000..af229562e5 --- /dev/null +++ b/src/content-helper/dashboard-page/pages/traffic-boost/page-component.tsx @@ -0,0 +1,57 @@ +/** + * WordPress dependencies + */ +import { SearchControl } from '@wordpress/components'; +import { useDebounce } from '@wordpress/compose'; +import { useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { PageBody, PageContainer, PageHeader, PostsTable } from '../../components'; +import './traffic-boost.scss'; + +/** + * Traffic Boost page component. + * + * @since 3.19.0 + */ +export const TrafficBoostPage = (): React.JSX.Element => { + const [ searchQuery, setSearchQuery ] = useState( '' ); + const debouncedSetSearchQuery = useDebounce( ( value: string ) => { + setSearchQuery( value ); + setCurrentPage( 1 ); + }, 300 ); + + const [ currentPage, setCurrentPage ] = useState( 1 ); + + return ( + + +

{ __( 'Manage Traffic Boost (beta)', 'wp-parsely' ) }

+
+ +
+ +
+ +
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-counter.tsx b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-counter.tsx new file mode 100644 index 0000000000..8f5a88193b --- /dev/null +++ b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-counter.tsx @@ -0,0 +1,205 @@ +/** + * WordPress dependencies + */ +import { Button } from '@wordpress/components'; +import { useDispatch } from '@wordpress/data'; +import { useEffect, useState } from '@wordpress/element'; +import { __, sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { HydratedPost } from '../../../../../common/providers/base-wordpress-provider'; +import { TrafficBoostStore } from '../../store'; + +/** + * Represents the type of link. + * + * @since 3.19.0 + */ +export type LinkType = 'external' | 'internal' | 'smart'; + +/** + * Represents the links for a post. + * + * @since 3.19.0 + */ +export interface PostLinks extends Record { + total: number; +} + +/** + * The shape of the link counter object. + * + * @since 3.19.0 + */ +type LinkCount = { + [key in LinkType]: number; +} + +/** + * Props for the LinkCounter component. + * + * @since 3.19.0 + */ +interface LinkCounterProps { + post: HydratedPost; + onLinkTypeClick?: ( type: LinkType | null ) => void; + selectedLinkType: LinkType | null; +} + +/** + * Component that displays a counter for different types of links. + * + * @since 3.19.0 + * + * @param {LinkCounterProps} props The component's props. + */ +export const LinkCounter = ( { + post, + onLinkTypeClick, + selectedLinkType: initialSelectedLinkType, +}: LinkCounterProps ): React.JSX.Element => { + const [ selectedLinkType, setSelectedLinkType ] = useState( initialSelectedLinkType ); + const [ links, setLinks ] = useState( { + external: 0, + internal: 0, + smart: 0, + } ); + + const { setPreviewLinkType } = useDispatch( TrafficBoostStore ); + + useEffect( () => { + const postContent = post.content.raw; + const siteUrl = new URL( post.link ).hostname; + + // Create a new DOMParser instance. + const parser = new DOMParser(); + const doc = parser.parseFromString( postContent, 'text/html' ); + const allLinks = doc.querySelectorAll( 'a' ); + + // Filter out links that have no text. + const linksWithText = Array.from( allLinks ).filter( ( link ) => link.textContent?.trim() !== '' ); + + // Classify the links into external, internal, and smart. + // Smart links contain the data-smartlink attribute. + const smartLinks = linksWithText.filter( ( link ) => link.hasAttribute( 'data-smartlink' ) ); + + // Internal links contain the site URL in the href attribute. + const internalLinks = linksWithText.filter( ( link ) => link.href.includes( siteUrl ) ); + + // External links are links that do not contain the site URL in the href attribute. + const externalLinks = linksWithText.filter( ( link ) => ! link.href.includes( siteUrl ) ); + + setLinks( { + external: externalLinks.length, + internal: internalLinks.length, + smart: smartLinks.length, + } ); + }, [ post ] ); + + /** + * Sets the selected link type and preview link type when the initial selected link type changes. + * + * @since 3.19.0 + */ + useEffect( () => { + setSelectedLinkType( initialSelectedLinkType ); + setPreviewLinkType( initialSelectedLinkType ); + }, [ initialSelectedLinkType, setPreviewLinkType ] ); + + /** + * Handles click events on link type buttons. + * + * @since 3.19.0 + * + * @param {LinkType} type The type of link that was clicked. + */ + const handleLinkTypeClick = ( type: LinkType ) => { + let newSelectedLinkType: LinkType | null = type; + + // If the same link type is clicked again, reset the selected link type. + if ( selectedLinkType === type ) { + newSelectedLinkType = null; + } + + setSelectedLinkType( newSelectedLinkType ); + setPreviewLinkType( newSelectedLinkType ); + + onLinkTypeClick?.( newSelectedLinkType ); + }; + + /** + * Checks if a link type is currently selected. + * + * @since 3.19.0 + * + * @param {LinkType} type The type to check. + * + * @return {boolean} Whether the type is selected. + */ + const isSelected = ( type: LinkType ) => selectedLinkType === type; + + const totalLinks = links.external + links.internal + links.smart; + + return ( +
+
+ { totalLinks > 0 ? ( + <> + { sprintf( + /* translators: %d: number of outbound links */ + __( 'Contains %d outbound links:', 'wp-parsely' ), + totalLinks + ) } + + ) : ( + <> + { __( 'This post has no outbound links.', 'wp-parsely' ) } + + ) } +
+
+ { links.external > 0 && ( + + ) } + { links.internal > 0 && ( + + ) } + { links.smart > 0 && ( + + ) } +
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-options-panel.tsx b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-options-panel.tsx new file mode 100644 index 0000000000..56a4030e7c --- /dev/null +++ b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/link-options-panel.tsx @@ -0,0 +1,150 @@ +/** + * WordPress imports + */ +import { + CheckboxControl, + PanelBody, + PanelRow, + TextControl, +} from '@wordpress/components'; +import { useEffect, useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal imports + */ +import { HydratedPost } from '../../../../../common/providers/base-wordpress-provider'; +import { TrafficBoostLink } from '../../provider'; + +/** + * Props structure for LinkOptionsPanel. + * + * @since 3.19.0 + */ +interface LinkOptionsPanelProps { + post: HydratedPost; + activeLink: TrafficBoostLink | null; + onTextChange: ( value: string ) => void; + onNewTabChange: ( value: boolean ) => void; + onNofollowChange: ( value: boolean ) => void; + linkText: string | null; +} + +/** + * Defines the state structure for LinkOptionsPanel. + * + * @since 3.19.0 + */ +interface OptionsState { + linkText: string; + openInNewTab: boolean; + nofollow: boolean; + isOpen: boolean; +} + +/** + * Link options panel component for the Traffic Boost feature. + * Displays link options for a selected post. + * + * Note: not in use currently. + * + * @since 3.19.0 + * + * @param {LinkOptionsPanelProps} props The component's props. + */ +export const LinkOptionsPanel = ( { + post, + activeLink, + onTextChange, + onNewTabChange, + onNofollowChange, + linkText, +}: LinkOptionsPanelProps ): React.JSX.Element => { + const [ options, setOptions ] = useState( { + linkText: linkText ?? activeLink?.smartLink?.text ?? '', + openInNewTab: false, + nofollow: false, + isOpen: false, + } ); + + /** + * Updates the link text when the linkText prop changes. + * + * @since 3.19.0 + */ + useEffect( () => { + setOptions( ( prevOptions: OptionsState ) => ( { + ...prevOptions, + linkText: linkText ?? '', + } ) ); + }, [ linkText ] ); + + /** + * Updates the link options when the active link changes. + * + * @since 3.19.0 + */ + useEffect( () => { + setOptions( ( prevOptions ) => ( { + ...prevOptions, + linkText: activeLink?.smartLink?.text ?? '', + isOpen: false, + } ) ); + }, [ activeLink ] ); + + return ( + setOptions( { ...options, isOpen } ) } + opened={ options.isOpen } + > + + { + setOptions( { ...options, linkText: value } ); + onTextChange( value ); + } } + help={ __( 'Select text in the post preview to change the link text', 'wp-parsely' ) } + /> + + + {} } // Disabled, so no need for implementation + /> + + +
+ { __( 'Advanced', 'wp-parsely' ) } +
+ { + setOptions( { ...options, openInNewTab: value } ); + onNewTabChange( value ); + } } + /> + { + setOptions( { ...options, nofollow: value } ); + onNofollowChange( value ); + } } + /> +
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-footer.tsx b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-footer.tsx new file mode 100644 index 0000000000..b00715afab --- /dev/null +++ b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-footer.tsx @@ -0,0 +1,193 @@ +/** + * WordPress imports + */ +import { Button, CheckboxControl } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { arrowLeft, arrowRight, check, close, undo } from '@wordpress/icons'; + +/** + * Internal imports + */ +import { VerticalDivider } from '../../../../../common/components/vertical-divider'; +import { TrafficBoostLink } from '../../provider'; +import { TrafficBoostStore } from '../../store'; +import { TextSelection } from '../preview'; + +/** + * Props structure for PreviewFooter. + * + * @since 3.19.0 + */ +interface PreviewFooterProps { + activeLink: TrafficBoostLink | null; + onAccept: ( link: TrafficBoostLink ) => void; + onRemove: ( link: TrafficBoostLink, restoreOriginal: boolean ) => void; + onUpdateLink: ( link: TrafficBoostLink, restoreOriginal: boolean ) => void; + onDiscard: ( link: TrafficBoostLink ) => void; + onNext: () => void; + onPrevious: () => void; + totalItems: number; + itemIndex: number; + onRestoreOriginal: () => void; + selectedText: TextSelection | null; +} + +/** + * Preview footer component for the Traffic Boost feature. + * Displays link options for a selected post. + * + * @since 3.19.0 + * + * @param {PreviewFooterProps} props The component's props. + */ +export const PreviewFooter = ( { + activeLink, + onAccept, + onUpdateLink, + onDiscard, + onNext, + onPrevious, + onRemove, + totalItems, + itemIndex, + onRestoreOriginal, + selectedText, +}: PreviewFooterProps ): React.JSX.Element => { + const isInboundLink = ! activeLink?.isSuggestion; + const hasNext = itemIndex < totalItems; + const hasPrevious = itemIndex > 1; + const [ restoreOriginal, setRestoreOriginal ] = useState( true ); + + const { + isAccepting, + isRemoving, + isGenerating, + } = useSelect( ( select ) => ( { + isAccepting: activeLink ? select( TrafficBoostStore ).isAccepting( activeLink ) : false, + isRemoving: activeLink ? select( TrafficBoostStore ).isRemoving( activeLink ) : false, + isGenerating: activeLink ? select( TrafficBoostStore ).isGenerating( activeLink ) : false, + } ), [ activeLink ] ); + + if ( ! activeLink ) { + return <>; + } + + return ( +
+
+ { hasPrevious && ( +
+ + { ! isGenerating && ( +
+ { ! isInboundLink && ( + <> + + + { selectedText && ( + <> + + + + ) } + + ) } + + { isInboundLink && ( + <> + { selectedText ? ( + <> + + { activeLink.smartLink?.is_link_replacement && ( + { + setRestoreOriginal( value ); + } } + /> + ) } + + + + ) : ( + <> + + { activeLink.smartLink?.is_link_replacement && ( + { + setRestoreOriginal( value ); + } } + /> + ) } + + ) } + + ) } +
+ ) } + +
+ { hasNext && ( +
+ +
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-header.tsx b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-header.tsx new file mode 100644 index 0000000000..6929ba6688 --- /dev/null +++ b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-header.tsx @@ -0,0 +1,177 @@ +/** + * WordPress imports + */ +import { Button, DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; +import { useEffect } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { desktop, edit, external, moreVertical } from '@wordpress/icons'; + +/** + * Internal imports + */ +import { LeafIcon } from '../../../../../common/icons/leaf-icon'; +import { HydratedPost } from '../../../../../common/providers/base-wordpress-provider'; +import { TrafficBoostLink } from '../../provider'; +import { isExternalURL } from '../utils'; +import { LinkCounter } from './link-counter'; + +/** + * Props structure for VerticalMoreMenu. + * + * @since 3.19.0 + */ +interface VerticalMoreMenuProps { + post: HydratedPost; + onEditClick: ( post: HydratedPost ) => void; + onViewInNewTabClick: ( post: HydratedPost ) => void; + onViewInParseLyClick: ( post: HydratedPost ) => void; +} + +/** + * VerticalMoreMenu component. + * + * This component is used to display a dropdown menu with actions for a post. + * + * @since 3.19.0 + * + * @param {VerticalMoreMenuProps} props The component's props. + */ +const VerticalMoreMenu = ( { + post, + onEditClick, + onViewInNewTabClick, + onViewInParseLyClick, +}: VerticalMoreMenuProps ): React.JSX.Element => { + /** + * Handles the click event for the dropdown menu items. + * + * @since 3.19.0 + * + * @param {string} type The type of action to perform. + * @param {Function} onClose The function to call when the action is performed. + */ + const onClickHandler = ( type: string, onClose: () => void ) => { + switch ( type ) { + case 'edit': + onEditClick( post ); + break; + case 'view-in-new-tab': + onViewInNewTabClick( post ); + break; + case 'view-in-parse-ly': + onViewInParseLyClick( post ); + break; + } + onClose(); + }; + + return ( + + { ( { onClose } ) => ( + + onClickHandler( 'edit', onClose ) }> + { __( 'Edit Post', 'wp-parsely' ) } + + onClickHandler( 'view-in-new-tab', onClose ) }> + { __( 'View post in a new tab', 'wp-parsely' ) } + + } onClick={ () => onClickHandler( 'view-in-parse-ly', onClose ) }> + { __( 'View in Parse.ly', 'wp-parsely' ) } + + + ) } + + ); +}; + +/** + * Props structure for PreviewHeader. + * + * @since 3.19.0 + */ +interface PreviewHeaderProps { + isLoading: boolean; + activeLink: TrafficBoostLink | null; + onOpenPostInNewTab: () => void; + onOpenPostEditor: () => void; + onOpenParselyDashboard: () => void; + isFrontendPreview: boolean; + setIsFrontendPreview: ( value: boolean ) => void; +} + +/** + * Preview header component for the Traffic Boost feature. + * Displays preview header for a selected post. + * + * @since 3.19.0 + * + * @param {PreviewHeaderProps} props The component's props. + */ +export const PreviewHeader = ( { + isLoading, + activeLink, + isFrontendPreview, + setIsFrontendPreview, + onOpenPostEditor, + onOpenPostInNewTab, + onOpenParselyDashboard, +}: PreviewHeaderProps ): React.JSX.Element => { + /** + * Toggles the frontend preview state. + * + * @since 3.19.0 + */ + const onToggleFrontendPreview = () => { + setIsFrontendPreview( ! isFrontendPreview ); + }; + + /** + * Toggles the frontend preview state when the active link is external, + * so that the iframe is not displayed. + * + * This prevents issues with cross-origin requests. + * + * @since 3.19.0 + */ + useEffect( () => { + if ( activeLink && isExternalURL( activeLink ) ) { + setIsFrontendPreview( false ); + } + }, [ activeLink, setIsFrontendPreview ] ); + + if ( ! activeLink ) { + return <>; + } + + return ( +
+
+
+
+
+ +
+
+ { ! isExternalURL( activeLink ) && false && ( +
+
+ ); +}; diff --git a/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx new file mode 100644 index 0000000000..ff1bb1d254 --- /dev/null +++ b/src/content-helper/dashboard-page/pages/traffic-boost/preview/components/preview-iframe.tsx @@ -0,0 +1,424 @@ +/** + * WordPress imports + */ +import { Spinner } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useCallback, useEffect, useMemo, useRef } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal imports + */ +import { usePrevious } from '@wordpress/compose'; +import { Loading } from '../../../../../common/components/loading'; +import { ErrorIcon } from '../../../../../common/icons/error-icon'; +import { TRAFFIC_BOOST_LOADING_MESSAGES, TrafficBoostLink } from '../../provider'; +import { TrafficBoostStore } from '../../store'; +import { useIframeHighlight } from '../hooks/use-iframe-highlight'; +import { TextSelection } from '../preview'; +import { getContentArea, isExternalURL } from '../utils'; +import { TextSelectionTooltip } from './text-selection-tooltip'; + +/** + * Props structure for PreviewIframe. + * + * @since 3.19.0 + */ +interface PreviewIframeProps { + activeLink?: TrafficBoostLink | null; + selectedText?: TextSelection | null; + previewUrl: string; + isLoading: boolean; + onTextSelected: ( text: string, offset: number ) => void; + isFrontendPreview: boolean; + onLoadingChange: ( isLoading: boolean ) => void; + onRestoreOriginal: () => void; +} + +/** + * Preview iframe component for the Traffic Boost feature. + * Displays preview iframe for a selected post. + * + * @since 3.19.0 + * + * @param {PreviewIframeProps} props The component's props. + */ +export const PreviewIframe = ( { + previewUrl, + isLoading, + onTextSelected, + isFrontendPreview, + activeLink, + selectedText, + onLoadingChange, + onRestoreOriginal, +}: PreviewIframeProps ): React.JSX.Element => { + const contentAreaRef = useRef( null ); + + const iframeRef = useRef( null ); + const isInboundLink = ! activeLink?.isSuggestion; + + const { selectedLinkType, isGenerating } = useSelect( ( select ) => ( { + selectedLinkType: select( TrafficBoostStore ).getPreviewLinkType(), + isGenerating: activeLink ? select( TrafficBoostStore ).isGenerating( activeLink ) : false, + } ), [ activeLink ] ); + + const previousIsGenerating = usePrevious( isGenerating ); + + /** + * Adds a random UUID to the iframe src. This triggers the WordPress Customizer to load + * and prevents potential undesired scripts from being loaded. + * + * @since 3.19.0 + */ + const iFrameSrc = useMemo( () => { + if ( ! previewUrl ) { + return previewUrl; + } + + const url = new URL( previewUrl ); + url.searchParams.set( 'customize_changeset_uuid', crypto.randomUUID() ); + + return url.toString(); + }, [ previewUrl ] ); + + /** + * Highlights the smart link in the iframe. + * + * @since 3.19.0 + */ + const { + injectHighlightStyles, + highlightSmartLink, + highlightLinkType, + removeSmartLinkHighlights, + } = useIframeHighlight( { + iframeRef, + contentAreaRef, + activeLink, + selectedText, + isInboundLink, + onRestoreOriginal, + } ); + + /** + * Hides the admin bar from the iframe if the preview is in frontend mode. + * + * @since 3.19.0 + * + * @param {HTMLIFrameElement} iframe The iframe element to hide the admin bar in. + */ + const hideAdminBar = useCallback( ( iframe: HTMLIFrameElement ) => { + if ( ! isFrontendPreview ) { + return; + } + + const adminBar = iframe.contentWindow?.document.getElementById( 'wpadminbar' ); + if ( adminBar ) { + adminBar.style.display = 'none'; + } + + const html = iframe.contentWindow?.document.documentElement; + if ( html ) { + html.style.setProperty( 'margin-top', '0', 'important' ); + } + }, [ isFrontendPreview ] ); + + /** + * Disables all navigation within the iframe. + * + * @since 3.19.0 + * + * @param {HTMLIFrameElement} iframe The iframe element to disable navigation in. + */ + const disableNavigation = useCallback( ( iframe: HTMLIFrameElement ) => { + const iframeDocument = iframe?.contentDocument ?? iframe.contentWindow?.document; + if ( ! iframeDocument ) { + return; + } + + // Prevent clicks on all links and handle link selection. + iframeDocument.addEventListener( 'click', ( event ) => { + const target = event.target as HTMLElement; + + // If the link is outside the content area, don't handle it. + if ( ! contentAreaRef.current?.contains( target ) ) { + event.preventDefault(); + event.stopPropagation(); + return; + } + + const link = target.tagName === 'A' ? target : target.closest( 'a' ); + if ( link ) { + event.preventDefault(); + event.stopPropagation(); + + // If the parent is not a paragraph or an anchor, skip. + const allowedParentTagNamesToBeClicked = [ 'P', 'A' ]; + if ( ! allowedParentTagNamesToBeClicked.includes( target.parentElement?.tagName ?? '' ) ) { + return; + } + + // Remove focus from the link. + link.blur(); + + // Select the link text so it can be highlighted. + link.ownerDocument.defaultView?.getSelection()?.selectAllChildren( link ); + } + }, true ); + + // Disable form submissions. + iframeDocument.addEventListener( 'submit', ( event ) => { + event.preventDefault(); + event.stopPropagation(); + }, true ); + + // Override window.open. + if ( iframe.contentWindow ) { + Object.defineProperty( iframe.contentWindow, 'open', { + value: () => null, + writable: false, + } ); + } + + // Disable right click. + iframeDocument.addEventListener( 'contextmenu', ( event ) => { + event.preventDefault(); + event.stopPropagation(); + }, true ); + + try { + // Attempt to disable history navigation. + if ( iframe.contentWindow?.history ) { + iframe.contentWindow.history.pushState = () => undefined; + iframe.contentWindow.history.replaceState = () => undefined; + } + } catch ( error ) { + // Silently fail if we can't override history methods. + } + + // Prevent navigation via history. + iframe.contentWindow?.addEventListener( 'popstate', ( event ) => { + event.preventDefault(); + event.stopPropagation(); + }, true ); + }, [ contentAreaRef ] ); + + /** + * Jumps to the smart link text in the iframe. + * + * @since 3.19.0 + * + * @param {HTMLIFrameElement} iframe The iframe element containing the smart link to scroll to. + */ + const jumpToSmartLink = useCallback( ( iframe: HTMLIFrameElement ) => { + const iframeDocument = iframe.contentDocument ?? iframe.contentWindow?.document; + if ( ! iframeDocument ) { + return; + } + + const scrollToHighlightedElement = async () => { + const highlightedElement = iframeDocument.querySelector( '.smart-link-highlight:not(.previous-suggestion)' ); + if ( highlightedElement ) { + // Wait 100ms to ensure the highlighted element is visible. + await new Promise( ( resolve ) => setTimeout( resolve, 100 ) ); + + highlightedElement.scrollIntoView( { + behavior: 'smooth', + block: 'center', + } ); + } + }; + + // The highlighted element might not be visible immediately after the iframe loads, due to + // the iframe content not being fully loaded yet (e.g. a custom block still being loaded). + // So we use a MutationObserver to watch for DOM changes and scroll to the highlighted + // element once it's visible. + const watchForHighlightedElement = () => { + const highlightedElement = iframeDocument.querySelector( '.smart-link-highlight:not(.previous-suggestion)' ); + if ( highlightedElement ) { + scrollToHighlightedElement(); + } + }; + + const observer = new MutationObserver( watchForHighlightedElement ); + const contentArea = getContentArea( iframeDocument ); + + if ( contentArea ) { + observer.observe( contentArea, { + childList: true, + subtree: true, + } ); + + // Try to scroll to the highlighted element immediately. + scrollToHighlightedElement(); + + // Disconnect the observer after a short delay to prevent infinite observation. + setTimeout( () => observer.disconnect(), 1000 ); + } + }, [] ); + + /** + * Handles the iframe load event. + * + * @since 3.19.0 + * + * @param {HTMLIFrameElement} iframe The iframe element to handle the load event for. + */ + const handleIframeLoad = useCallback( ( iframe: HTMLIFrameElement ) => { + if ( ! iframe?.contentDocument ) { + return; + } + + injectHighlightStyles( iframe ); + + // Updates the content area ref to the iframe's content area. + const contentArea = getContentArea( iframe.contentDocument ); + if ( contentArea ) { + contentAreaRef.current = contentArea; + } + + hideAdminBar( iframe ); + highlightLinkType( iframe, selectedLinkType ); + disableNavigation( iframe ); + + onLoadingChange( false ); + jumpToSmartLink( iframe ); + }, [ contentAreaRef, + disableNavigation, + hideAdminBar, + highlightLinkType, + injectHighlightStyles, + jumpToSmartLink, + onLoadingChange, + selectedLinkType, + ] ); + + /** + * Handles iframe initialization and cleanup. + * + * @since 3.19.0 + */ + useEffect( () => { + // If we're generating placement, don't try to set up the iframe yet. + if ( isGenerating ) { + return; + } + + const iframe = iframeRef.current; + if ( ! iframe ) { + return; + } + + /** + * Handles the iframe load event. + * + * @since 3.19.0 + */ + const handleLoadCallback = () => { + handleIframeLoad( iframe ); + }; + + // Only set loading state if the URL has changed. + if ( iframe.src !== iFrameSrc ) { + onLoadingChange( true ); + } + + iframe.addEventListener( 'load', handleLoadCallback ); + + return () => { + iframe.removeEventListener( 'load', handleLoadCallback ); + }; + }, [ isGenerating, iFrameSrc, handleIframeLoad, onLoadingChange ] ); + + /** + * Resets content area ref when active link changes. + * + * @since 3.19.0 + */ + useEffect( () => { + contentAreaRef.current = null; + }, [ activeLink, contentAreaRef ] ); + + /** + * Re-highlights smart link when selection changes. + * + * @since 3.19.0 + */ + useEffect( () => { + const iframe = iframeRef.current; + if ( ! iframe?.contentDocument || contentAreaRef.current === null || isLoading ) { + return; + } + + removeSmartLinkHighlights( iframe ); + highlightSmartLink( iframe ); + jumpToSmartLink( iframe ); + }, [ contentAreaRef, highlightSmartLink, isLoading, jumpToSmartLink, removeSmartLinkHighlights, selectedText ] ); + + /** + * Highlights the link type in the iframe. + * + * @since 3.19.0 + */ + useEffect( () => { + const iframe = iframeRef.current; + if ( ! iframe?.contentDocument || contentAreaRef.current === null || isLoading ) { + return; + } + + highlightLinkType( iframe, selectedLinkType ); + }, [ contentAreaRef, highlightLinkType, isLoading, selectedLinkType ] ); + + return ( +
+
+
+ { isFrontendPreview && activeLink && isExternalURL( activeLink ) ? ( + <> + + { __( 'This link is not available in the preview.', 'wp-parsely' ) } + + ) : ( + <> + { isLoading && ( + <> + + { ( isGenerating || previousIsGenerating ) && ( + <> + + + ) } + + ) } + + ) } +
+ + { activeLink && ! isGenerating && ( ! isFrontendPreview || ! isExternalURL( activeLink ) ) && ( + <> +