diff --git a/assets/css/src/design-pack-notice.scss b/assets/css/src/design-pack-notice.scss
new file mode 100644
index 0000000..aa02b7a
--- /dev/null
+++ b/assets/css/src/design-pack-notice.scss
@@ -0,0 +1,118 @@
+@custom-media --max-tablet (max-width: 769px);
+@custom-media --max-desktop (max-width: 1200px);
+
+#fork-design-pack-notice {
+
+ .notice-wrap {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ border: 0;
+ border-radius: 8px;
+ padding: 20px 25px;
+ opacity: 0;
+ animation: fade-down-in 0.3s ease forwards 0.3s;
+ z-index: 10000;
+ position: fixed;
+ background: #fff;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ right: 10px;
+ bottom: 35px;
+
+ @media (--max-desktop) {
+ bottom: 10px;
+ right: 10px;
+ padding: 10px 15px;
+ margin-left: 10px;
+ }
+
+ &.dismissed {
+ animation: fade-up-out 0.3s ease forwards 0s;
+ }
+ }
+
+ svg {
+ flex-shrink: 0;
+ }
+
+ button {
+ border: 0;
+ background: 0;
+ cursor: pointer;
+ padding: 0;
+ border-radius: 5px;
+
+ &:hover {
+ background: #e7e7e7;
+ }
+ }
+
+ .content-wrap {
+ display: grid;
+ }
+
+ span {
+ font-weight: 600;
+ color: #6a6a6a;
+ font-size: 12px;
+
+ @media (--max-desktop) {
+ font-size: 10px;
+ }
+ }
+
+ p {
+
+ @media (--max-desktop) {
+ font-size: 12px;
+ }
+ font-size: 16px;
+ margin: 0;
+ padding: 0;
+ }
+
+ a {
+ margin-left: 35px;
+ font-weight: 700;
+ font-size: 16px;
+ text-decoration: 0;
+ color: #fff;
+ background: #383fef;
+ border-radius: 5px;
+ padding: 12px 16px;
+ text-align: center;
+
+ @media (--max-desktop) {
+ font-size: 14px;
+ padding: 7px 10px;
+ margin-left: 0;
+ flex-shrink: 0;
+ }
+ }
+}
+
+@keyframes fade-down-in {
+
+ 0% {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes fade-up-out {
+
+ 0% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+}
diff --git a/assets/js/src/components/DesignPackNotice.js b/assets/js/src/components/DesignPackNotice.js
new file mode 100644
index 0000000..d9afc33
--- /dev/null
+++ b/assets/js/src/components/DesignPackNotice.js
@@ -0,0 +1,98 @@
+/* global designPackNoticeData */
+import { useSelect } from '@wordpress/data';
+import { Icon, closeSmall } from '@wordpress/icons';
+import { useEffect, useState } from '@wordpress/element';
+
+const logo = (
+
+);
+
+const BLOCK_PATTERN_INSERTED_NOTICE = 'block-pattern-inserted-notice';
+export default () => {
+ const [ dismissed, setDismissed ] = useState( false );
+ const [ noticeTriggered, setNoticeTriggered ] = useState( false );
+
+ const patternInserted = useSelect(
+ ( select ) =>
+ select( 'core/notices' )
+ .getNotices()
+ .filter( ( n ) => n.id === BLOCK_PATTERN_INSERTED_NOTICE )
+ .length > 0
+ );
+
+ useEffect( () => {
+ if ( noticeTriggered ) {
+ return;
+ }
+ if ( patternInserted ) {
+ setNoticeTriggered( true );
+ }
+ }, [ patternInserted ] );
+
+ const { ajaxUrl, ajaxAction, nonce, strings, buttonLink } =
+ designPackNoticeData;
+ const { dismiss, recommends, learnMore, noticeHtml } = strings;
+
+ const dismissNotice = () => {
+ const data = new window.FormData();
+
+ data.append( 'action', ajaxAction );
+ data.append( 'nonce', nonce );
+
+ fetch( ajaxUrl, {
+ method: 'POST',
+ body: data,
+ } ).then( () => {
+ setDismissed( true );
+ } );
+ };
+
+ const classes = [ 'notice-wrap' ];
+
+ if ( dismissed ) {
+ classes.push( 'dismissed' );
+ }
+
+ if ( ! noticeTriggered ) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/assets/js/src/design-pack-notice.js b/assets/js/src/design-pack-notice.js
new file mode 100644
index 0000000..764e811
--- /dev/null
+++ b/assets/js/src/design-pack-notice.js
@@ -0,0 +1,9 @@
+import { createRoot } from '@wordpress/element';
+
+import DesignPackNotice from './components/DesignPackNotice';
+
+const container = document.getElementById( 'fork-design-pack-notice' );
+
+if ( container ) {
+ createRoot( container ).render( );
+}
diff --git a/inc/Admin.php b/inc/Admin.php
index d78e1c3..211005d 100644
--- a/inc/Admin.php
+++ b/inc/Admin.php
@@ -34,6 +34,82 @@ public function setup_admin_hooks() {
add_action( 'wp_ajax_fork_dismiss_welcome_notice', array( $this, 'remove_welcome_notice' ) );
add_action( 'wp_ajax_fork_set_otter_ref', array( $this, 'set_otter_ref' ) );
add_action( 'admin_print_scripts', array( $this, 'add_nps_form' ) );
+
+ add_action( 'enqueue_block_editor_assets', array( $this, 'add_fse_design_pack_notice' ) );
+ add_action( 'wp_ajax_fork_dismiss_design_pack_notice', array( $this, 'remove_design_pack_notice' ) );
+ }
+
+ /**
+ * Render design pack notice.
+ *
+ * @return void
+ */
+ public function add_fse_design_pack_notice() {
+ if ( ! $this->should_render_design_pack_notice() ) {
+ return;
+ }
+
+ Assets_Manager::enqueue_style( Assets_Manager::ASSETS_SLUGS['design-pack-notice'], 'design-pack-notice' );
+ Assets_Manager::enqueue_script(
+ Assets_Manager::ASSETS_SLUGS['design-pack-notice'],
+ 'design-pack-notice',
+ true,
+ array(),
+ array(
+ 'nonce' => wp_create_nonce( 'fork-dismiss-design-pack-notice' ),
+ 'ajaxUrl' => esc_url( admin_url( 'admin-ajax.php' ) ),
+ 'ajaxAction' => 'fork_dismiss_design_pack_notice',
+ 'buttonLink' => tsdk_utmify( 'https://themeisle.com/plugins/fse-design-pack', 'editor', 'fork' ),
+ 'strings' => array(
+ 'dismiss' => __( 'Dismiss', 'fork' ),
+ 'recommends' => __( 'Fork recommends', 'fork' ),
+ 'learnMore' => __( 'Learn More', 'fork' ),
+ 'noticeHtml' => sprintf(
+ /* translators: %s: FSE Design Pack: */
+ __( '%s Access a collection of 40+ layout patterns ready to import to your website', 'fork' ),
+ 'FSE Design Pack:'
+ ),
+ ),
+ ),
+ 'designPackNoticeData'
+ );
+
+ echo '';
+ }
+
+ /**
+ * Should we show the design pack notice?
+ *
+ * @return bool
+ */
+ private function should_render_design_pack_notice() {
+ // Already using.
+ if ( is_plugin_active( 'fse-design-pack/fse-design-pack.php' ) ) {
+ return false;
+ }
+
+ // Notice was dismissed.
+ if ( get_option( Constants::CACHE_KEYS['dismissed-fse-design-pack-notice'], 'no' ) === 'yes' ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Dismiss the design pack notice.
+ *
+ * @return void
+ */
+ public function remove_design_pack_notice() {
+ if ( ! isset( $_POST['nonce'] ) ) {
+ return;
+ }
+ if ( ! wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'fork-dismiss-design-pack-notice' ) ) {
+ return;
+ }
+ update_option( Constants::CACHE_KEYS['dismissed-fse-design-pack-notice'], 'yes' );
+ wp_die();
}
/**
diff --git a/inc/Assets_Manager.php b/inc/Assets_Manager.php
index 0e6d07f..2d80eec 100644
--- a/inc/Assets_Manager.php
+++ b/inc/Assets_Manager.php
@@ -16,9 +16,10 @@
*/
class Assets_Manager {
const ASSETS_SLUGS = array(
- 'frontend-css' => 'fork-style',
- 'editor-css' => 'fork-editor',
- 'welcome-notice' => 'fork-welcome-notice',
+ 'frontend-css' => 'fork-style',
+ 'editor-css' => 'fork-editor',
+ 'welcome-notice' => 'fork-welcome-notice',
+ 'design-pack-notice' => 'fork-design-pack-notice',
);
/**
diff --git a/inc/Constants.php b/inc/Constants.php
index 80eadce..56c3e9b 100644
--- a/inc/Constants.php
+++ b/inc/Constants.php
@@ -16,6 +16,7 @@
*/
class Constants {
const CACHE_KEYS = array(
- 'dismissed-welcome-notice' => 'fork-welcome-notice-dismissed',
+ 'dismissed-welcome-notice' => 'fork-welcome-notice-dismissed',
+ 'dismissed-fse-design-pack-notice' => 'fork-design-pack-dismissed',
);
}
diff --git a/package.json b/package.json
index 1455cd2..6adbbb4 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@wordpress/eslint-plugin": "^12.8.0",
+ "@wordpress/icons": "^9.47.0",
"@wordpress/scripts": "^23.6.0",
"@wordpress/stylelint-config": "^20.0.2",
"conventional-changelog-simple-preset": "^1.0.20",
diff --git a/yarn.lock b/yarn.lock
index b13a187..aa0a4ff 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2201,6 +2201,21 @@
dependencies:
"@types/react" "^17"
+"@types/react-dom@^18.0.6":
+ version "18.3.0"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0"
+ integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@^18.0.21":
+ version "18.3.0"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.0.tgz#2e6ac50dea2f68f774b20f1bd536ef82365cd64a"
+ integrity sha512-DiUcKjzE6soLyln8NNZmyhcQjVv+WsUIFSqetMN0p8927OztKT4VTfFTqsbAi5oAGIcgOmOajlfBqyptDDjZRw==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
"@types/react@^17", "@types/react@^17.0.37":
version "17.0.52"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.52.tgz#10d8b907b5c563ac014a541f289ae8eaa9bf2e9b"
@@ -2626,6 +2641,20 @@
react "^17.0.2"
react-dom "^17.0.2"
+"@wordpress/element@^5.33.0":
+ version "5.33.0"
+ resolved "https://registry.yarnpkg.com/@wordpress/element/-/element-5.33.0.tgz#33ffd6c75ed8f711b55f8e6051dc09e963d23c78"
+ integrity sha512-RNisHbRgAO5/RLyfckgHYWgKq+IKd8Yn1mJHYWp+1Fx+1K6vjlhr/1D4a81fWL15IoCTV3tYh6zYei4/fRpZog==
+ dependencies:
+ "@babel/runtime" "^7.16.0"
+ "@types/react" "^18.0.21"
+ "@types/react-dom" "^18.0.6"
+ "@wordpress/escape-html" "^2.56.0"
+ change-case "^4.1.2"
+ is-plain-object "^5.0.0"
+ react "^18.2.0"
+ react-dom "^18.2.0"
+
"@wordpress/escape-html@^2.22.0":
version "2.22.0"
resolved "https://registry.yarnpkg.com/@wordpress/escape-html/-/escape-html-2.22.0.tgz#2fa4e901b0ab96634541ca7d153baf910b741977"
@@ -2633,6 +2662,13 @@
dependencies:
"@babel/runtime" "^7.16.0"
+"@wordpress/escape-html@^2.56.0":
+ version "2.56.0"
+ resolved "https://registry.yarnpkg.com/@wordpress/escape-html/-/escape-html-2.56.0.tgz#042626b9fc33dbd210b24ed554e71a9a9665b246"
+ integrity sha512-f+NDe9ZyUtaoiU8VYSKRjxsKqqzinrVcpcqj+umiLhKD5ShGW8V7LcSr3JOdE4TgjHvw2eezFvRmEo/kXowmMA==
+ dependencies:
+ "@babel/runtime" "^7.16.0"
+
"@wordpress/eslint-plugin@^12.8.0", "@wordpress/eslint-plugin@^12.9.0":
version "12.9.0"
resolved "https://registry.yarnpkg.com/@wordpress/eslint-plugin/-/eslint-plugin-12.9.0.tgz#c49f0a523c8c72ade28c2b86a975668832b22938"
@@ -2655,6 +2691,15 @@
globals "^13.12.0"
requireindex "^1.2.0"
+"@wordpress/icons@^9.47.0":
+ version "9.47.0"
+ resolved "https://registry.yarnpkg.com/@wordpress/icons/-/icons-9.47.0.tgz#ea817c822b2e307bdfb5c9ec555933037a2c0c6a"
+ integrity sha512-IQIoEr0LxPWUOgcHnMIqU/ytg3x/swxbl8AGG1ONFks3/2tYdDk3I2/CAYgQGpaiSFIOJjNVk1keqa8DBOnciw==
+ dependencies:
+ "@babel/runtime" "^7.16.0"
+ "@wordpress/element" "^5.33.0"
+ "@wordpress/primitives" "^3.54.0"
+
"@wordpress/jest-console@^5.4.0":
version "5.4.0"
resolved "https://registry.yarnpkg.com/@wordpress/jest-console/-/jest-console-5.4.0.tgz#b01301ced098b0f0f6adeeb2e5235699d7a80b66"
@@ -2692,6 +2737,15 @@
resolved "https://registry.yarnpkg.com/@wordpress/prettier-config/-/prettier-config-1.4.0.tgz#8eaeb8daf7253e8b0806da2279017d4f4fef0f62"
integrity sha512-uvrgUAhRnOvIysXjcXH9VDsrKLqH9r3BfdGoy+WFLSHFnTfdMhW7bdDQXl4F4UIUuefUwGi+ZvT/rChg9zoBkQ==
+"@wordpress/primitives@^3.54.0":
+ version "3.54.0"
+ resolved "https://registry.yarnpkg.com/@wordpress/primitives/-/primitives-3.54.0.tgz#7e46aed14c1e261314171b4fc496ce5214604d54"
+ integrity sha512-2TrXDvYW3V0nlq6ZCYYvJ5obPZNtrsuIdB0iLdUavCOSBoXTROhRZY9Pxz45bB2CLlmEUs9OfL7izx9IuAg4Mw==
+ dependencies:
+ "@babel/runtime" "^7.16.0"
+ "@wordpress/element" "^5.33.0"
+ classnames "^2.3.1"
+
"@wordpress/scripts@^23.6.0":
version "23.7.2"
resolved "https://registry.yarnpkg.com/@wordpress/scripts/-/scripts-23.7.2.tgz#93f38354d799ed91cc9adc27144927c6935ce413"
@@ -3836,6 +3890,11 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
+classnames@^2.3.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
+ integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
+
clean-stack@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
@@ -10670,6 +10729,14 @@ react-dom@^17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
+react-dom@^18.2.0:
+ version "18.3.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.0.tgz#98a3a1cc4e471d517c2a084f38ab1d58d02cada7"
+ integrity sha512-zaKdLBftQJnvb7FtDIpZtsAIb2MZU087RM8bRDZU8LVCCFYjPTsDZJNFUWPcVz3HFSN1n/caxi0ca4B/aaVQGQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.23.1"
+
react-is@^16.12.0, react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -10716,6 +10783,13 @@ react@^17.0.2:
loose-envify "^1.1.0"
object-assign "^4.1.1"
+react@^18.2.0:
+ version "18.3.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.3.0.tgz#84386d0a36fdf5ef50fa5755b7812bdfb76194a5"
+ integrity sha512-RPutkJftSAldDibyrjuku7q11d3oy6wKOyPe5K1HA/HwwrXcEqBdHsLypkC2FFYjP7bPUa6gbzSBhw4sY2JcDg==
+ dependencies:
+ loose-envify "^1.1.0"
+
read-cmd-shim@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz#868c235ec59d1de2db69e11aec885bc095aea087"
@@ -11230,6 +11304,13 @@ scheduler@^0.20.2:
loose-envify "^1.1.0"
object-assign "^4.1.1"
+scheduler@^0.23.1:
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.1.tgz#ef964a7936d7cbe8f7bc0d38fc479a823aed2923"
+ integrity sha512-5GKS5JGfiah1O38Vfa9srZE4s3wdHbwjlCrvIookrg2FO9aIwKLOJXuJQFlEfNcVSOXuaL2hzDeY20uVXcUtrw==
+ dependencies:
+ loose-envify "^1.1.0"
+
schema-utils@^2.6.5:
version "2.7.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"