From c28ad8d35f2ac4ac079af58a5aee5a853d553860 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Wed, 23 Oct 2024 15:28:18 +0100 Subject: [PATCH 01/27] added link prefetch options component, LinkPrefetch class and js for frontend --- assets/js/linkPrefetch.js | 219 ++++++++++++++++++++++++++ assets/js/linkPrefetch.min.js | 1 + components/linkPrefetch/index.js | 136 ++++++++++++++++ components/performance/defaultText.js | 19 +++ components/performance/index.js | 9 +- includes/LinkPrefetch.php | 71 +++++++++ includes/Performance.php | 6 +- 7 files changed, 459 insertions(+), 2 deletions(-) create mode 100644 assets/js/linkPrefetch.js create mode 100644 assets/js/linkPrefetch.min.js create mode 100644 components/linkPrefetch/index.js create mode 100644 includes/LinkPrefetch.php diff --git a/assets/js/linkPrefetch.js b/assets/js/linkPrefetch.js new file mode 100644 index 0000000..47bd6a8 --- /dev/null +++ b/assets/js/linkPrefetch.js @@ -0,0 +1,219 @@ +window.addEventListener( 'load', () => { + /* check if the browser supports Prefetch */ + const testlink = document.createElement("link"), + supportsPrefetchCheck = testlink.relList && testlink.relList.supports && testlink.relList.supports("prefetch"), + /* check if the user has set a reduced data usage option on the user agent or if the current connection effective type is 2g */ + navigatorConnectionCheck = navigator.connection && (navigator.connection.saveData || (navigator.connection.effectiveType || "").includes("2g")), + intersectionObserverCheck = window.IntersectionObserver && "isIntersecting" in IntersectionObserverEntry.prototype; + + if ( ! supportsPrefetchCheck || navigatorConnectionCheck ) { + return; + } else { + class LP_APP { + constructor(config) { + this.config = config; + this.activeOnDesktop = config.activeOnDesktop; + this.behavior = config.behavior; + this.hoverDelay = config.hoverDelay; + this.ignoreKeywords = config.ignoreKeywords.split(','); + this.instantClick = config.instantClick; + this.mobileActive = config.mobileActive; + this.isMobile = config.isMobile; + this.mobileBehavior = config.mobileBehavior; + this.prefetchedUrls = new Set(); + this.timerIdentifier; + this.eventListenerOptions = { capture: !0, passive: !0 }; + } + /** + * Init + * @returns {void} + */ + init() { + const isChrome = navigator.userAgent.indexOf("Chrome/") > -1, + chromeVersion = isChrome && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Chrome/") + "Chrome/".length)); + + if ( isChrome && chromeVersion < 110 ) {return;} + if ( this.isMobile && ! this.mobileActive ) {return;} + if ( ! this.isMobile && ! this.activeOnDesktop ) {return;} + + if ( ! this.isMobile ) { + if ( 'mouseHover' === this.behavior ) { + let hoverDelay = parseInt(this.hoverDelay); + hoverDelay = isNaN(hoverDelay) ? 60 : hoverDelay; + document.addEventListener("mouseover", this.mouseHover.bind(this), this.eventListenerOptions); + } else if ( 'mouseDown' === this.behavior ) { + if ( this.instantClick ) { + document.addEventListener("mousedown", this.mouseDownToClick.bind(this), this.eventListenerOptions); + } else { + document.addEventListener("mousedown", this.mouseDown.bind(this), this.eventListenerOptions) + } + } + } + + if ( this.mobileActive ) { + if ( 'touchstart' === this.mobileBehavior ) { + document.addEventListener("touchstart", this.touchstart.bind(this), this.eventListenerOptions); + } else if ( 'viewport' && intersectionObserverCheck ) { + this.viewport(); + } + } + } + /** + * Viewport handler + * @returns {void} + */ + viewport() { + const io = new IntersectionObserver((e) => { + e.forEach((e) => { + if (e.isIntersecting) { + const n = e.target; + io.unobserve(n); + this.canPrefetch(n) && this.prefetchIt(n.href); + } + }); + }); + let requestIdleCallback = window.requestIdleCallback || + function (cb) { + var start = Date.now(); + return setTimeout(function () { + cb({ + didTimeout: false, + timeRemaining: function () { + return Math.max(0, 50 - (Date.now() - start)); + } + }); + }, 1); + }; + requestIdleCallback( () => { + return setTimeout(function () { + return document.querySelectorAll("a").forEach(function (a) { + return io.observe(a); + }); + }, 1000); + }, { timeout: 1000 }); + } + /** + * Mouse Down handler + * @param {Event} e - listener event + * @returns {void} + */ + mouseDown(e) { + const el = e.target.closest("a"); + this.canPrefetch(el) && this.prefetchIt(el.href); + } + + /** + * Mouse Down handler for instant click + * @param {Event} e - listener event + * @returns {void} + */ + mouseDownToClick(e) { + //if (performance.now() - o < r) return; + const el = e.target.closest("a"); + if (e.which > 1 || e.metaKey || e.ctrlKey) return; + if (!el) return; + el.addEventListener( + "click", + function (t) { + 'lpappinstantclick' != t.detail && t.preventDefault(); + }, + { capture: !0, passive: !1, once: !0 } + ); + const n = new MouseEvent("click", { view: window, bubbles: !0, cancelable: !1, detail: 'lpappinstantclick' }); + el.dispatchEvent(n); + } + + touchstart(e) { + const el = e.target.closest("a"); + this.canPrefetch(el) && this.prefetchIt(el.href); + } + + /** + * Clean Timers + * @param {Event} t - listener event + * @returns {void} + */ + clean(t) { + if ( t.relatedTarget && t.target.closest("a") == t.relatedTarget.closest("a") || this.timerIdentifier ) { + clearTimeout( this.timerIdentifier ); + this.timerIdentifier = void(0); + } + } + + /** + * Mouse hover function + * @param {Event} e - listener event + * @returns {void} + */ + mouseHover(e) { + if ( !("closest" in e.target) ) return; + const link = e.target.closest("a"); + if ( this.canPrefetch( link ) ) { + link.addEventListener("mouseout", this.clean.bind(this), { passive: !0 }); + this.timerIdentifier = setTimeout(()=> { + this.prefetchIt( link.href ); + this.timerIdentifier = void(0); + }, this.hoverDelay); + } + } + + /** + * Can the url be prefetched or not + * @param {Element} el - link element + * @returns {boolean} - if it can be prefetched + */ + canPrefetch( el ) { + if ( el && el.href ) { + /* it has been just prefetched before */ + if (this.prefetchedUrls.has(el.href)) { + return false; + } + + /* avoid if it is the same url as the actual location */ + if ( el.href.replace(/\/$/, "") !== location.origin.replace(/\/$/, "") && el.href.replace(/\/$/, "") !== location.href.replace(/\/$/, "") ) { + return true; + } + + /* checking exclusions */ + const exclude = this.ignoreKeywords.filter( k => { + if ( el.href.indexOf (k) > -1) { + return k; + } + }) + if ( exclude.length > 0 ) { return false; } + + } + + return false; + } + + /** + * Append link rel=prefetch to the head + * @param {string} url - url to prefetch + * @returns {void} + */ + prefetchIt(url) { + const toPrefechLink = document.createElement("link"); + + toPrefechLink.rel = "prefetch"; + toPrefechLink.href = url; + toPrefechLink.as = "document"; + + document.head.appendChild(toPrefechLink); + this.prefetchedUrls.add(url); + } + } + /* + default config: + 'activeOnDesktop' => true, + 'behavior' =>'mouseHover', + 'hoverDelay' => 60, + 'instantClick' => true , + 'activeOnMobile' => true , + 'mobileBehavior' => 'viewport', + 'ignoreKeywords' =>'wp-admin,#,?', + */ + const lpapp = new LP_APP( window.LP_CONFIG ); + lpapp.init(); + } +}); diff --git a/assets/js/linkPrefetch.min.js b/assets/js/linkPrefetch.min.js new file mode 100644 index 0000000..fe07dc1 --- /dev/null +++ b/assets/js/linkPrefetch.min.js @@ -0,0 +1 @@ +window.addEventListener("load",(()=>{const e=document.createElement("link"),t=e.relList&&e.relList.supports&&e.relList.supports("prefetch"),i=navigator.connection&&(navigator.connection.saveData||(navigator.connection.effectiveType||"").includes("2g")),n=window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype;if(t&&!i){class e{constructor(e){this.config=e,this.activeOnDesktop=e.activeOnDesktop,this.behavior=e.behavior,this.hoverDelay=e.hoverDelay,this.ignoreKeywords=e.ignoreKeywords.split(","),this.instantClick=e.instantClick,this.mobileActive=e.mobileActive,this.isMobile=e.isMobile,this.mobileBehavior=e.mobileBehavior,this.prefetchedUrls=new Set,this.timerIdentifier,this.eventListenerOptions={capture:!0,passive:!0}}init(){const e=navigator.userAgent.indexOf("Chrome/")>-1,t=e&&parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Chrome/")+7));if(!(e&&t<110)&&(!this.isMobile||this.mobileActive)&&(this.isMobile||this.activeOnDesktop)){if(!this.isMobile)if("mouseHover"===this.behavior){let e=parseInt(this.hoverDelay);e=isNaN(e)?60:e,document.addEventListener("mouseover",this.mouseHover.bind(this),this.eventListenerOptions)}else"mouseDown"===this.behavior&&(this.instantClick?document.addEventListener("mousedown",this.mouseDownToClick.bind(this),this.eventListenerOptions):document.addEventListener("mousedown",this.mouseDown.bind(this),this.eventListenerOptions));this.mobileActive&&("touchstart"===this.mobileBehavior?document.addEventListener("touchstart",this.touchstart.bind(this),this.eventListenerOptions):n&&this.viewport())}}viewport(){const e=new IntersectionObserver((t=>{t.forEach((t=>{if(t.isIntersecting){const i=t.target;e.unobserve(i),this.canPrefetch(i)&&this.prefetchIt(i.href)}}))}));(window.requestIdleCallback||function(e){var t=Date.now();return setTimeout((function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})}),1)})((()=>setTimeout((function(){return document.querySelectorAll("a").forEach((function(t){return e.observe(t)}))}),1e3)),{timeout:1e3})}mouseDown(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}mouseDownToClick(e){const t=e.target.closest("a");if(e.which>1||e.metaKey||e.ctrlKey)return;if(!t)return;t.addEventListener("click",(function(e){"lpappinstantclick"!=e.detail&&e.preventDefault()}),{capture:!0,passive:!1,once:!0});const i=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:"lpappinstantclick"});t.dispatchEvent(i)}touchstart(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}clean(e){(e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||this.timerIdentifier)&&(clearTimeout(this.timerIdentifier),this.timerIdentifier=void 0)}mouseHover(e){if(!("closest"in e.target))return;const t=e.target.closest("a");this.canPrefetch(t)&&(t.addEventListener("mouseout",this.clean.bind(this),{passive:!0}),this.timerIdentifier=setTimeout((()=>{this.prefetchIt(t.href),this.timerIdentifier=void 0}),this.hoverDelay))}canPrefetch(e){if(e&&e.href){if(this.prefetchedUrls.has(e.href))return!1;if(e.href.replace(/\/$/,"")!==location.origin.replace(/\/$/,"")&&e.href.replace(/\/$/,"")!==location.href.replace(/\/$/,""))return!0;if(this.ignoreKeywords.filter((t=>{if(e.href.indexOf(t)>-1)return t})).length>0)return!1}return!1}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,t.as="document",document.head.appendChild(t),this.prefetchedUrls.add(e)}}new e(window.LP_CONFIG).init()}})); \ No newline at end of file diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js new file mode 100644 index 0000000..c545a33 --- /dev/null +++ b/components/linkPrefetch/index.js @@ -0,0 +1,136 @@ +import { ToggleField, TextField, TextareaField, SelectField, Container } from "@newfold/ui-component-library"; +const LinkPrefetch = ({methods, constants}) => { + const [settings, setSettings] = methods.useState(constants.store.linkPrefetch) + + const handleChangeOption = ( option, value ) => { + if ( option in settings ) { + const updatedSettings = settings; + updatedSettings[option] = value; + methods.newfoldSettingsApiFetch( + { linkPrefetch: updatedSettings }, + methods.setError, (response) => { + setSettings( (prev)=> { + return { + ...prev, + [option]: value + } + }); + } + ); + } + } + + methods.useUpdateEffect(() => { + methods.setStore({ + ...constants.store, + linkPrefetch: settings, + }); + + methods.makeNotice( + "link-prefetch-change-notice", + constants.text.linkPrefetchTitle, + constants.text.linkPrefetchNoticeTitle, + "success", + 5000 + ); + }, [settings]); + + return( + + handleChangeOption( 'activeOnDesktop', !settings.activeOnDesktop) } + description={constants.text.linkPrefetchActivateOnDekstopDescription} + /> + { settings.activeOnDesktop && ( + <> + handleChangeOption( 'behavior', v) } + description={constants.text.linkPrefetchBehaviorDescription} + > + + + + { + 'mouseDown' === settings.behavior && ( + handleChangeOption( 'instantClick', !settings.instantClick) } + description={constants.text.linkPrefetchInstantClickDescription} + /> + ) + } + { + 'mouseHover' === settings.behavior && ( + handleChangeOption( 'hoverDelay', '' === e.target.value ? 60 : e.target.value )} + type="number" + value={settings.hoverDelay} + description={constants.text.linkPrefetchHoverDelayDescription} + /> + ) + } + + ) + } + handleChangeOption( 'activeOnMobile', !settings.activeOnMobile) } + description={constants.text.linkPrefetchActivateOnMobileDescription} + /> + { settings.activeOnMobile && ( + handleChangeOption( 'mobileBehavior', v) } + description={constants.text.linkPrefetchBehaviorDescription} + > + + + + ) + } + { ( settings.activeOnMobile || settings.activeOnDesktop ) && + handleChangeOption('ignoreKeywords', e.target.value)} + defaultValue={settings.ignoreKeywords} + /> + } + + + ) +} + +export default LinkPrefetch; \ No newline at end of file diff --git a/components/performance/defaultText.js b/components/performance/defaultText.js index 2603b96..a1b9d69 100644 --- a/components/performance/defaultText.js +++ b/components/performance/defaultText.js @@ -22,6 +22,25 @@ const defaultText = { clearCacheDescription: __('We automatically clear your cache as you work (creating content, changing settings, installing plugins and more). But you can manually clear it here to be confident it is fresh.', 'wp-module-performance'), clearCacheNoticeTitle: __('Cache cleared', 'wp-module-performance'), clearCacheTitle: __('Clear Cache', 'wp-module-performance'), + linkPrefetchDescription: __('Some description text here','wp-module-performance'), + linkPrefetchNoticeTitle: __('Link prefetching setting saved','wp-module-performance'), + linkPrefetchTitle: __('Link Prefetch','wp-module-performance'), + linkPrefetchActivateOnDekstopDescription: __('Enable link prefetching on desktop','wp-module-performance'), + linkPrefetchActivateOnDekstopLabel: __('Activate on desktop','wp-module-performance'), + linkPrefetchBehaviorDescription: __('Behavior of the prefetch','wp-module-performance'), + linkPrefetchBehaviorLabel: __('Behavior','wp-module-performance'), + linkPrefetchInstantClickDescription: __('If active the click is triggered on mouse down','wp-module-performance'), + linkPrefetchInstantClickLabel: __('Instant click','wp-module-performance'), + linkPrefetchHoverDelayDescription: __('Set the hover delay in ms','wp-module-performance'), + linkPrefetchHoverDelayLabel: __('Hover delay','wp-module-performance'), + linkPrefetchBehaviorMouseDownLabel: __('Mouse down','wp-module-performance'), + linkPrefetchBehaviorMouseHoverLabel: __('Mouse hover','wp-module-performance'), + linkPrefetchActivateOnMobileDescription: __('Enable link prefetching on Mobile','wp-module-performance'), + linkPrefetchActivateOnMobileLabel: __('Activate on mobile','wp-module-performance'), + linkPrefetchBehaviorMobileTouchstartLabel: __('Touchstart','wp-module-performance'), + linkPrefetchBehaviorMobileViewportLabel: __('Viewport','wp-module-performance'), + linkPrefetchIgnoreKeywordsDescription: __('The list of keywords that should be ignored from prefetching','wp-module-performance'), + linkPrefetchIgnoreKeywordsLabel: __('Ignore keywords','wp-module-performance'), }; export default defaultText; \ No newline at end of file diff --git a/components/performance/index.js b/components/performance/index.js index e6d7483..76672dd 100644 --- a/components/performance/index.js +++ b/components/performance/index.js @@ -2,6 +2,7 @@ import { Container } from '@newfold/ui-component-library'; import { default as CacheSettings } from '../cacheSettings/'; import { default as ClearCache } from '../clearCache/'; import { default as defaultText } from './defaultText'; +import { default as LinkPrefetch } from '../linkPrefetch/'; /** * Performance Module @@ -45,12 +46,18 @@ const Performance = ({methods, constants, Components, ...props}) => { Components={Components} /> - + + + + ); diff --git a/includes/LinkPrefetch.php b/includes/LinkPrefetch.php new file mode 100644 index 0000000..5299287 --- /dev/null +++ b/includes/LinkPrefetch.php @@ -0,0 +1,71 @@ +container = $container; + + add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts') ); + } + /** + * Enqueue de script. + * + * return void + */ + public function enqueueScripts() { + $plugin_url = $this->container->plugin()->url . $this->getScriptPath(); + $settings = get_option( 'nfd_linkPrefetch', $this->getDefaultSettings() ); + + if ( ! $settings['activeOnDesktop'] && ! $settings['activeOnMobile'] ) { return; } + + $settings['isMobile'] = wp_is_mobile(); + + wp_enqueue_script( 'linkprefetcher', $plugin_url, array(), $this->container->plugin()->version, true ); + wp_add_inline_script( 'linkprefetcher', 'window.LP_CONFIG = ' . json_encode( $settings ), 'before' ); + } + + /** + * Get js script path. + * + * return string + */ + public function getScriptPath() { + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; + return 'vendor/newfold-labs/wp-module-performance/assets/js/linkPrefetch' . $suffix . '.js'; + } + + /** + * Get link prefetch default settings. + * + * return array + */ + public function getDefaultSettings() { + return array( + 'activeOnDesktop' => false, + 'behavior' => 'mouseHover', + 'hoverDelay' => 60, + 'instantClick' => false , + 'activeOnMobile' => false , + 'mobileBehavior' => 'viewport', + 'ignoreKeywords' => 'wp-admin,#,?', + ); + } +} \ No newline at end of file diff --git a/includes/Performance.php b/includes/Performance.php index ac50c2f..c7e961c 100644 --- a/includes/Performance.php +++ b/includes/Performance.php @@ -72,13 +72,17 @@ public function __construct( Container $container ) { $cacheManager = new CacheManager( $container ); $cachePurger = new CachePurgingService( $cacheManager->getInstances() ); + $linkPrefetch = new LinkPrefetch( $container ); + // Ensure that purgeable cache types are enabled before showing the UI. if ( $cachePurger->canPurge() ) { add_action( 'admin_bar_menu', array( $this, 'adminBarMenu' ), 100 ); } $container->set( 'cachePurger', $cachePurger ); - + + $container->set( 'linkPrefetch', $linkPrefetch ); + $container->set( 'hasMustUsePlugin', file_exists( WPMU_PLUGIN_DIR . '/endurance-page-cache.php' ) ); } From 03256c3b671ad618f7423126f548ecd7fef1a1c5 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Fri, 25 Oct 2024 12:19:38 +0100 Subject: [PATCH 02/27] added defer attribute to script tag --- includes/LinkPrefetch.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/includes/LinkPrefetch.php b/includes/LinkPrefetch.php index 5299287..7e4a80e 100644 --- a/includes/LinkPrefetch.php +++ b/includes/LinkPrefetch.php @@ -24,6 +24,7 @@ public function __construct( Container $container ) { $this->container = $container; add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts') ); + add_filter('script_loader_tag', array( $this, 'addDefer' ), 10, 2 ); } /** * Enqueue de script. @@ -40,6 +41,7 @@ public function enqueueScripts() { wp_enqueue_script( 'linkprefetcher', $plugin_url, array(), $this->container->plugin()->version, true ); wp_add_inline_script( 'linkprefetcher', 'window.LP_CONFIG = ' . json_encode( $settings ), 'before' ); + } /** @@ -68,4 +70,19 @@ public function getDefaultSettings() { 'ignoreKeywords' => 'wp-admin,#,?', ); } + + /** + * Add defer attribute to the script. + * + * @param string $tag html tag. + * @param string $handle handle of the script. + * + * return string + */ + public function addDefer( $tag, $handle ) { + if ('linkprefetcher' === $handle && false === strpos($tag, 'defer')) { + $tag = preg_replace(':(?=>):', ' defer', $tag); + } + return $tag; + } } \ No newline at end of file From 414553400da9503c177d5ec2ab3788c2204a9d52 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Fri, 25 Oct 2024 12:58:51 +0100 Subject: [PATCH 03/27] phpcs on new class --- includes/LinkPrefetch.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/includes/LinkPrefetch.php b/includes/LinkPrefetch.php index 7e4a80e..de1a281 100644 --- a/includes/LinkPrefetch.php +++ b/includes/LinkPrefetch.php @@ -23,8 +23,8 @@ class LinkPrefetch { public function __construct( Container $container ) { $this->container = $container; - add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts') ); - add_filter('script_loader_tag', array( $this, 'addDefer' ), 10, 2 ); + add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts' ) ); + add_filter( 'script_loader_tag', array( $this, 'addDefer' ), 10, 2 ); } /** * Enqueue de script. @@ -40,8 +40,7 @@ public function enqueueScripts() { $settings['isMobile'] = wp_is_mobile(); wp_enqueue_script( 'linkprefetcher', $plugin_url, array(), $this->container->plugin()->version, true ); - wp_add_inline_script( 'linkprefetcher', 'window.LP_CONFIG = ' . json_encode( $settings ), 'before' ); - + wp_add_inline_script( 'linkprefetcher', 'window.LP_CONFIG = ' . wp_json_encode( $settings ), 'before' ); } /** @@ -64,8 +63,8 @@ public function getDefaultSettings() { 'activeOnDesktop' => false, 'behavior' => 'mouseHover', 'hoverDelay' => 60, - 'instantClick' => false , - 'activeOnMobile' => false , + 'instantClick' => false, + 'activeOnMobile' => false, 'mobileBehavior' => 'viewport', 'ignoreKeywords' => 'wp-admin,#,?', ); @@ -76,13 +75,13 @@ public function getDefaultSettings() { * * @param string $tag html tag. * @param string $handle handle of the script. - * + * * return string */ public function addDefer( $tag, $handle ) { - if ('linkprefetcher' === $handle && false === strpos($tag, 'defer')) { - $tag = preg_replace(':(?=>):', ' defer', $tag); + if ( 'linkprefetcher' === $handle && false === strpos( $tag, 'defer' ) ) { + $tag = preg_replace( ':(?=>):', ' defer', $tag ); } return $tag; } -} \ No newline at end of file +} From ba1198a8ec7546ca79b790ff2ca08dd03a3d5cc6 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 4 Nov 2024 11:26:56 +0000 Subject: [PATCH 04/27] added copy text and changed toggle style --- components/linkPrefetch/index.js | 119 ++++++++++++++------------ components/performance/defaultText.js | 22 ++--- includes/LinkPrefetch.php | 2 +- 3 files changed, 74 insertions(+), 69 deletions(-) diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index c545a33..8f85ed6 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -1,6 +1,13 @@ -import { ToggleField, TextField, TextareaField, SelectField, Container } from "@newfold/ui-component-library"; +import { Toggle, TextField, TextareaField, SelectField, Container } from "@newfold/ui-component-library"; + const LinkPrefetch = ({methods, constants}) => { - const [settings, setSettings] = methods.useState(constants.store.linkPrefetch) + const [settings, setSettings] = methods.useState(constants.store?.linkPrefetch ? constants.store?.linkPrefetch : null) + + if ( !settings ) { + return; + } + + console.log(methods.NewfoldRuntime) const handleChangeOption = ( option, value ) => { if ( option in settings ) { @@ -36,69 +43,66 @@ const LinkPrefetch = ({methods, constants}) => { }, [settings]); return( + <> - handleChangeOption( 'activeOnDesktop', !settings.activeOnDesktop) } - description={constants.text.linkPrefetchActivateOnDekstopDescription} - /> +
+
+ +
+ {constants.text.linkPrefetchActivateOnDekstopDescription} +
+
+ handleChangeOption( 'activeOnDesktop', !settings.activeOnDesktop) } + /> +
{ settings.activeOnDesktop && ( - <> - handleChangeOption( 'behavior', v) } - description={constants.text.linkPrefetchBehaviorDescription} - > - - - - { - 'mouseDown' === settings.behavior && ( - handleChangeOption( 'instantClick', !settings.instantClick) } - description={constants.text.linkPrefetchInstantClickDescription} - /> - ) - } - { - 'mouseHover' === settings.behavior && ( - handleChangeOption( 'hoverDelay', '' === e.target.value ? 60 : e.target.value )} - type="number" - value={settings.hoverDelay} - description={constants.text.linkPrefetchHoverDelayDescription} - /> - ) - } - + handleChangeOption( 'behavior', v) } + description={ 'mouseDown' === settings.behavior ? constants.text.linkPrefetchBehaviorMouseDownDescription : constants.text.linkPrefetchBehaviorMouseHoverDescription} + > + + + ) } - +
+ +
+ {constants.text.linkPrefetchActivateOnMobileDescription} +
+
+ handleChangeOption('activeOnMobile', !settings.activeOnMobile) } + /> + +{/* handleChangeOption( 'activeOnMobile', !settings.activeOnMobile) } + onChange={() => handleChangeOption('activeOnMobile', !settings.activeOnMobile) } description={constants.text.linkPrefetchActivateOnMobileDescription} - /> + /> */} { settings.activeOnMobile && ( { value={settings.mobileBehavior} selectedLabel={'touchstart' === settings.mobileBehavior ? constants.text.linkPrefetchBehaviorMobileTouchstartLabel : constants.text.linkPrefetchBehaviorMobileViewportLabel} onChange={(v) => handleChangeOption( 'mobileBehavior', v) } - description={constants.text.linkPrefetchBehaviorDescription} + description={'touchstart' === settings.mobileBehavior ? constants.text.linkPrefetchBehaviorMobileTouchstartDescription : constants.text.linkPrefetchBehaviorMobileViewportDescription} > { ) } { ( settings.activeOnMobile || settings.activeOnDesktop ) && - handleChangeOption('ignoreKeywords', e.target.value)} - defaultValue={settings.ignoreKeywords} + value={settings.ignoreKeywords} /> }
+ ) } diff --git a/components/performance/defaultText.js b/components/performance/defaultText.js index a1b9d69..8ce5d23 100644 --- a/components/performance/defaultText.js +++ b/components/performance/defaultText.js @@ -22,25 +22,25 @@ const defaultText = { clearCacheDescription: __('We automatically clear your cache as you work (creating content, changing settings, installing plugins and more). But you can manually clear it here to be confident it is fresh.', 'wp-module-performance'), clearCacheNoticeTitle: __('Cache cleared', 'wp-module-performance'), clearCacheTitle: __('Clear Cache', 'wp-module-performance'), - linkPrefetchDescription: __('Some description text here','wp-module-performance'), + linkPrefetchDescription: __('Asks the browser to download and cache links on the page ahead of them being clicked on, so that when they are clicked they load almost instantly. ','wp-module-performance'), linkPrefetchNoticeTitle: __('Link prefetching setting saved','wp-module-performance'), linkPrefetchTitle: __('Link Prefetch','wp-module-performance'), linkPrefetchActivateOnDekstopDescription: __('Enable link prefetching on desktop','wp-module-performance'), linkPrefetchActivateOnDekstopLabel: __('Activate on desktop','wp-module-performance'), linkPrefetchBehaviorDescription: __('Behavior of the prefetch','wp-module-performance'), linkPrefetchBehaviorLabel: __('Behavior','wp-module-performance'), - linkPrefetchInstantClickDescription: __('If active the click is triggered on mouse down','wp-module-performance'), - linkPrefetchInstantClickLabel: __('Instant click','wp-module-performance'), - linkPrefetchHoverDelayDescription: __('Set the hover delay in ms','wp-module-performance'), - linkPrefetchHoverDelayLabel: __('Hover delay','wp-module-performance'), - linkPrefetchBehaviorMouseDownLabel: __('Mouse down','wp-module-performance'), - linkPrefetchBehaviorMouseHoverLabel: __('Mouse hover','wp-module-performance'), + linkPrefetchBehaviorMouseDownLabel: __('Prefetch on Mouse down','wp-module-performance'), + linkPrefetchBehaviorMouseDownDescription: __('Prefetch on Mouse Down: Starts loading the page as soon as you click down, for faster response when you release the click.','wp-module-performance'), + linkPrefetchBehaviorMouseHoverLabel: __('Prefetch on Mouse Hover (Recommended)','wp-module-performance'), + linkPrefetchBehaviorMouseHoverDescription: __('Prefetch on Mouse Hover: Begins loading the page the moment your cursor hovers over a link','wp-module-performance'), linkPrefetchActivateOnMobileDescription: __('Enable link prefetching on Mobile','wp-module-performance'), linkPrefetchActivateOnMobileLabel: __('Activate on mobile','wp-module-performance'), - linkPrefetchBehaviorMobileTouchstartLabel: __('Touchstart','wp-module-performance'), - linkPrefetchBehaviorMobileViewportLabel: __('Viewport','wp-module-performance'), - linkPrefetchIgnoreKeywordsDescription: __('The list of keywords that should be ignored from prefetching','wp-module-performance'), - linkPrefetchIgnoreKeywordsLabel: __('Ignore keywords','wp-module-performance'), + linkPrefetchBehaviorMobileTouchstartLabel: __('Prefetch on Touchstart (Recommended)','wp-module-performance'), + linkPrefetchBehaviorMobileTouchstartDescription: __('Prefetch on Touch Start: Instantly starts loading the page as soon as you tap the screen, ensuring a quicker response when you lift your finger.','wp-module-performance'), + linkPrefetchBehaviorMobileViewportLabel: __('Prefetch Above the Fold','wp-module-performance'), + linkPrefetchBehaviorMobileViewportDescription: __('Prefetch Above the Fold: Loads links in your current view instantly, ensuring they\'re ready when you need them.','wp-module-performance'), + linkPrefetchIgnoreKeywordsDescription: __('Exclude Keywords: A comma separated list of words or strings that will exclude a link from being prefetched. For example, excluding "app" will prevent https://example.com/apple from being prefetched.','wp-module-performance'), + linkPrefetchIgnoreKeywordsLabel: __('Exclude keywords','wp-module-performance'), }; export default defaultText; \ No newline at end of file diff --git a/includes/LinkPrefetch.php b/includes/LinkPrefetch.php index de1a281..f06f40e 100644 --- a/includes/LinkPrefetch.php +++ b/includes/LinkPrefetch.php @@ -65,7 +65,7 @@ public function getDefaultSettings() { 'hoverDelay' => 60, 'instantClick' => false, 'activeOnMobile' => false, - 'mobileBehavior' => 'viewport', + 'mobileBehavior' => 'touchstart', 'ignoreKeywords' => 'wp-admin,#,?', ); } From 3f9047010081d902f0eb922ce6c101a86801ad76 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 4 Nov 2024 15:01:04 +0000 Subject: [PATCH 05/27] added restapi to manage the settings, adding bottom margin to fields --- assets/js/linkPrefetch.js | 6 +- components/linkPrefetch/index.js | 57 +++++----- includes/LinkPrefetch.php | 40 +++++++ includes/RestApi/LinkPrefetchController.php | 112 ++++++++++++++++++++ 4 files changed, 181 insertions(+), 34 deletions(-) create mode 100644 includes/RestApi/LinkPrefetchController.php diff --git a/assets/js/linkPrefetch.js b/assets/js/linkPrefetch.js index 47bd6a8..2e0d338 100644 --- a/assets/js/linkPrefetch.js +++ b/assets/js/linkPrefetch.js @@ -17,7 +17,7 @@ window.addEventListener( 'load', () => { this.hoverDelay = config.hoverDelay; this.ignoreKeywords = config.ignoreKeywords.split(','); this.instantClick = config.instantClick; - this.mobileActive = config.mobileActive; + this.mobileActive = config.activeOnMobile; this.isMobile = config.isMobile; this.mobileBehavior = config.mobileBehavior; this.prefetchedUrls = new Set(); @@ -35,7 +35,7 @@ window.addEventListener( 'load', () => { if ( isChrome && chromeVersion < 110 ) {return;} if ( this.isMobile && ! this.mobileActive ) {return;} if ( ! this.isMobile && ! this.activeOnDesktop ) {return;} - + if ( ! this.isMobile ) { if ( 'mouseHover' === this.behavior ) { let hoverDelay = parseInt(this.hoverDelay); @@ -49,7 +49,7 @@ window.addEventListener( 'load', () => { } } } - + if ( this.mobileActive ) { if ( 'touchstart' === this.mobileBehavior ) { document.addEventListener("touchstart", this.touchstart.bind(this), this.eventListenerOptions); diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index 8f85ed6..7480a31 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -1,29 +1,29 @@ -import { Toggle, TextField, TextareaField, SelectField, Container } from "@newfold/ui-component-library"; +import { Toggle, TextField, SelectField, Container } from "@newfold/ui-component-library"; const LinkPrefetch = ({methods, constants}) => { - const [settings, setSettings] = methods.useState(constants.store?.linkPrefetch ? constants.store?.linkPrefetch : null) - - if ( !settings ) { - return; - } - - console.log(methods.NewfoldRuntime) + const [settings, setSettings] = methods.useState(methods.NewfoldRuntime.sdk.linkPrefetch.settings); + const [isError, setIsError] = methods.useState(false); + const apiUrl = methods.NewfoldRuntime.createApiUrl("/newfold-ecommerce/v1/linkprefetch/update"); const handleChangeOption = ( option, value ) => { if ( option in settings ) { const updatedSettings = settings; updatedSettings[option] = value; - methods.newfoldSettingsApiFetch( - { linkPrefetch: updatedSettings }, - methods.setError, (response) => { - setSettings( (prev)=> { - return { - ...prev, - [option]: value - } - }); - } - ); + methods.apiFetch({ + url: apiUrl, + method: "POST", + data: {settings: updatedSettings} + }).then((result)=>{ + console.log('updating settings',result) + setSettings( (prev)=> { + return { + ...prev, + [option]: value + } + }); + }).catch((error) => { + setIsError(error.message); + }); } } @@ -36,11 +36,11 @@ const LinkPrefetch = ({methods, constants}) => { methods.makeNotice( "link-prefetch-change-notice", constants.text.linkPrefetchTitle, - constants.text.linkPrefetchNoticeTitle, - "success", + !isError ? constants.text.linkPrefetchNoticeTitle : isError, + !isError ? "success" : "error", 5000 ); - }, [settings]); + }, [settings, isError]); return( <> @@ -48,7 +48,7 @@ const LinkPrefetch = ({methods, constants}) => { title={constants.text.linkPrefetchTitle} description={constants.text.linkPrefetchDescription} > -
+
@@ -70,6 +70,7 @@ const LinkPrefetch = ({methods, constants}) => { selectedLabel={'mouseDown' === settings.behavior ? constants.text.linkPrefetchBehaviorMouseDownLabel : constants.text.linkPrefetchBehaviorMouseHoverLabel} onChange={(v) => handleChangeOption( 'behavior', v) } description={ 'mouseDown' === settings.behavior ? constants.text.linkPrefetchBehaviorMouseDownDescription : constants.text.linkPrefetchBehaviorMouseHoverDescription} + className='nfd-mb-6' > { ) } -
+
@@ -96,13 +97,6 @@ const LinkPrefetch = ({methods, constants}) => { onChange={() => handleChangeOption('activeOnMobile', !settings.activeOnMobile) } />
-{/* handleChangeOption('activeOnMobile', !settings.activeOnMobile) } - description={constants.text.linkPrefetchActivateOnMobileDescription} - /> */} { settings.activeOnMobile && ( { selectedLabel={'touchstart' === settings.mobileBehavior ? constants.text.linkPrefetchBehaviorMobileTouchstartLabel : constants.text.linkPrefetchBehaviorMobileViewportLabel} onChange={(v) => handleChangeOption( 'mobileBehavior', v) } description={'touchstart' === settings.mobileBehavior ? constants.text.linkPrefetchBehaviorMobileTouchstartDescription : constants.text.linkPrefetchBehaviorMobileViewportDescription} + className='nfd-mb-6' > container = $container; + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + add_filter( 'newfold-runtime', array( $this, 'add_to_runtime' ) ); + add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts' ) ); add_filter( 'script_loader_tag', array( $this, 'addDefer' ), 10, 2 ); } + + /** + * Register API routes. + */ + public function register_routes() { + foreach ( $this->controllers as $Controller ) { + /** + * Get an instance of the WP_REST_Controller. + * + * @var $instance \WP_REST_Controller + */ + $instance = new $Controller( $this->container ); + $instance->register_routes(); + } + } + /** + * Add values to the runtime object. + * + * @param array $sdk The runtime object. + * + * @return array + */ + public function add_to_runtime( $sdk ) { + $values = array( + 'settings' => get_option( 'nfd_linkPrefetch', $this->getDefaultSettings() ), + ); + return array_merge( $sdk, array( 'linkPrefetch' => $values ) ); + } /** * Enqueue de script. * diff --git a/includes/RestApi/LinkPrefetchController.php b/includes/RestApi/LinkPrefetchController.php new file mode 100644 index 0000000..d5504e6 --- /dev/null +++ b/includes/RestApi/LinkPrefetchController.php @@ -0,0 +1,112 @@ +container = $container; + } + + /** + * Registers rest routes for PluginsController class. + * + * @return void + */ + public function register_routes() { + \register_rest_route( + $this->namespace, + $this->rest_base . '/settings', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_settings' ), + 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), + ), + ) + ); + \register_rest_route( + $this->namespace, + $this->rest_base . '/update', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'update_settings' ), + 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), + ), + ) + ); + } + + /** + * Get the settings + * + * @return \WP_REST_Response + */ + public function get_settings() { + return new \WP_REST_Response( + array( + 'settings' => get_option( 'nfd_linkPrefetch', $this->container->get( 'linkPrefetch' )->getDefaultSettings() ), + ), + 200 + ); + } + + /** + * Update the settings + * + * @param \WP_REST_Request $request the request. + * @return \WP_REST_Response + */ + public function update_settings( \WP_REST_Request $request ) { + $settings = $request->get_param( 'settings' ); + if ( is_array( $settings ) && update_option( 'nfd_linkPrefetch', $settings ) ) { + return new \WP_REST_Response( + array( + 'result' => true, + ), + 200 + ); + } + + return new \WP_REST_Response( + array( + 'result' => false, + ), + 400 + ); + } +} From fe39f82fb4f08004cb33efa440fcd00595f53a34 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Thu, 7 Nov 2024 11:47:38 +0000 Subject: [PATCH 06/27] removed console.log --- components/linkPrefetch/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index 7480a31..1fb9096 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -14,7 +14,6 @@ const LinkPrefetch = ({methods, constants}) => { method: "POST", data: {settings: updatedSettings} }).then((result)=>{ - console.log('updating settings',result) setSettings( (prev)=> { return { ...prev, From 61fa41ffc29894d96458cf06fc55206756c7cf1a Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 11 Nov 2024 12:57:33 +0000 Subject: [PATCH 07/27] fixed check for mobile --- assets/js/linkPrefetch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/linkPrefetch.js b/assets/js/linkPrefetch.js index 2e0d338..1a21489 100644 --- a/assets/js/linkPrefetch.js +++ b/assets/js/linkPrefetch.js @@ -49,8 +49,8 @@ window.addEventListener( 'load', () => { } } } - - if ( this.mobileActive ) { + + if ( this.mobileActive && this.isMobile ) { if ( 'touchstart' === this.mobileBehavior ) { document.addEventListener("touchstart", this.touchstart.bind(this), this.eventListenerOptions); } else if ( 'viewport' && intersectionObserverCheck ) { From 8374c5f87d2382ae5ae2adcf3527e8bed3a69535 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 11 Nov 2024 12:59:26 +0000 Subject: [PATCH 08/27] added fix for minified js --- assets/js/linkPrefetch.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/linkPrefetch.min.js b/assets/js/linkPrefetch.min.js index fe07dc1..c6ea1d4 100644 --- a/assets/js/linkPrefetch.min.js +++ b/assets/js/linkPrefetch.min.js @@ -1 +1 @@ -window.addEventListener("load",(()=>{const e=document.createElement("link"),t=e.relList&&e.relList.supports&&e.relList.supports("prefetch"),i=navigator.connection&&(navigator.connection.saveData||(navigator.connection.effectiveType||"").includes("2g")),n=window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype;if(t&&!i){class e{constructor(e){this.config=e,this.activeOnDesktop=e.activeOnDesktop,this.behavior=e.behavior,this.hoverDelay=e.hoverDelay,this.ignoreKeywords=e.ignoreKeywords.split(","),this.instantClick=e.instantClick,this.mobileActive=e.mobileActive,this.isMobile=e.isMobile,this.mobileBehavior=e.mobileBehavior,this.prefetchedUrls=new Set,this.timerIdentifier,this.eventListenerOptions={capture:!0,passive:!0}}init(){const e=navigator.userAgent.indexOf("Chrome/")>-1,t=e&&parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Chrome/")+7));if(!(e&&t<110)&&(!this.isMobile||this.mobileActive)&&(this.isMobile||this.activeOnDesktop)){if(!this.isMobile)if("mouseHover"===this.behavior){let e=parseInt(this.hoverDelay);e=isNaN(e)?60:e,document.addEventListener("mouseover",this.mouseHover.bind(this),this.eventListenerOptions)}else"mouseDown"===this.behavior&&(this.instantClick?document.addEventListener("mousedown",this.mouseDownToClick.bind(this),this.eventListenerOptions):document.addEventListener("mousedown",this.mouseDown.bind(this),this.eventListenerOptions));this.mobileActive&&("touchstart"===this.mobileBehavior?document.addEventListener("touchstart",this.touchstart.bind(this),this.eventListenerOptions):n&&this.viewport())}}viewport(){const e=new IntersectionObserver((t=>{t.forEach((t=>{if(t.isIntersecting){const i=t.target;e.unobserve(i),this.canPrefetch(i)&&this.prefetchIt(i.href)}}))}));(window.requestIdleCallback||function(e){var t=Date.now();return setTimeout((function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})}),1)})((()=>setTimeout((function(){return document.querySelectorAll("a").forEach((function(t){return e.observe(t)}))}),1e3)),{timeout:1e3})}mouseDown(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}mouseDownToClick(e){const t=e.target.closest("a");if(e.which>1||e.metaKey||e.ctrlKey)return;if(!t)return;t.addEventListener("click",(function(e){"lpappinstantclick"!=e.detail&&e.preventDefault()}),{capture:!0,passive:!1,once:!0});const i=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:"lpappinstantclick"});t.dispatchEvent(i)}touchstart(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}clean(e){(e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||this.timerIdentifier)&&(clearTimeout(this.timerIdentifier),this.timerIdentifier=void 0)}mouseHover(e){if(!("closest"in e.target))return;const t=e.target.closest("a");this.canPrefetch(t)&&(t.addEventListener("mouseout",this.clean.bind(this),{passive:!0}),this.timerIdentifier=setTimeout((()=>{this.prefetchIt(t.href),this.timerIdentifier=void 0}),this.hoverDelay))}canPrefetch(e){if(e&&e.href){if(this.prefetchedUrls.has(e.href))return!1;if(e.href.replace(/\/$/,"")!==location.origin.replace(/\/$/,"")&&e.href.replace(/\/$/,"")!==location.href.replace(/\/$/,""))return!0;if(this.ignoreKeywords.filter((t=>{if(e.href.indexOf(t)>-1)return t})).length>0)return!1}return!1}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,t.as="document",document.head.appendChild(t),this.prefetchedUrls.add(e)}}new e(window.LP_CONFIG).init()}})); \ No newline at end of file +window.addEventListener("load",(()=>{const e=document.createElement("link"),t=e.relList&&e.relList.supports&&e.relList.supports("prefetch"),i=navigator.connection&&(navigator.connection.saveData||(navigator.connection.effectiveType||"").includes("2g")),n=window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype;if(t&&!i){class e{constructor(e){this.config=e,this.activeOnDesktop=e.activeOnDesktop,this.behavior=e.behavior,this.hoverDelay=e.hoverDelay,this.ignoreKeywords=e.ignoreKeywords.split(","),this.instantClick=e.instantClick,this.mobileActive=e.activeOnMobile,this.isMobile=e.isMobile,this.mobileBehavior=e.mobileBehavior,this.prefetchedUrls=new Set,this.timerIdentifier,this.eventListenerOptions={capture:!0,passive:!0}}init(){const e=navigator.userAgent.indexOf("Chrome/")>-1,t=e&&parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Chrome/")+7));if(!(e&&t<110)&&(!this.isMobile||this.mobileActive)&&(this.isMobile||this.activeOnDesktop)){if(!this.isMobile)if("mouseHover"===this.behavior){let e=parseInt(this.hoverDelay);e=isNaN(e)?60:e,document.addEventListener("mouseover",this.mouseHover.bind(this),this.eventListenerOptions)}else"mouseDown"===this.behavior&&(this.instantClick?document.addEventListener("mousedown",this.mouseDownToClick.bind(this),this.eventListenerOptions):document.addEventListener("mousedown",this.mouseDown.bind(this),this.eventListenerOptions));this.mobileActive&&this.isMobile&&("touchstart"===this.mobileBehavior?document.addEventListener("touchstart",this.touchstart.bind(this),this.eventListenerOptions):n&&this.viewport())}}viewport(){const e=new IntersectionObserver((t=>{t.forEach((t=>{if(t.isIntersecting){const i=t.target;e.unobserve(i),this.canPrefetch(i)&&this.prefetchIt(i.href)}}))}));(window.requestIdleCallback||function(e){var t=Date.now();return setTimeout((function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})}),1)})((()=>setTimeout((function(){return document.querySelectorAll("a").forEach((function(t){return e.observe(t)}))}),1e3)),{timeout:1e3})}mouseDown(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}mouseDownToClick(e){const t=e.target.closest("a");if(e.which>1||e.metaKey||e.ctrlKey)return;if(!t)return;t.addEventListener("click",(function(e){"lpappinstantclick"!=e.detail&&e.preventDefault()}),{capture:!0,passive:!1,once:!0});const i=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:"lpappinstantclick"});t.dispatchEvent(i)}touchstart(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}clean(e){(e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||this.timerIdentifier)&&(clearTimeout(this.timerIdentifier),this.timerIdentifier=void 0)}mouseHover(e){if(!("closest"in e.target))return;const t=e.target.closest("a");this.canPrefetch(t)&&(t.addEventListener("mouseout",this.clean.bind(this),{passive:!0}),this.timerIdentifier=setTimeout((()=>{this.prefetchIt(t.href),this.timerIdentifier=void 0}),this.hoverDelay))}canPrefetch(e){if(e&&e.href){if(this.prefetchedUrls.has(e.href))return!1;if(e.href.replace(/\/$/,"")!==location.origin.replace(/\/$/,"")&&e.href.replace(/\/$/,"")!==location.href.replace(/\/$/,""))return!0;if(this.ignoreKeywords.filter((t=>{if(e.href.indexOf(t)>-1)return t})).length>0)return!1}return!1}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,t.as="document",document.head.appendChild(t),this.prefetchedUrls.add(e)}}new e(window.LP_CONFIG).init()}})); \ No newline at end of file From 49feb011b96b4197008b3d2ac7d466027c7ec78f Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 09:34:21 +0000 Subject: [PATCH 09/27] Update includes/RestApi/LinkPrefetchController.php Co-authored-by: Arun Shenoy --- includes/RestApi/LinkPrefetchController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/RestApi/LinkPrefetchController.php b/includes/RestApi/LinkPrefetchController.php index d5504e6..c52c66e 100644 --- a/includes/RestApi/LinkPrefetchController.php +++ b/includes/RestApi/LinkPrefetchController.php @@ -23,7 +23,7 @@ class LinkPrefetchController { * * @var string */ - protected $rest_base = '/linkprefetch'; + protected $rest_base = '/link-prefetch'; /** * Container loaded from the brand plugin. From 24dff12b82686c3c528ea0c0c44310bfe0a2519e Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 09:34:33 +0000 Subject: [PATCH 10/27] Update includes/RestApi/LinkPrefetchController.php Co-authored-by: Arun Shenoy --- includes/RestApi/LinkPrefetchController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/RestApi/LinkPrefetchController.php b/includes/RestApi/LinkPrefetchController.php index c52c66e..1ac7f2f 100644 --- a/includes/RestApi/LinkPrefetchController.php +++ b/includes/RestApi/LinkPrefetchController.php @@ -16,7 +16,7 @@ class LinkPrefetchController { * * @var string */ - protected $namespace = 'newfold-ecommerce/v1'; + protected $namespace = 'newfold-performance/v1'; /** * REST base From ecbdb4738da74952fe5f85f0e87e57fdfc7a6db5 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 09:38:57 +0000 Subject: [PATCH 11/27] updated LinkPrefetchController with more fix --- includes/RestApi/LinkPrefetchController.php | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/includes/RestApi/LinkPrefetchController.php b/includes/RestApi/LinkPrefetchController.php index 1ac7f2f..4a371b1 100644 --- a/includes/RestApi/LinkPrefetchController.php +++ b/includes/RestApi/LinkPrefetchController.php @@ -3,7 +3,7 @@ namespace NewfoldLabs\WP\Module\Performance\RestApi; use NewfoldLabs\WP\Module\ECommerce\Permissions; -use NewfoldLabs\WP\ModuleLoader\Container; +use NewfoldLabs\WP\Module\Performance\LinkPrefetch; /** * Class LinkPrefetchController @@ -25,22 +25,6 @@ class LinkPrefetchController { */ protected $rest_base = '/link-prefetch'; - /** - * Container loaded from the brand plugin. - * - * @var Container - */ - protected $container; - - /** - * Constructor - * - * @param Container $container the container. - */ - public function __construct( Container $container ) { - $this->container = $container; - } - /** * Registers rest routes for PluginsController class. * @@ -79,7 +63,7 @@ public function register_routes() { public function get_settings() { return new \WP_REST_Response( array( - 'settings' => get_option( 'nfd_linkPrefetch', $this->container->get( 'linkPrefetch' )->getDefaultSettings() ), + 'settings' => get_option( 'nfd_linkPrefetch', LinkPrefetch::getDefaultSettings() ), ), 200 ); From f743bfecac53c1ef75070fe9ee59fca10e03abc4 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 09:52:13 +0000 Subject: [PATCH 12/27] adding suggested improvements to LinkPrefetchController.php --- includes/RestApi/LinkPrefetchController.php | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/includes/RestApi/LinkPrefetchController.php b/includes/RestApi/LinkPrefetchController.php index 4a371b1..993786a 100644 --- a/includes/RestApi/LinkPrefetchController.php +++ b/includes/RestApi/LinkPrefetchController.php @@ -31,25 +31,23 @@ class LinkPrefetchController { * @return void */ public function register_routes() { - \register_rest_route( + register_rest_route( $this->namespace, $this->rest_base . '/settings', array( array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array( $this, 'get_settings' ), - 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), + 'permission_callback' => function () { + return current_user_can( 'manage_options' ); + }, ), - ) - ); - \register_rest_route( - $this->namespace, - $this->rest_base . '/update', - array( array( 'methods' => \WP_REST_Server::CREATABLE, 'callback' => array( $this, 'update_settings' ), - 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), + 'permission_callback' => function () { + return current_user_can( 'manage_options' ); + }, ), ) ); @@ -63,7 +61,7 @@ public function register_routes() { public function get_settings() { return new \WP_REST_Response( array( - 'settings' => get_option( 'nfd_linkPrefetch', LinkPrefetch::getDefaultSettings() ), + 'settings' => get_option( 'nfd_link_prefetch_settings', LinkPrefetch::getDefaultSettings() ), ), 200 ); @@ -77,18 +75,20 @@ public function get_settings() { */ public function update_settings( \WP_REST_Request $request ) { $settings = $request->get_param( 'settings' ); - if ( is_array( $settings ) && update_option( 'nfd_linkPrefetch', $settings ) ) { + if ( is_array( $settings ) ) { + $updated = update_option( 'nfd_link_prefetch_settings', $settings ); return new \WP_REST_Response( array( - 'result' => true, + 'result' => $updated, ), - 200 + $updated ? 200 : 400 ); } return new \WP_REST_Response( array( 'result' => false, + 'message' => 'Invalid settings format', ), 400 ); From b7f0abd65b54c6dfe23ca8a8096fa0db27e3c800 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 09:59:23 +0000 Subject: [PATCH 13/27] removed unused Permissions class and removed LinkPrefetch new and container set in performance.php --- includes/Performance.php | 6 +----- includes/RestApi/LinkPrefetchController.php | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/includes/Performance.php b/includes/Performance.php index c7e961c..ac50c2f 100644 --- a/includes/Performance.php +++ b/includes/Performance.php @@ -72,17 +72,13 @@ public function __construct( Container $container ) { $cacheManager = new CacheManager( $container ); $cachePurger = new CachePurgingService( $cacheManager->getInstances() ); - $linkPrefetch = new LinkPrefetch( $container ); - // Ensure that purgeable cache types are enabled before showing the UI. if ( $cachePurger->canPurge() ) { add_action( 'admin_bar_menu', array( $this, 'adminBarMenu' ), 100 ); } $container->set( 'cachePurger', $cachePurger ); - - $container->set( 'linkPrefetch', $linkPrefetch ); - + $container->set( 'hasMustUsePlugin', file_exists( WPMU_PLUGIN_DIR . '/endurance-page-cache.php' ) ); } diff --git a/includes/RestApi/LinkPrefetchController.php b/includes/RestApi/LinkPrefetchController.php index 993786a..31f29ee 100644 --- a/includes/RestApi/LinkPrefetchController.php +++ b/includes/RestApi/LinkPrefetchController.php @@ -2,7 +2,6 @@ namespace NewfoldLabs\WP\Module\Performance\RestApi; -use NewfoldLabs\WP\Module\ECommerce\Permissions; use NewfoldLabs\WP\Module\Performance\LinkPrefetch; /** @@ -10,7 +9,6 @@ */ class LinkPrefetchController { - /** * REST namespace * From 1427769f85921913c04193594ba942905f1266f7 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 10:09:28 +0000 Subject: [PATCH 14/27] defaultText.js fix --- components/performance/defaultText.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/performance/defaultText.js b/components/performance/defaultText.js index 8ce5d23..8b1c399 100644 --- a/components/performance/defaultText.js +++ b/components/performance/defaultText.js @@ -25,8 +25,8 @@ const defaultText = { linkPrefetchDescription: __('Asks the browser to download and cache links on the page ahead of them being clicked on, so that when they are clicked they load almost instantly. ','wp-module-performance'), linkPrefetchNoticeTitle: __('Link prefetching setting saved','wp-module-performance'), linkPrefetchTitle: __('Link Prefetch','wp-module-performance'), - linkPrefetchActivateOnDekstopDescription: __('Enable link prefetching on desktop','wp-module-performance'), - linkPrefetchActivateOnDekstopLabel: __('Activate on desktop','wp-module-performance'), + linkPrefetchActivateOnDesktopDescription: __('Enable link prefetching on desktop','wp-module-performance'), + linkPrefetchActivateOnDesktopLabel: __('Activate on desktop','wp-module-performance'), linkPrefetchBehaviorDescription: __('Behavior of the prefetch','wp-module-performance'), linkPrefetchBehaviorLabel: __('Behavior','wp-module-performance'), linkPrefetchBehaviorMouseDownLabel: __('Prefetch on Mouse down','wp-module-performance'), From 62999b1b3152e965deabd15c33df4471a9b0bdc6 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 10:22:18 +0000 Subject: [PATCH 15/27] Update assets/js/linkPrefetch.js Co-authored-by: Arun Shenoy --- assets/js/linkPrefetch.js | 290 ++++++++++++-------------------------- 1 file changed, 87 insertions(+), 203 deletions(-) diff --git a/assets/js/linkPrefetch.js b/assets/js/linkPrefetch.js index 1a21489..bf29f1d 100644 --- a/assets/js/linkPrefetch.js +++ b/assets/js/linkPrefetch.js @@ -1,219 +1,103 @@ -window.addEventListener( 'load', () => { - /* check if the browser supports Prefetch */ - const testlink = document.createElement("link"), - supportsPrefetchCheck = testlink.relList && testlink.relList.supports && testlink.relList.supports("prefetch"), - /* check if the user has set a reduced data usage option on the user agent or if the current connection effective type is 2g */ - navigatorConnectionCheck = navigator.connection && (navigator.connection.saveData || (navigator.connection.effectiveType || "").includes("2g")), - intersectionObserverCheck = window.IntersectionObserver && "isIntersecting" in IntersectionObserverEntry.prototype; - - if ( ! supportsPrefetchCheck || navigatorConnectionCheck ) { - return; - } else { - class LP_APP { - constructor(config) { - this.config = config; - this.activeOnDesktop = config.activeOnDesktop; - this.behavior = config.behavior; - this.hoverDelay = config.hoverDelay; - this.ignoreKeywords = config.ignoreKeywords.split(','); - this.instantClick = config.instantClick; - this.mobileActive = config.activeOnMobile; - this.isMobile = config.isMobile; - this.mobileBehavior = config.mobileBehavior; - this.prefetchedUrls = new Set(); - this.timerIdentifier; - this.eventListenerOptions = { capture: !0, passive: !0 }; - } - /** - * Init - * @returns {void} - */ - init() { - const isChrome = navigator.userAgent.indexOf("Chrome/") > -1, - chromeVersion = isChrome && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Chrome/") + "Chrome/".length)); - - if ( isChrome && chromeVersion < 110 ) {return;} - if ( this.isMobile && ! this.mobileActive ) {return;} - if ( ! this.isMobile && ! this.activeOnDesktop ) {return;} - - if ( ! this.isMobile ) { - if ( 'mouseHover' === this.behavior ) { - let hoverDelay = parseInt(this.hoverDelay); - hoverDelay = isNaN(hoverDelay) ? 60 : hoverDelay; - document.addEventListener("mouseover", this.mouseHover.bind(this), this.eventListenerOptions); - } else if ( 'mouseDown' === this.behavior ) { - if ( this.instantClick ) { - document.addEventListener("mousedown", this.mouseDownToClick.bind(this), this.eventListenerOptions); - } else { - document.addEventListener("mousedown", this.mouseDown.bind(this), this.eventListenerOptions) - } - } - } +document.addEventListener('DOMContentLoaded', () => { + const testLink = document.createElement('link'); + const supportsPrefetch = testLink.relList?.supports?.('prefetch'); + const isDataSaver = navigator.connection?.saveData || navigator.connection?.effectiveType?.includes('2g'); + const supportsIntersectionObserver = 'IntersectionObserver' in window && 'isIntersecting' in IntersectionObserverEntry.prototype; - if ( this.mobileActive && this.isMobile ) { - if ( 'touchstart' === this.mobileBehavior ) { - document.addEventListener("touchstart", this.touchstart.bind(this), this.eventListenerOptions); - } else if ( 'viewport' && intersectionObserverCheck ) { - this.viewport(); - } - } - } - /** - * Viewport handler - * @returns {void} - */ - viewport() { - const io = new IntersectionObserver((e) => { - e.forEach((e) => { - if (e.isIntersecting) { - const n = e.target; - io.unobserve(n); - this.canPrefetch(n) && this.prefetchIt(n.href); - } - }); - }); - let requestIdleCallback = window.requestIdleCallback || - function (cb) { - var start = Date.now(); - return setTimeout(function () { - cb({ - didTimeout: false, - timeRemaining: function () { - return Math.max(0, 50 - (Date.now() - start)); - } - }); - }, 1); - }; - requestIdleCallback( () => { - return setTimeout(function () { - return document.querySelectorAll("a").forEach(function (a) { - return io.observe(a); - }); - }, 1000); - }, { timeout: 1000 }); - } - /** - * Mouse Down handler - * @param {Event} e - listener event - * @returns {void} - */ - mouseDown(e) { - const el = e.target.closest("a"); - this.canPrefetch(el) && this.prefetchIt(el.href); - } + if (!supportsPrefetch || isDataSaver) return; - /** - * Mouse Down handler for instant click - * @param {Event} e - listener event - * @returns {void} - */ - mouseDownToClick(e) { - //if (performance.now() - o < r) return; - const el = e.target.closest("a"); - if (e.which > 1 || e.metaKey || e.ctrlKey) return; - if (!el) return; - el.addEventListener( - "click", - function (t) { - 'lpappinstantclick' != t.detail && t.preventDefault(); - }, - { capture: !0, passive: !1, once: !0 } - ); - const n = new MouseEvent("click", { view: window, bubbles: !0, cancelable: !1, detail: 'lpappinstantclick' }); - el.dispatchEvent(n); - } + class LinkPrefetcher { + constructor(config) { + Object.assign(this, { + activeOnDesktop: config.activeOnDesktop, + behavior: config.behavior, + hoverDelay: parseInt(config.hoverDelay) || 60, + ignoreKeywords: config.ignoreKeywords.split(','), + instantClick: config.instantClick, + mobileActive: config.activeOnMobile, + isMobile: config.isMobile, + mobileBehavior: config.mobileBehavior, + prefetchedUrls: new Set(), + eventOptions: { capture: true, passive: true }, + timerId: null, + }); + } - touchstart(e) { - const el = e.target.closest("a"); - this.canPrefetch(el) && this.prefetchIt(el.href); - } + init() { + const isChrome = navigator.userAgent.includes('Chrome/'); + const chromeVersion = isChrome && parseInt(navigator.userAgent.split('Chrome/')[1]); - /** - * Clean Timers - * @param {Event} t - listener event - * @returns {void} - */ - clean(t) { - if ( t.relatedTarget && t.target.closest("a") == t.relatedTarget.closest("a") || this.timerIdentifier ) { - clearTimeout( this.timerIdentifier ); - this.timerIdentifier = void(0); - } + if (isChrome && chromeVersion < 110) return; + if ((this.isMobile && !this.mobileActive) || (!this.isMobile && !this.activeOnDesktop)) return; + + if (!this.isMobile) { + this.behavior === 'mouseHover' && document.addEventListener('mouseover', this.handleHover.bind(this), this.eventOptions); + this.behavior === 'mouseDown' && document.addEventListener('mousedown', this.instantClick ? this.handleInstantClick.bind(this) : this.handleMouseDown.bind(this), this.eventOptions); } - /** - * Mouse hover function - * @param {Event} e - listener event - * @returns {void} - */ - mouseHover(e) { - if ( !("closest" in e.target) ) return; - const link = e.target.closest("a"); - if ( this.canPrefetch( link ) ) { - link.addEventListener("mouseout", this.clean.bind(this), { passive: !0 }); - this.timerIdentifier = setTimeout(()=> { - this.prefetchIt( link.href ); - this.timerIdentifier = void(0); - }, this.hoverDelay); - } + if (this.isMobile && this.mobileBehavior === 'viewport' && supportsIntersectionObserver) { + this.setupViewportObserver(); } - - /** - * Can the url be prefetched or not - * @param {Element} el - link element - * @returns {boolean} - if it can be prefetched - */ - canPrefetch( el ) { - if ( el && el.href ) { - /* it has been just prefetched before */ - if (this.prefetchedUrls.has(el.href)) { - return false; - } + } - /* avoid if it is the same url as the actual location */ - if ( el.href.replace(/\/$/, "") !== location.origin.replace(/\/$/, "") && el.href.replace(/\/$/, "") !== location.href.replace(/\/$/, "") ) { - return true; + setupViewportObserver() { + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + observer.unobserve(entry.target); + this.prefetchIfEligible(entry.target.href); } + }); + }); - /* checking exclusions */ - const exclude = this.ignoreKeywords.filter( k => { - if ( el.href.indexOf (k) > -1) { - return k; - } - }) - if ( exclude.length > 0 ) { return false; } - - } - - return false; - } + const idleCallback = window.requestIdleCallback || ((cb) => setTimeout(cb, 1)); + idleCallback(() => setTimeout(() => document.querySelectorAll('a').forEach((a) => observer.observe(a)), 1000)); + } - /** - * Append link rel=prefetch to the head - * @param {string} url - url to prefetch - * @returns {void} - */ - prefetchIt(url) { - const toPrefechLink = document.createElement("link"); + handleMouseDown(event) { + const el = event.target.closest('a'); + this.prefetchIfEligible(el?.href); + } - toPrefechLink.rel = "prefetch"; - toPrefechLink.href = url; - toPrefechLink.as = "document"; + handleInstantClick(event) { + const el = event.target.closest('a'); + if (!el || event.which > 1 || event.metaKey || event.ctrlKey) return; + el.addEventListener('click', (e) => e.detail !== 'instantClick' && e.preventDefault(), { capture: true, passive: false, once: true }); + el.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: false, detail: 'instantClick' })); + } - document.head.appendChild(toPrefechLink); - this.prefetchedUrls.add(url); - } + handleHover(event) { + const link = event.target.closest('a'); + if (!link || !this.prefetchIfEligible(link.href)) return; + link.addEventListener('mouseout', () => clearTimeout(this.timerId), this.eventOptions); + this.timerId = setTimeout(() => this.prefetchIt(link.href), this.hoverDelay); + } + + prefetchIfEligible(url) { + if (!url || this.prefetchedUrls.has(url)) return false; + if (url.replace(/\/$/, '') === location.href.replace(/\/$/, '') || this.ignoreKeywords.some((k) => url.includes(k))) return false; + return true; + } + + prefetchIt(url) { + const link = document.createElement('link'); + link.rel = 'prefetch'; + link.href = url; + document.head.appendChild(link); + this.prefetchedUrls.add(url); } - /* - default config: - 'activeOnDesktop' => true, - 'behavior' =>'mouseHover', - 'hoverDelay' => 60, - 'instantClick' => true , - 'activeOnMobile' => true , - 'mobileBehavior' => 'viewport', - 'ignoreKeywords' =>'wp-admin,#,?', - */ - const lpapp = new LP_APP( window.LP_CONFIG ); - lpapp.init(); } + + const config = window.LP_CONFIG || { + activeOnDesktop: true, + behavior: 'mouseHover', + hoverDelay: 60, + instantClick: true, + activeOnMobile: true, + mobileBehavior: 'viewport', + ignoreKeywords: 'wp-admin,#,?', + }; + + new LinkPrefetcher(config).init(); }); + From b5a52840e75f47745e72b1fb9b31d3d55f1460a5 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 10:24:53 +0000 Subject: [PATCH 16/27] Update components/linkPrefetch/index.js Co-authored-by: Arun Shenoy --- components/linkPrefetch/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index 1fb9096..d0ba6c5 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -3,7 +3,7 @@ import { Toggle, TextField, SelectField, Container } from "@newfold/ui-component const LinkPrefetch = ({methods, constants}) => { const [settings, setSettings] = methods.useState(methods.NewfoldRuntime.sdk.linkPrefetch.settings); const [isError, setIsError] = methods.useState(false); - const apiUrl = methods.NewfoldRuntime.createApiUrl("/newfold-ecommerce/v1/linkprefetch/update"); + const apiUrl = methods.NewfoldRuntime.createApiUrl("/newfold-performance/v1/link-prefetch/settings"); const handleChangeOption = ( option, value ) => { if ( option in settings ) { From c9c5775750ce71e75b0827a46ea1618e124e21bb Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 10:26:45 +0000 Subject: [PATCH 17/27] moved non-react scripts to scripts folder --- assets/js/linkPrefetch.min.js | 1 - {assets/js => scripts}/linkPrefetch.js | 0 scripts/linkPrefetch.min.js | 1 + 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 assets/js/linkPrefetch.min.js rename {assets/js => scripts}/linkPrefetch.js (100%) create mode 100644 scripts/linkPrefetch.min.js diff --git a/assets/js/linkPrefetch.min.js b/assets/js/linkPrefetch.min.js deleted file mode 100644 index c6ea1d4..0000000 --- a/assets/js/linkPrefetch.min.js +++ /dev/null @@ -1 +0,0 @@ -window.addEventListener("load",(()=>{const e=document.createElement("link"),t=e.relList&&e.relList.supports&&e.relList.supports("prefetch"),i=navigator.connection&&(navigator.connection.saveData||(navigator.connection.effectiveType||"").includes("2g")),n=window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype;if(t&&!i){class e{constructor(e){this.config=e,this.activeOnDesktop=e.activeOnDesktop,this.behavior=e.behavior,this.hoverDelay=e.hoverDelay,this.ignoreKeywords=e.ignoreKeywords.split(","),this.instantClick=e.instantClick,this.mobileActive=e.activeOnMobile,this.isMobile=e.isMobile,this.mobileBehavior=e.mobileBehavior,this.prefetchedUrls=new Set,this.timerIdentifier,this.eventListenerOptions={capture:!0,passive:!0}}init(){const e=navigator.userAgent.indexOf("Chrome/")>-1,t=e&&parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("Chrome/")+7));if(!(e&&t<110)&&(!this.isMobile||this.mobileActive)&&(this.isMobile||this.activeOnDesktop)){if(!this.isMobile)if("mouseHover"===this.behavior){let e=parseInt(this.hoverDelay);e=isNaN(e)?60:e,document.addEventListener("mouseover",this.mouseHover.bind(this),this.eventListenerOptions)}else"mouseDown"===this.behavior&&(this.instantClick?document.addEventListener("mousedown",this.mouseDownToClick.bind(this),this.eventListenerOptions):document.addEventListener("mousedown",this.mouseDown.bind(this),this.eventListenerOptions));this.mobileActive&&this.isMobile&&("touchstart"===this.mobileBehavior?document.addEventListener("touchstart",this.touchstart.bind(this),this.eventListenerOptions):n&&this.viewport())}}viewport(){const e=new IntersectionObserver((t=>{t.forEach((t=>{if(t.isIntersecting){const i=t.target;e.unobserve(i),this.canPrefetch(i)&&this.prefetchIt(i.href)}}))}));(window.requestIdleCallback||function(e){var t=Date.now();return setTimeout((function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})}),1)})((()=>setTimeout((function(){return document.querySelectorAll("a").forEach((function(t){return e.observe(t)}))}),1e3)),{timeout:1e3})}mouseDown(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}mouseDownToClick(e){const t=e.target.closest("a");if(e.which>1||e.metaKey||e.ctrlKey)return;if(!t)return;t.addEventListener("click",(function(e){"lpappinstantclick"!=e.detail&&e.preventDefault()}),{capture:!0,passive:!1,once:!0});const i=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:"lpappinstantclick"});t.dispatchEvent(i)}touchstart(e){const t=e.target.closest("a");this.canPrefetch(t)&&this.prefetchIt(t.href)}clean(e){(e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||this.timerIdentifier)&&(clearTimeout(this.timerIdentifier),this.timerIdentifier=void 0)}mouseHover(e){if(!("closest"in e.target))return;const t=e.target.closest("a");this.canPrefetch(t)&&(t.addEventListener("mouseout",this.clean.bind(this),{passive:!0}),this.timerIdentifier=setTimeout((()=>{this.prefetchIt(t.href),this.timerIdentifier=void 0}),this.hoverDelay))}canPrefetch(e){if(e&&e.href){if(this.prefetchedUrls.has(e.href))return!1;if(e.href.replace(/\/$/,"")!==location.origin.replace(/\/$/,"")&&e.href.replace(/\/$/,"")!==location.href.replace(/\/$/,""))return!0;if(this.ignoreKeywords.filter((t=>{if(e.href.indexOf(t)>-1)return t})).length>0)return!1}return!1}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,t.as="document",document.head.appendChild(t),this.prefetchedUrls.add(e)}}new e(window.LP_CONFIG).init()}})); \ No newline at end of file diff --git a/assets/js/linkPrefetch.js b/scripts/linkPrefetch.js similarity index 100% rename from assets/js/linkPrefetch.js rename to scripts/linkPrefetch.js diff --git a/scripts/linkPrefetch.min.js b/scripts/linkPrefetch.min.js new file mode 100644 index 0000000..a487957 --- /dev/null +++ b/scripts/linkPrefetch.min.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",(()=>{const e=document.createElement("link"),t=e.relList?.supports?.("prefetch"),i=navigator.connection?.saveData||navigator.connection?.effectiveType?.includes("2g"),s="IntersectionObserver"in window&&"isIntersecting"in IntersectionObserverEntry.prototype;if(!t||i)return;const n=window.LP_CONFIG||{activeOnDesktop:!0,behavior:"mouseHover",hoverDelay:60,instantClick:!0,activeOnMobile:!0,mobileBehavior:"viewport",ignoreKeywords:"wp-admin,#,?"};new class{constructor(e){Object.assign(this,{activeOnDesktop:e.activeOnDesktop,behavior:e.behavior,hoverDelay:parseInt(e.hoverDelay)||60,ignoreKeywords:e.ignoreKeywords.split(","),instantClick:e.instantClick,mobileActive:e.activeOnMobile,isMobile:e.isMobile,mobileBehavior:e.mobileBehavior,prefetchedUrls:new Set,eventOptions:{capture:!0,passive:!0},timerId:null})}init(){const e=navigator.userAgent.includes("Chrome/"),t=e&&parseInt(navigator.userAgent.split("Chrome/")[1]);e&&t<110||this.isMobile&&!this.mobileActive||!this.isMobile&&!this.activeOnDesktop||(this.isMobile||("mouseHover"===this.behavior&&document.addEventListener("mouseover",this.handleHover.bind(this),this.eventOptions),"mouseDown"===this.behavior&&document.addEventListener("mousedown",this.instantClick?this.handleInstantClick.bind(this):this.handleMouseDown.bind(this),this.eventOptions)),this.isMobile&&"viewport"===this.mobileBehavior&&s&&this.setupViewportObserver())}setupViewportObserver(){const e=new IntersectionObserver((t=>{t.forEach((t=>{t.isIntersecting&&(e.unobserve(t.target),this.prefetchIfEligible(t.target.href))}))}));(window.requestIdleCallback||(e=>setTimeout(e,1)))((()=>setTimeout((()=>document.querySelectorAll("a").forEach((t=>e.observe(t)))),1e3)))}handleMouseDown(e){const t=e.target.closest("a");this.prefetchIfEligible(t?.href)}handleInstantClick(e){const t=e.target.closest("a");!t||e.which>1||e.metaKey||e.ctrlKey||(t.addEventListener("click",(e=>"instantClick"!==e.detail&&e.preventDefault()),{capture:!0,passive:!1,once:!0}),t.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!1,detail:"instantClick"})))}handleHover(e){const t=e.target.closest("a");t&&this.prefetchIfEligible(t.href)&&(t.addEventListener("mouseout",(()=>clearTimeout(this.timerId)),this.eventOptions),this.timerId=setTimeout((()=>this.prefetchIt(t.href)),this.hoverDelay))}prefetchIfEligible(e){return!(!e||this.prefetchedUrls.has(e))&&(e.replace(/\/$/,"")!==location.href.replace(/\/$/,"")&&!this.ignoreKeywords.some((t=>e.includes(t))))}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,document.head.appendChild(t),this.prefetchedUrls.add(e)}}(n).init()})); \ No newline at end of file From 2202638dae6771a9452c2f4c5a669a06f3d04fb9 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 10:35:07 +0000 Subject: [PATCH 18/27] added RestApi.php --- includes/RestApi/RestApi.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 includes/RestApi/RestApi.php diff --git a/includes/RestApi/RestApi.php b/includes/RestApi/RestApi.php new file mode 100644 index 0000000..6a4a897 --- /dev/null +++ b/includes/RestApi/RestApi.php @@ -0,0 +1,36 @@ +controllers as $Controller ) { + /** + * Get an instance of the WP_REST_Controller. + * + * @var $instance \WP_REST_Controller + */ + $instance = new $Controller(); + $instance->register_routes(); + } + } +} From 5b5c22df4039ed58725b179601b81004ca611597 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 10:41:45 +0000 Subject: [PATCH 19/27] applied suggestion changes to component index.js --- components/linkPrefetch/index.js | 45 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index d0ba6c5..370eba0 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -5,26 +5,22 @@ const LinkPrefetch = ({methods, constants}) => { const [isError, setIsError] = methods.useState(false); const apiUrl = methods.NewfoldRuntime.createApiUrl("/newfold-performance/v1/link-prefetch/settings"); - const handleChangeOption = ( option, value ) => { - if ( option in settings ) { - const updatedSettings = settings; - updatedSettings[option] = value; - methods.apiFetch({ + const handleChangeOption = (option, value) => { + if (!(option in settings)) return; + const updatedSettings = { ...settings, [option]: value }; + methods + .apiFetch({ url: apiUrl, method: "POST", - data: {settings: updatedSettings} - }).then((result)=>{ - setSettings( (prev)=> { - return { - ...prev, - [option]: value - } - }); - }).catch((error) => { - setIsError(error.message); - }); - } - } + data: { settings: updatedSettings }, + }) + .then(() => { + setSettings((prev) => ({ ...prev, [option]: value })); + }) + .catch((error) => { + setIsError(error.message); + }); + }; methods.useUpdateEffect(() => { methods.setStore({ @@ -35,8 +31,8 @@ const LinkPrefetch = ({methods, constants}) => { methods.makeNotice( "link-prefetch-change-notice", constants.text.linkPrefetchTitle, - !isError ? constants.text.linkPrefetchNoticeTitle : isError, - !isError ? "success" : "error", + isError || constants.text.linkPrefetchNoticeTitle, + isError ? "error" : "success", 5000 ); }, [settings, isError]); @@ -47,16 +43,17 @@ const LinkPrefetch = ({methods, constants}) => { title={constants.text.linkPrefetchTitle} description={constants.text.linkPrefetchDescription} > + {/* Desktop Settings */}
- +
- {constants.text.linkPrefetchActivateOnDekstopDescription} + {constants.text.linkPrefetchActivateOnDesktopDescription}
handleChangeOption( 'activeOnDesktop', !settings.activeOnDesktop) } /> @@ -82,6 +79,7 @@ const LinkPrefetch = ({methods, constants}) => { ) } + {/* Mobile Settings */}
@@ -117,6 +115,7 @@ const LinkPrefetch = ({methods, constants}) => { ) } + {/* Ignore Keywords */} { ( settings.activeOnMobile || settings.activeOnDesktop ) && Date: Mon, 18 Nov 2024 11:15:52 +0000 Subject: [PATCH 20/27] other fixies for RestApi and LinkPrefetch Starting --- includes/LinkPrefetch.php | 37 ++++-------------- includes/Performance.php | 7 ++-- includes/RestApi/RestApi.php | 72 ++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 69 deletions(-) diff --git a/includes/LinkPrefetch.php b/includes/LinkPrefetch.php index 1436538..cd686e1 100644 --- a/includes/LinkPrefetch.php +++ b/includes/LinkPrefetch.php @@ -1,5 +1,4 @@ container = $container; - add_action( 'rest_api_init', array( $this, 'register_routes' ) ); add_filter( 'newfold-runtime', array( $this, 'add_to_runtime' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts' ) ); add_filter( 'script_loader_tag', array( $this, 'addDefer' ), 10, 2 ); } - /** - * Register API routes. - */ - public function register_routes() { - foreach ( $this->controllers as $Controller ) { - /** - * Get an instance of the WP_REST_Controller. - * - * @var $instance \WP_REST_Controller - */ - $instance = new $Controller( $this->container ); - $instance->register_routes(); - } - } /** * Add values to the runtime object. * @@ -62,7 +37,7 @@ public function register_routes() { */ public function add_to_runtime( $sdk ) { $values = array( - 'settings' => get_option( 'nfd_linkPrefetch', $this->getDefaultSettings() ), + 'settings' => get_option( 'nfd_link_prefetch_settings', static::getDefaultSettings() ), ); return array_merge( $sdk, array( 'linkPrefetch' => $values ) ); } @@ -73,9 +48,11 @@ public function add_to_runtime( $sdk ) { */ public function enqueueScripts() { $plugin_url = $this->container->plugin()->url . $this->getScriptPath(); - $settings = get_option( 'nfd_linkPrefetch', $this->getDefaultSettings() ); + $settings = get_option( 'nfd_link_prefetch_settings', static::getDefaultSettings() ); - if ( ! $settings['activeOnDesktop'] && ! $settings['activeOnMobile'] ) { return; } + if ( ! $settings['activeOnDesktop'] && ! $settings['activeOnMobile'] ) { + return; + } $settings['isMobile'] = wp_is_mobile(); @@ -90,7 +67,7 @@ public function enqueueScripts() { */ public function getScriptPath() { $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; - return 'vendor/newfold-labs/wp-module-performance/assets/js/linkPrefetch' . $suffix . '.js'; + return 'vendor/newfold-labs/wp-module-performance/scripts/linkPrefetch' . $suffix . '.js'; } /** @@ -98,7 +75,7 @@ public function getScriptPath() { * * return array */ - public function getDefaultSettings() { + public static function getDefaultSettings() { return array( 'activeOnDesktop' => false, 'behavior' => 'mouseHover', diff --git a/includes/Performance.php b/includes/Performance.php index ac50c2f..0d201ad 100644 --- a/includes/Performance.php +++ b/includes/Performance.php @@ -2,9 +2,7 @@ namespace NewfoldLabs\WP\Module\Performance; -use NewfoldLabs\WP\Module\Performance\CacheTypes\Browser; -use NewfoldLabs\WP\Module\Performance\CacheTypes\File; -use NewfoldLabs\WP\Module\Performance\CacheTypes\Skip404; +use NewfoldLabs\WP\Module\Performance\RestApi\RestApi; use NewfoldLabs\WP\ModuleLoader\Container; /** @@ -72,6 +70,9 @@ public function __construct( Container $container ) { $cacheManager = new CacheManager( $container ); $cachePurger = new CachePurgingService( $cacheManager->getInstances() ); + new LinkPrefetch( $container ); + new RestApi(); + // Ensure that purgeable cache types are enabled before showing the UI. if ( $cachePurger->canPurge() ) { add_action( 'admin_bar_menu', array( $this, 'adminBarMenu' ), 100 ); diff --git a/includes/RestApi/RestApi.php b/includes/RestApi/RestApi.php index 6a4a897..7afb6cb 100644 --- a/includes/RestApi/RestApi.php +++ b/includes/RestApi/RestApi.php @@ -1,36 +1,36 @@ -controllers as $Controller ) { - /** - * Get an instance of the WP_REST_Controller. - * - * @var $instance \WP_REST_Controller - */ - $instance = new $Controller(); - $instance->register_routes(); - } - } -} +controllers as $Controller ) { + /** + * Get an instance of the WP_REST_Controller. + * + * @var $instance \WP_REST_Controller + */ + $instance = new $Controller(); + $instance->register_routes(); + } + } +} From af2d8431d1eaeaf4fc05e249ca1d582f40ee2579 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 12:11:30 +0000 Subject: [PATCH 21/27] moved inline styles to file and load it --- components/linkPrefetch/index.js | 4 +-- includes/LinkPrefetch.php | 12 +-------- includes/Performance.php | 11 +++++++++ includes/functions.php | 42 +++++++++++++++++++++++++------- styles/styles.css | 4 +++ 5 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 styles/styles.css diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index 370eba0..060cd2b 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -44,7 +44,7 @@ const LinkPrefetch = ({methods, constants}) => { description={constants.text.linkPrefetchDescription} > {/* Desktop Settings */} -
+
@@ -80,7 +80,7 @@ const LinkPrefetch = ({methods, constants}) => { ) } {/* Mobile Settings */} -
+
diff --git a/includes/LinkPrefetch.php b/includes/LinkPrefetch.php index cd686e1..2046d86 100644 --- a/includes/LinkPrefetch.php +++ b/includes/LinkPrefetch.php @@ -47,7 +47,7 @@ public function add_to_runtime( $sdk ) { * return void */ public function enqueueScripts() { - $plugin_url = $this->container->plugin()->url . $this->getScriptPath(); + $plugin_url = $this->container->plugin()->url . get_scripts_path( 'linkPrefetch' ); $settings = get_option( 'nfd_link_prefetch_settings', static::getDefaultSettings() ); if ( ! $settings['activeOnDesktop'] && ! $settings['activeOnMobile'] ) { @@ -60,16 +60,6 @@ public function enqueueScripts() { wp_add_inline_script( 'linkprefetcher', 'window.LP_CONFIG = ' . wp_json_encode( $settings ), 'before' ); } - /** - * Get js script path. - * - * return string - */ - public function getScriptPath() { - $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; - return 'vendor/newfold-labs/wp-module-performance/scripts/linkPrefetch' . $suffix . '.js'; - } - /** * Get link prefetch default settings. * diff --git a/includes/Performance.php b/includes/Performance.php index 0d201ad..5756be5 100644 --- a/includes/Performance.php +++ b/includes/Performance.php @@ -81,6 +81,8 @@ public function __construct( Container $container ) { $container->set( 'cachePurger', $cachePurger ); $container->set( 'hasMustUsePlugin', file_exists( WPMU_PLUGIN_DIR . '/endurance-page-cache.php' ) ); + + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); } /** @@ -293,4 +295,13 @@ public function adminBarMenu( \WP_Admin_Bar $wp_admin_bar ) { ); } } + + /** + * Enqueue scripts and styles in admin + */ + public function enqueue_scripts() { + $plugin_url = $this->container->plugin()->url . get_styles_path(); + wp_register_style( 'wp-module-performance-styles', $plugin_url ); + wp_enqueue_style( 'wp-module-performance-styles' ); + } } diff --git a/includes/functions.php b/includes/functions.php index 4133e84..447cdb4 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -17,12 +17,12 @@ function getCacheLevel() { * @return string[] */ function getCacheLevels() { - return [ + return array( 0 => 'Off', // Disable caching 1 => 'Assets Only', // Cache assets only 2 => 'Normal', // Cache pages and assets for a shorter time range 3 => 'Advanced', // Cache pages and assets for a longer time range - ]; + ); } /** @@ -36,10 +36,10 @@ function getCacheLevelDropdown() { $name = Performance::OPTION_CACHE_LEVEL; $label = __( 'Cache Level', 'newfold-performance-module' ); ?> - + $optionLabel ) : ?> + @@ -65,10 +65,10 @@ function getSkip404InputField() { ?> + aria-label="" + /> Date: Mon, 18 Nov 2024 12:28:45 +0000 Subject: [PATCH 22/27] some phpcs fixiews --- includes/Performance.php | 6 +++--- includes/RestApi/RestApi.php | 5 ++++- includes/functions.php | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/includes/Performance.php b/includes/Performance.php index 5756be5..3dba9f8 100644 --- a/includes/Performance.php +++ b/includes/Performance.php @@ -111,7 +111,7 @@ function () { * * @param Container $container the container */ - public function hooks( Container $container ) { + public function hooks() { add_action( 'admin_init', array( $this, 'registerSettings' ), 11 ); @@ -156,7 +156,7 @@ function () { * * @return int New retention period in seconds. */ - public function nfd_asr_default( $retention_period ) { + public function nfd_asr_default() { return 5 * constant( 'DAY_IN_SECONDS' ); } @@ -301,7 +301,7 @@ public function adminBarMenu( \WP_Admin_Bar $wp_admin_bar ) { */ public function enqueue_scripts() { $plugin_url = $this->container->plugin()->url . get_styles_path(); - wp_register_style( 'wp-module-performance-styles', $plugin_url ); + wp_register_style( 'wp-module-performance-styles', $plugin_url, array(), $this->container->plugin()->version ); wp_enqueue_style( 'wp-module-performance-styles' ); } } diff --git a/includes/RestApi/RestApi.php b/includes/RestApi/RestApi.php index 7afb6cb..87b555c 100644 --- a/includes/RestApi/RestApi.php +++ b/includes/RestApi/RestApi.php @@ -1,6 +1,9 @@ Date: Mon, 18 Nov 2024 12:30:38 +0000 Subject: [PATCH 23/27] phpcs --- includes/Performance.php | 4 - package-lock.json | 1788 +++++++++++++++++++++++++++++++++++++- package.json | 3 +- phpcs.xml | 2 +- 4 files changed, 1744 insertions(+), 53 deletions(-) diff --git a/includes/Performance.php b/includes/Performance.php index 3dba9f8..5ed4766 100644 --- a/includes/Performance.php +++ b/includes/Performance.php @@ -108,8 +108,6 @@ function () { /** * Add hooks. - * - * @param Container $container the container */ public function hooks() { @@ -152,8 +150,6 @@ function () { * @hooked action_scheduler_retention_period * @see ActionScheduler_QueueCleaner::delete_old_actions() * - * @param int $retention_period Minimum scheduled age in seconds of the actions to be deleted. - * * @return int New retention period in seconds. */ public function nfd_asr_default() { diff --git a/package-lock.json b/package-lock.json index ed1b9dc..8eb32b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@heroicons/react": "^2.0.18", - "@newfold/ui-component-library": "^1.0.1" + "@newfold/ui-component-library": "^1.0.1", + "@tailwindcss/forms": "^0.5.8" }, "devDependencies": { "@testing-library/cypress": "^9.0.0", @@ -16,6 +17,18 @@ "cypress-axe": "^1.4.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -268,6 +281,150 @@ "react": ">= 16" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "peer": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "peer": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "peer": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@newfold/ui-component-library": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@newfold/ui-component-library/-/ui-component-library-1.0.1.tgz", @@ -295,6 +452,51 @@ "react": ">= 16" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "peer": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@reduxjs/toolkit": { "version": "1.9.7", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", @@ -318,6 +520,17 @@ } } }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", + "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20" + } + }, "node_modules/@testing-library/cypress": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-9.0.0.tgz", @@ -529,7 +742,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -538,7 +750,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -549,6 +760,25 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "peer": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -569,6 +799,12 @@ } ] }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "peer": true + }, "node_modules/aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -679,8 +915,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -711,6 +946,18 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -733,6 +980,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "peer": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -798,6 +1057,15 @@ "tslib": "^2.0.3" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "peer": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/capital-case": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", @@ -860,6 +1128,42 @@ "node": ">= 0.8.0" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "peer": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", @@ -941,7 +1245,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -952,8 +1255,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.20", @@ -1018,7 +1320,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1028,6 +1329,18 @@ "node": ">= 8" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "peer": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", @@ -1209,6 +1522,18 @@ "node": ">=0.4.0" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "peer": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "peer": true + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -1225,6 +1550,12 @@ "tslib": "^2.0.3" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "peer": true + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1238,8 +1569,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/end-of-stream": { "version": "1.4.4", @@ -1368,6 +1698,43 @@ "node >=0.6.0" ] }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "peer": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -1392,6 +1759,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "peer": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -1401,6 +1780,34 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1445,6 +1852,20 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1527,6 +1948,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "peer": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -1792,9 +2225,21 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "peer": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "dependencies": { @@ -1858,15 +2303,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "peer": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -1892,6 +2357,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "peer": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -2068,8 +2542,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isstream": { "version": "0.1.2", @@ -2077,6 +2550,30 @@ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "peer": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "peer": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2136,6 +2633,21 @@ "node": "> 0.8" } }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "peer": true + }, "node_modules/listr2": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", @@ -2286,6 +2798,28 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "peer": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -2316,6 +2850,14 @@ "node": ">=6" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2337,12 +2879,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "peer": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "peer": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -2371,6 +2933,15 @@ "tslib": "^2.0.3" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -2391,6 +2962,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "peer": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -2488,6 +3068,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "peer": true + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -2531,7 +3117,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -2541,6 +3126,28 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "peer": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "peer": true + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -2559,6 +3166,18 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "peer": true }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -2567,6 +3186,15 @@ "node": ">=0.10.0" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "peer": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/postcss": { "version": "8.4.32", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", @@ -2611,6 +3239,110 @@ "postcss": "^8.0.0" } }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "peer": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "peer": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -2730,6 +3462,26 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -2796,6 +3548,18 @@ "pify": "^2.3.0" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "peer": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", @@ -2883,6 +3647,16 @@ "node": ">=8" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "peer": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rfdc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", @@ -2904,6 +3678,29 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", @@ -2978,7 +3775,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -2990,7 +3786,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -3089,7 +3884,21 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3103,7 +3912,19 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3120,6 +3941,81 @@ "node": ">=6" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "peer": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3143,6 +4039,64 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "peer": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "peer": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "peer": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", @@ -3167,6 +4121,18 @@ "node": ">=8.17.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "peer": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/tough-cookie": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", @@ -3191,6 +4157,12 @@ "node": ">= 4.0.0" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "peer": true + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -3272,6 +4244,12 @@ "requires-port": "^1.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "peer": true + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -3299,7 +4277,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -3377,6 +4354,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3389,6 +4384,18 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -3401,6 +4408,12 @@ } }, "dependencies": { + "@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "peer": true + }, "@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -3608,6 +4621,110 @@ "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==", "requires": {} }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "peer": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "peer": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "peer": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "peer": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "peer": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "peer": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "peer": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "peer": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "peer": true + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "peer": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "peer": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "peer": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "@newfold/ui-component-library": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@newfold/ui-component-library/-/ui-component-library-1.0.1.tgz", @@ -3632,6 +4749,39 @@ } } }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "peer": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "peer": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "peer": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "peer": true + }, "@reduxjs/toolkit": { "version": "1.9.7", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", @@ -3643,6 +4793,14 @@ "reselect": "^4.1.8" } }, + "@tailwindcss/forms": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", + "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==", + "requires": { + "mini-svg-data-uri": "^1.2.3" + } + }, "@testing-library/cypress": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-9.0.0.tgz", @@ -3821,16 +4979,30 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { - "color-convert": "^2.0.1" + "color-convert": "^2.0.1" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "peer": true + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "peer": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, "arch": { @@ -3839,6 +5011,12 @@ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "peer": true + }, "aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -3925,8 +5103,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { "version": "1.5.1", @@ -3943,6 +5120,12 @@ "tweetnacl": "^0.14.3" } }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "peer": true + }, "blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -3965,6 +5148,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "peer": true, + "requires": { + "fill-range": "^7.1.1" + } + }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -4007,6 +5199,12 @@ "tslib": "^2.0.3" } }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "peer": true + }, "capital-case": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", @@ -4060,6 +5258,33 @@ "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", "dev": true }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "peer": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "peer": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", @@ -4115,7 +5340,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -4123,8 +5347,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "colorette": { "version": "2.0.20", @@ -4180,13 +5403,18 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "peer": true + }, "csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", @@ -4328,6 +5556,18 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "peer": true + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "peer": true + }, "dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -4344,6 +5584,12 @@ "tslib": "^2.0.3" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "peer": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -4357,8 +5603,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "end-of-stream": { "version": "1.4.4", @@ -4458,6 +5703,39 @@ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "peer": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "peer": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "peer": true, + "requires": { + "reusify": "^1.0.4" + } + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -4476,6 +5754,15 @@ "escape-string-regexp": "^1.0.5" } }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "peer": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -4485,6 +5772,24 @@ "is-callable": "^1.1.3" } }, + "foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "peer": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "peer": true + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -4520,6 +5825,13 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true, + "peer": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -4584,6 +5896,15 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "peer": true, + "requires": { + "is-glob": "^4.0.3" + } + }, "global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -4765,6 +6086,15 @@ "has-bigints": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "peer": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -4807,11 +6137,25 @@ "has-tostringtag": "^1.0.0" } }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "peer": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "peer": true, + "requires": { + "is-extglob": "^2.1.1" + } }, "is-installed-globally": { "version": "0.4.0", @@ -4829,6 +6173,12 @@ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "peer": true + }, "is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -4945,8 +6295,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "isstream": { "version": "0.1.2", @@ -4954,6 +6303,22 @@ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "peer": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "peer": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5005,6 +6370,18 @@ "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", "dev": true }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "peer": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "peer": true + }, "listr2": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", @@ -5116,6 +6493,22 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "peer": true + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "peer": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -5137,6 +6530,11 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==" + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5152,12 +6550,29 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "peer": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "peer": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -5174,6 +6589,12 @@ "tslib": "^2.0.3" } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "peer": true + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -5188,6 +6609,12 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "peer": true + }, "object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -5255,6 +6682,12 @@ "aggregate-error": "^3.0.0" } }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "peer": true + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -5294,14 +6727,31 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "peer": true, + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "peer": true + } + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -5320,11 +6770,23 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "peer": true }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "peer": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "peer": true + }, "postcss": { "version": "8.4.32", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", @@ -5346,6 +6808,52 @@ "resolve": "^1.1.7" } }, + "postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "peer": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "peer": true, + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "dependencies": { + "lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "peer": true + } + } + }, + "postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "peer": true, + "requires": { + "postcss-selector-parser": "^6.1.1" + } + }, + "postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "peer": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -5442,6 +6950,12 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "peer": true + }, "react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -5489,6 +7003,15 @@ "pify": "^2.3.0" } }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "peer": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", @@ -5559,6 +7082,12 @@ "signal-exit": "^3.0.2" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "peer": true + }, "rfdc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", @@ -5574,6 +7103,15 @@ "glob": "^7.1.3" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "peer": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", @@ -5628,7 +7166,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -5636,8 +7173,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "side-channel": { "version": "1.0.4", @@ -5713,7 +7249,17 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "peer": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5724,7 +7270,15 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "peer": true, "requires": { "ansi-regex": "^5.0.1" } @@ -5735,6 +7289,61 @@ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, + "sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "peer": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "peer": true + }, + "glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "peer": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5749,6 +7358,54 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "peer": true, + "requires": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + } + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "peer": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "peer": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", @@ -5770,6 +7427,15 @@ "rimraf": "^3.0.0" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "peer": true, + "requires": { + "is-number": "^7.0.0" + } + }, "tough-cookie": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", @@ -5790,6 +7456,12 @@ } } }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "peer": true + }, "tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -5856,6 +7528,12 @@ "requires-port": "^1.0.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "peer": true + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -5877,7 +7555,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -5931,6 +7608,17 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "peer": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5943,6 +7631,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "peer": true + }, "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 6388cb6..9c80c61 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ ], "dependencies": { "@heroicons/react": "^2.0.18", - "@newfold/ui-component-library": "^1.0.1" + "@newfold/ui-component-library": "^1.0.1", + "@tailwindcss/forms": "^0.5.8" }, "devDependencies": { "@testing-library/cypress": "^9.0.0", diff --git a/phpcs.xml b/phpcs.xml index 3541898..df08a6b 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,6 +1,6 @@ - + From e2170d616f70e52f793d9d7d2d372787ff3ba0c9 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Mon, 18 Nov 2024 14:38:02 +0000 Subject: [PATCH 24/27] linkPrefetch.js lint --- scripts/linkPrefetch.js | 174 ++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 53 deletions(-) diff --git a/scripts/linkPrefetch.js b/scripts/linkPrefetch.js index bf29f1d..9f4d5fb 100644 --- a/scripts/linkPrefetch.js +++ b/scripts/linkPrefetch.js @@ -1,18 +1,24 @@ -document.addEventListener('DOMContentLoaded', () => { - const testLink = document.createElement('link'); - const supportsPrefetch = testLink.relList?.supports?.('prefetch'); - const isDataSaver = navigator.connection?.saveData || navigator.connection?.effectiveType?.includes('2g'); - const supportsIntersectionObserver = 'IntersectionObserver' in window && 'isIntersecting' in IntersectionObserverEntry.prototype; - - if (!supportsPrefetch || isDataSaver) return; +document.addEventListener( 'DOMContentLoaded', () => { + const testLink = document.createElement( 'link' ); + const supportsPrefetch = testLink.relList?.supports?.( 'prefetch' ); + const isDataSaver = + navigator.connection?.saveData || + navigator.connection?.effectiveType?.includes( '2g' ); + const supportsIntersectionObserver = + 'IntersectionObserver' in window && + 'isIntersecting' in IntersectionObserverEntry.prototype; + + if ( ! supportsPrefetch || isDataSaver ) { + return; + } class LinkPrefetcher { - constructor(config) { - Object.assign(this, { + constructor( config ) { + Object.assign( this, { activeOnDesktop: config.activeOnDesktop, behavior: config.behavior, - hoverDelay: parseInt(config.hoverDelay) || 60, - ignoreKeywords: config.ignoreKeywords.split(','), + hoverDelay: parseInt( config.hoverDelay ) || 60, + ignoreKeywords: config.ignoreKeywords.split( ',' ), instantClick: config.instantClick, mobileActive: config.activeOnMobile, isMobile: config.isMobile, @@ -20,71 +26,134 @@ document.addEventListener('DOMContentLoaded', () => { prefetchedUrls: new Set(), eventOptions: { capture: true, passive: true }, timerId: null, - }); + } ); } init() { - const isChrome = navigator.userAgent.includes('Chrome/'); - const chromeVersion = isChrome && parseInt(navigator.userAgent.split('Chrome/')[1]); + const isChrome = navigator.userAgent.includes( 'Chrome/' ); + const chromeVersion = + isChrome && + parseInt( navigator.userAgent.split( 'Chrome/' )[ 1 ] ); - if (isChrome && chromeVersion < 110) return; - if ((this.isMobile && !this.mobileActive) || (!this.isMobile && !this.activeOnDesktop)) return; + if ( isChrome && chromeVersion < 110 ) { + return; + } + if ( + ( this.isMobile && ! this.mobileActive ) || + ( ! this.isMobile && ! this.activeOnDesktop ) + ) { + return; + } - if (!this.isMobile) { - this.behavior === 'mouseHover' && document.addEventListener('mouseover', this.handleHover.bind(this), this.eventOptions); - this.behavior === 'mouseDown' && document.addEventListener('mousedown', this.instantClick ? this.handleInstantClick.bind(this) : this.handleMouseDown.bind(this), this.eventOptions); + if ( ! this.isMobile ) { + this.behavior === 'mouseHover' && + document.addEventListener( + 'mouseover', + this.handleHover.bind( this ), + this.eventOptions + ); + this.behavior === 'mouseDown' && + document.addEventListener( + 'mousedown', + this.instantClick + ? this.handleInstantClick.bind( this ) + : this.handleMouseDown.bind( this ), + this.eventOptions + ); } - if (this.isMobile && this.mobileBehavior === 'viewport' && supportsIntersectionObserver) { + if ( + this.isMobile && + this.mobileBehavior === 'viewport' && + supportsIntersectionObserver + ) { this.setupViewportObserver(); } } setupViewportObserver() { - const observer = new IntersectionObserver((entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - observer.unobserve(entry.target); - this.prefetchIfEligible(entry.target.href); + const observer = new IntersectionObserver( ( entries ) => { + entries.forEach( ( entry ) => { + if ( entry.isIntersecting ) { + observer.unobserve( entry.target ); + this.prefetchIfEligible( entry.target.href ); } - }); - }); - - const idleCallback = window.requestIdleCallback || ((cb) => setTimeout(cb, 1)); - idleCallback(() => setTimeout(() => document.querySelectorAll('a').forEach((a) => observer.observe(a)), 1000)); + } ); + } ); + + const idleCallback = + window.requestIdleCallback || ( ( cb ) => setTimeout( cb, 1 ) ); + idleCallback( () => + setTimeout( + () => + document + .querySelectorAll( 'a' ) + .forEach( ( a ) => observer.observe( a ) ), + 1000 + ) + ); } - handleMouseDown(event) { - const el = event.target.closest('a'); - this.prefetchIfEligible(el?.href); + handleMouseDown( event ) { + const el = event.target.closest( 'a' ); + this.prefetchIfEligible( el?.href ); } - handleInstantClick(event) { - const el = event.target.closest('a'); - if (!el || event.which > 1 || event.metaKey || event.ctrlKey) return; - el.addEventListener('click', (e) => e.detail !== 'instantClick' && e.preventDefault(), { capture: true, passive: false, once: true }); - el.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: false, detail: 'instantClick' })); + handleInstantClick( event ) { + const el = event.target.closest( 'a' ); + if ( ! el || event.which > 1 || event.metaKey || event.ctrlKey ) { + return; + } + el.addEventListener( + 'click', + ( e ) => e.detail !== 'instantClick' && e.preventDefault(), + { capture: true, passive: false, once: true } + ); + el.dispatchEvent( + new MouseEvent( 'click', { + bubbles: true, + cancelable: false, + detail: 'instantClick', + } ) + ); } - handleHover(event) { - const link = event.target.closest('a'); - if (!link || !this.prefetchIfEligible(link.href)) return; - link.addEventListener('mouseout', () => clearTimeout(this.timerId), this.eventOptions); - this.timerId = setTimeout(() => this.prefetchIt(link.href), this.hoverDelay); + handleHover( event ) { + const link = event.target.closest( 'a' ); + if ( ! link || ! this.prefetchIfEligible( link.href ) ) { + return; + } + link.addEventListener( + 'mouseout', + () => clearTimeout( this.timerId ), + this.eventOptions + ); + this.timerId = setTimeout( + () => this.prefetchIt( link.href ), + this.hoverDelay + ); } - prefetchIfEligible(url) { - if (!url || this.prefetchedUrls.has(url)) return false; - if (url.replace(/\/$/, '') === location.href.replace(/\/$/, '') || this.ignoreKeywords.some((k) => url.includes(k))) return false; + prefetchIfEligible( url ) { + if ( ! url || this.prefetchedUrls.has( url ) ) { + return false; + } + if ( + url.replace( /\/$/, '' ) === + location.href.replace( /\/$/, '' ) || + this.ignoreKeywords.some( ( k ) => url.includes( k ) ) + ) { + return false; + } return true; } - prefetchIt(url) { - const link = document.createElement('link'); + prefetchIt( url ) { + const link = document.createElement( 'link' ); link.rel = 'prefetch'; link.href = url; - document.head.appendChild(link); - this.prefetchedUrls.add(url); + document.head.appendChild( link ); + this.prefetchedUrls.add( url ); } } @@ -98,6 +167,5 @@ document.addEventListener('DOMContentLoaded', () => { ignoreKeywords: 'wp-admin,#,?', }; - new LinkPrefetcher(config).init(); -}); - + new LinkPrefetcher( config ).init(); +} ); From 96f9b80df659f20abb12752bf456fc3539ebc0d6 Mon Sep 17 00:00:00 2001 From: arunshenoy99 Date: Wed, 20 Nov 2024 20:25:09 +0800 Subject: [PATCH 25/27] Lint js files --- components/linkPrefetch/index.js | 318 ++++++++++++++++---------- components/performance/defaultText.js | 181 +++++++++++---- components/performance/index.js | 95 ++++---- 3 files changed, 388 insertions(+), 206 deletions(-) diff --git a/components/linkPrefetch/index.js b/components/linkPrefetch/index.js index 060cd2b..ebc8f99 100644 --- a/components/linkPrefetch/index.js +++ b/components/linkPrefetch/index.js @@ -1,134 +1,220 @@ -import { Toggle, TextField, SelectField, Container } from "@newfold/ui-component-library"; +import { + Toggle, + TextField, + SelectField, + Container, +} from '@newfold/ui-component-library'; -const LinkPrefetch = ({methods, constants}) => { - const [settings, setSettings] = methods.useState(methods.NewfoldRuntime.sdk.linkPrefetch.settings); - const [isError, setIsError] = methods.useState(false); - const apiUrl = methods.NewfoldRuntime.createApiUrl("/newfold-performance/v1/link-prefetch/settings"); +const LinkPrefetch = ( { methods, constants } ) => { + const [ settings, setSettings ] = methods.useState( + methods.NewfoldRuntime.sdk.linkPrefetch.settings + ); + const [ isError, setIsError ] = methods.useState( false ); + const apiUrl = methods.NewfoldRuntime.createApiUrl( + '/newfold-performance/v1/link-prefetch/settings' + ); - const handleChangeOption = (option, value) => { - if (!(option in settings)) return; - const updatedSettings = { ...settings, [option]: value }; + const handleChangeOption = ( option, value ) => { + if ( ! ( option in settings ) ) return; + const updatedSettings = { ...settings, [ option ]: value }; methods - .apiFetch({ + .apiFetch( { url: apiUrl, - method: "POST", + method: 'POST', data: { settings: updatedSettings }, - }) - .then(() => { - setSettings((prev) => ({ ...prev, [option]: value })); - }) - .catch((error) => { - setIsError(error.message); - }); + } ) + .then( () => { + setSettings( ( prev ) => ( { ...prev, [ option ]: value } ) ); + } ) + .catch( ( error ) => { + setIsError( error.message ); + } ); }; - methods.useUpdateEffect(() => { - methods.setStore({ - ...constants.store, - linkPrefetch: settings, - }); + methods.useUpdateEffect( () => { + methods.setStore( { + ...constants.store, + linkPrefetch: settings, + } ); - methods.makeNotice( - "link-prefetch-change-notice", - constants.text.linkPrefetchTitle, + methods.makeNotice( + 'link-prefetch-change-notice', + constants.text.linkPrefetchTitle, isError || constants.text.linkPrefetchNoticeTitle, - isError ? "error" : "success", - 5000 - ); - }, [settings, isError]); + isError ? 'error' : 'success', + 5000 + ); + }, [ settings, isError ] ); - return( + return ( <> - - {/* Desktop Settings */} -
-
- -
- {constants.text.linkPrefetchActivateOnDesktopDescription} + + { /* Desktop Settings */ } +
+
+ +
+ { + constants.text + .linkPrefetchActivateOnDesktopDescription + } +
-
- handleChangeOption( 'activeOnDesktop', !settings.activeOnDesktop) } - /> -
- { settings.activeOnDesktop && ( - handleChangeOption( 'behavior', v) } - description={ 'mouseDown' === settings.behavior ? constants.text.linkPrefetchBehaviorMouseDownDescription : constants.text.linkPrefetchBehaviorMouseHoverDescription} - className='nfd-mb-6' - > - + handleChangeOption( + 'activeOnDesktop', + ! settings.activeOnDesktop + ) + } /> - - - ) - } - {/* Mobile Settings */} -
-
- -
- {constants.text.linkPrefetchActivateOnMobileDescription} +
+ { settings.activeOnDesktop && ( + + handleChangeOption( 'behavior', v ) + } + description={ + 'mouseDown' === settings.behavior + ? constants.text + .linkPrefetchBehaviorMouseDownDescription + : constants.text + .linkPrefetchBehaviorMouseHoverDescription + } + className="nfd-mb-6" + > + + + + ) } + { /* Mobile Settings */ } +
+
+ +
+ { + constants.text + .linkPrefetchActivateOnMobileDescription + } +
-
- handleChangeOption('activeOnMobile', !settings.activeOnMobile) } - /> -
- { settings.activeOnMobile && ( - handleChangeOption( 'mobileBehavior', v) } - description={'touchstart' === settings.mobileBehavior ? constants.text.linkPrefetchBehaviorMobileTouchstartDescription : constants.text.linkPrefetchBehaviorMobileViewportDescription} - className='nfd-mb-6' - > - + handleChangeOption( + 'activeOnMobile', + ! settings.activeOnMobile + ) + } /> - + { settings.activeOnMobile && ( + + handleChangeOption( 'mobileBehavior', v ) + } + description={ + 'touchstart' === settings.mobileBehavior + ? constants.text + .linkPrefetchBehaviorMobileTouchstartDescription + : constants.text + .linkPrefetchBehaviorMobileViewportDescription + } + className="nfd-mb-6" + > + + + + ) } + { /* Ignore Keywords */ } + { ( settings.activeOnMobile || settings.activeOnDesktop ) && ( + + handleChangeOption( + 'ignoreKeywords', + e.target.value + ) + } + value={ settings.ignoreKeywords } /> - - ) - } - {/* Ignore Keywords */} - { ( settings.activeOnMobile || settings.activeOnDesktop ) && - handleChangeOption('ignoreKeywords', e.target.value)} - value={settings.ignoreKeywords} - /> - } - - + ) } + - ) -} + ); +}; -export default LinkPrefetch; \ No newline at end of file +export default LinkPrefetch; diff --git a/components/performance/defaultText.js b/components/performance/defaultText.js index 8b1c399..c286dcd 100644 --- a/components/performance/defaultText.js +++ b/components/performance/defaultText.js @@ -1,46 +1,141 @@ +import { __ } from '@wordpress/i18n'; + const defaultText = { - cacheLevel0Description: __('No cache enabled. Every page load is fresh. ', 'wp-module-performance'), - cacheLevel0Label: __('Disabled', 'wp-module-performance'), - cacheLevel0NoticeText: __('Caching disabled.', 'wp-module-performance'), - cacheLevel0Recommendation: __('Not recommended.', 'wp-module-performance'), - cacheLevel1Description: __('Cache static assets like images and the appearance of your site for 1 hour. ', 'wp-module-performance'), - cacheLevel1Label: __('Assets Only', 'wp-module-performance'), - cacheLevel1NoticeText: __('Cache enabled for assets only.', 'wp-module-performance'), - cacheLevel1Recommendation: __('Tuned for online stores and member sites that need to be fresh.', 'wp-module-performance'), - cacheLevel2Description: __('Cache static assets for 24 hours and web pages for 2 hours. ', 'wp-module-performance'), - cacheLevel2Label: __('Assets & Web Pages', 'wp-module-performance'), - cacheLevel2NoticeText: __('Cache enabled for assets and pages.', 'wp-module-performance'), - cacheLevel2Recommendation: __('Tuned for sites that change at least weekly.', 'wp-module-performance'), - cacheLevel3Description: __('Cache static assets for 1 week and web pages for 8 hours. ', 'wp-module-performance'), - cacheLevel3Label: __('Assets & Web Pages - Extended', 'wp-module-performance'), - cacheLevel3NoticeText: __('Cache enabled for assets and pages (extended).', 'wp-module-performance'), - cacheLevel3Recommendation: __('Tuned for sites that update a few times a month or less.', 'wp-module-performance'), - cacheLevelDescription: __('Boost speed and performance by storing a copy of your website content, files, and images online so the pages of your website load faster for your visitors.', 'wp-module-performance'), - cacheLevelNoticeTitle: __('Cache setting saved', 'wp-module-performance'), - cacheLevelTitle: __('Cache Level', 'wp-module-performance'), - clearCacheButton: __('Clear All Cache Now', 'wp-module-performance'), - clearCacheDescription: __('We automatically clear your cache as you work (creating content, changing settings, installing plugins and more). But you can manually clear it here to be confident it is fresh.', 'wp-module-performance'), - clearCacheNoticeTitle: __('Cache cleared', 'wp-module-performance'), - clearCacheTitle: __('Clear Cache', 'wp-module-performance'), - linkPrefetchDescription: __('Asks the browser to download and cache links on the page ahead of them being clicked on, so that when they are clicked they load almost instantly. ','wp-module-performance'), - linkPrefetchNoticeTitle: __('Link prefetching setting saved','wp-module-performance'), - linkPrefetchTitle: __('Link Prefetch','wp-module-performance'), - linkPrefetchActivateOnDesktopDescription: __('Enable link prefetching on desktop','wp-module-performance'), - linkPrefetchActivateOnDesktopLabel: __('Activate on desktop','wp-module-performance'), - linkPrefetchBehaviorDescription: __('Behavior of the prefetch','wp-module-performance'), - linkPrefetchBehaviorLabel: __('Behavior','wp-module-performance'), - linkPrefetchBehaviorMouseDownLabel: __('Prefetch on Mouse down','wp-module-performance'), - linkPrefetchBehaviorMouseDownDescription: __('Prefetch on Mouse Down: Starts loading the page as soon as you click down, for faster response when you release the click.','wp-module-performance'), - linkPrefetchBehaviorMouseHoverLabel: __('Prefetch on Mouse Hover (Recommended)','wp-module-performance'), - linkPrefetchBehaviorMouseHoverDescription: __('Prefetch on Mouse Hover: Begins loading the page the moment your cursor hovers over a link','wp-module-performance'), - linkPrefetchActivateOnMobileDescription: __('Enable link prefetching on Mobile','wp-module-performance'), - linkPrefetchActivateOnMobileLabel: __('Activate on mobile','wp-module-performance'), - linkPrefetchBehaviorMobileTouchstartLabel: __('Prefetch on Touchstart (Recommended)','wp-module-performance'), - linkPrefetchBehaviorMobileTouchstartDescription: __('Prefetch on Touch Start: Instantly starts loading the page as soon as you tap the screen, ensuring a quicker response when you lift your finger.','wp-module-performance'), - linkPrefetchBehaviorMobileViewportLabel: __('Prefetch Above the Fold','wp-module-performance'), - linkPrefetchBehaviorMobileViewportDescription: __('Prefetch Above the Fold: Loads links in your current view instantly, ensuring they\'re ready when you need them.','wp-module-performance'), - linkPrefetchIgnoreKeywordsDescription: __('Exclude Keywords: A comma separated list of words or strings that will exclude a link from being prefetched. For example, excluding "app" will prevent https://example.com/apple from being prefetched.','wp-module-performance'), - linkPrefetchIgnoreKeywordsLabel: __('Exclude keywords','wp-module-performance'), + cacheLevel0Description: __( + 'No cache enabled. Every page load is fresh. ', + 'wp-module-performance' + ), + cacheLevel0Label: __( 'Disabled', 'wp-module-performance' ), + cacheLevel0NoticeText: __( 'Caching disabled.', 'wp-module-performance' ), + cacheLevel0Recommendation: __( + 'Not recommended.', + 'wp-module-performance' + ), + cacheLevel1Description: __( + 'Cache static assets like images and the appearance of your site for 1 hour. ', + 'wp-module-performance' + ), + cacheLevel1Label: __( 'Assets Only', 'wp-module-performance' ), + cacheLevel1NoticeText: __( + 'Cache enabled for assets only.', + 'wp-module-performance' + ), + cacheLevel1Recommendation: __( + 'Tuned for online stores and member sites that need to be fresh.', + 'wp-module-performance' + ), + cacheLevel2Description: __( + 'Cache static assets for 24 hours and web pages for 2 hours. ', + 'wp-module-performance' + ), + cacheLevel2Label: __( 'Assets & Web Pages', 'wp-module-performance' ), + cacheLevel2NoticeText: __( + 'Cache enabled for assets and pages.', + 'wp-module-performance' + ), + cacheLevel2Recommendation: __( + 'Tuned for sites that change at least weekly.', + 'wp-module-performance' + ), + cacheLevel3Description: __( + 'Cache static assets for 1 week and web pages for 8 hours. ', + 'wp-module-performance' + ), + cacheLevel3Label: __( + 'Assets & Web Pages - Extended', + 'wp-module-performance' + ), + cacheLevel3NoticeText: __( + 'Cache enabled for assets and pages (extended).', + 'wp-module-performance' + ), + cacheLevel3Recommendation: __( + 'Tuned for sites that update a few times a month or less.', + 'wp-module-performance' + ), + cacheLevelDescription: __( + 'Boost speed and performance by storing a copy of your website content, files, and images online so the pages of your website load faster for your visitors.', + 'wp-module-performance' + ), + cacheLevelNoticeTitle: __( 'Cache setting saved', 'wp-module-performance' ), + cacheLevelTitle: __( 'Cache Level', 'wp-module-performance' ), + clearCacheButton: __( 'Clear All Cache Now', 'wp-module-performance' ), + clearCacheDescription: __( + 'We automatically clear your cache as you work (creating content, changing settings, installing plugins and more). But you can manually clear it here to be confident it is fresh.', + 'wp-module-performance' + ), + clearCacheNoticeTitle: __( 'Cache cleared', 'wp-module-performance' ), + clearCacheTitle: __( 'Clear Cache', 'wp-module-performance' ), + linkPrefetchDescription: __( + 'Asks the browser to download and cache links on the page ahead of them being clicked on, so that when they are clicked they load almost instantly. ', + 'wp-module-performance' + ), + linkPrefetchNoticeTitle: __( + 'Link prefetching setting saved', + 'wp-module-performance' + ), + linkPrefetchTitle: __( 'Link Prefetch', 'wp-module-performance' ), + linkPrefetchActivateOnDesktopDescription: __( + 'Enable link prefetching on desktop', + 'wp-module-performance' + ), + linkPrefetchActivateOnDesktopLabel: __( + 'Activate on desktop', + 'wp-module-performance' + ), + linkPrefetchBehaviorDescription: __( + 'Behavior of the prefetch', + 'wp-module-performance' + ), + linkPrefetchBehaviorLabel: __( 'Behavior', 'wp-module-performance' ), + linkPrefetchBehaviorMouseDownLabel: __( + 'Prefetch on Mouse down', + 'wp-module-performance' + ), + linkPrefetchBehaviorMouseDownDescription: __( + 'Prefetch on Mouse Down: Starts loading the page as soon as you click down, for faster response when you release the click.', + 'wp-module-performance' + ), + linkPrefetchBehaviorMouseHoverLabel: __( + 'Prefetch on Mouse Hover (Recommended)', + 'wp-module-performance' + ), + linkPrefetchBehaviorMouseHoverDescription: __( + 'Prefetch on Mouse Hover: Begins loading the page the moment your cursor hovers over a link', + 'wp-module-performance' + ), + linkPrefetchActivateOnMobileDescription: __( + 'Enable link prefetching on Mobile', + 'wp-module-performance' + ), + linkPrefetchActivateOnMobileLabel: __( + 'Activate on mobile', + 'wp-module-performance' + ), + linkPrefetchBehaviorMobileTouchstartLabel: __( + 'Prefetch on Touchstart (Recommended)', + 'wp-module-performance' + ), + linkPrefetchBehaviorMobileTouchstartDescription: __( + 'Prefetch on Touch Start: Instantly starts loading the page as soon as you tap the screen, ensuring a quicker response when you lift your finger.', + 'wp-module-performance' + ), + linkPrefetchBehaviorMobileViewportLabel: __( + 'Prefetch Above the Fold', + 'wp-module-performance' + ), + linkPrefetchBehaviorMobileViewportDescription: __( + "Prefetch Above the Fold: Loads links in your current view instantly, ensuring they're ready when you need them.", + 'wp-module-performance' + ), + linkPrefetchIgnoreKeywordsDescription: __( + 'Exclude Keywords: A comma separated list of words or strings that will exclude a link from being prefetched. For example, excluding "app" will prevent https://example.com/apple from being prefetched.', + 'wp-module-performance' + ), + linkPrefetchIgnoreKeywordsLabel: __( + 'Exclude keywords', + 'wp-module-performance' + ), }; -export default defaultText; \ No newline at end of file +export default defaultText; diff --git a/components/performance/index.js b/components/performance/index.js index 76672dd..a7b9878 100644 --- a/components/performance/index.js +++ b/components/performance/index.js @@ -7,60 +7,61 @@ import { default as LinkPrefetch } from '../linkPrefetch/'; /** * Performance Module * For use in brand plugin apps to display performance page and settings - * - * @param {*} props - * @returns + * + * @param {*} props + * @return */ -const Performance = ({methods, constants, Components, ...props}) => { - const { store, setStore } = methods.useContext(methods.AppStore); - const [ isError, setError ] = methods.useState(false); +const Performance = ( { methods, constants, Components, ...props } ) => { + const { store, setStore } = methods.useContext( methods.AppStore ); + const [ isError, setError ] = methods.useState( false ); - let notify = methods.useNotification(); + const notify = methods.useNotification(); // set default text if not provided - constants.text = Object.assign(defaultText, constants.text); + constants.text = Object.assign( defaultText, constants.text ); - const makeNotice = (id, title, description, variant="success", duration=false) => { - notify.push(`performance-notice-${id}`, { - title, - description: ( - - {description} - - ), - variant, - autoDismiss: duration, - }); - }; - constants.store = store; - methods.makeNotice = makeNotice; - methods.setStore = setStore; - methods.setError = setError; + const makeNotice = ( + id, + title, + description, + variant = 'success', + duration = false + ) => { + notify.push( `performance-notice-${ id }`, { + title, + description: { description }, + variant, + autoDismiss: duration, + } ); + }; + constants.store = store; + methods.makeNotice = makeNotice; + methods.setStore = setStore; + methods.setError = setError; return ( - <> - - - - - - - - - - + <> + + + + + + + + + + ); - }; -export default Performance; \ No newline at end of file +export default Performance; From a78673c3499834d7ce6b9643bdacca22460df2ae Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Wed, 27 Nov 2024 12:09:46 +0000 Subject: [PATCH 26/27] fix for mousedown event --- scripts/linkPrefetch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/linkPrefetch.js b/scripts/linkPrefetch.js index 9f4d5fb..d774869 100644 --- a/scripts/linkPrefetch.js +++ b/scripts/linkPrefetch.js @@ -96,7 +96,7 @@ document.addEventListener( 'DOMContentLoaded', () => { handleMouseDown( event ) { const el = event.target.closest( 'a' ); - this.prefetchIfEligible( el?.href ); + this.prefetchIfEligible( el?.href ) && this.prefetchIt( el?.href ); } handleInstantClick( event ) { From cd5d1d8ce6c65c528963a2cd25d5fb5bbd889d66 Mon Sep 17 00:00:00 2001 From: Armando Liccardo Date: Wed, 27 Nov 2024 15:27:33 +0000 Subject: [PATCH 27/27] adding minified js --- scripts/linkPrefetch.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/linkPrefetch.min.js b/scripts/linkPrefetch.min.js index a487957..e59fda1 100644 --- a/scripts/linkPrefetch.min.js +++ b/scripts/linkPrefetch.min.js @@ -1 +1 @@ -document.addEventListener("DOMContentLoaded",(()=>{const e=document.createElement("link"),t=e.relList?.supports?.("prefetch"),i=navigator.connection?.saveData||navigator.connection?.effectiveType?.includes("2g"),s="IntersectionObserver"in window&&"isIntersecting"in IntersectionObserverEntry.prototype;if(!t||i)return;const n=window.LP_CONFIG||{activeOnDesktop:!0,behavior:"mouseHover",hoverDelay:60,instantClick:!0,activeOnMobile:!0,mobileBehavior:"viewport",ignoreKeywords:"wp-admin,#,?"};new class{constructor(e){Object.assign(this,{activeOnDesktop:e.activeOnDesktop,behavior:e.behavior,hoverDelay:parseInt(e.hoverDelay)||60,ignoreKeywords:e.ignoreKeywords.split(","),instantClick:e.instantClick,mobileActive:e.activeOnMobile,isMobile:e.isMobile,mobileBehavior:e.mobileBehavior,prefetchedUrls:new Set,eventOptions:{capture:!0,passive:!0},timerId:null})}init(){const e=navigator.userAgent.includes("Chrome/"),t=e&&parseInt(navigator.userAgent.split("Chrome/")[1]);e&&t<110||this.isMobile&&!this.mobileActive||!this.isMobile&&!this.activeOnDesktop||(this.isMobile||("mouseHover"===this.behavior&&document.addEventListener("mouseover",this.handleHover.bind(this),this.eventOptions),"mouseDown"===this.behavior&&document.addEventListener("mousedown",this.instantClick?this.handleInstantClick.bind(this):this.handleMouseDown.bind(this),this.eventOptions)),this.isMobile&&"viewport"===this.mobileBehavior&&s&&this.setupViewportObserver())}setupViewportObserver(){const e=new IntersectionObserver((t=>{t.forEach((t=>{t.isIntersecting&&(e.unobserve(t.target),this.prefetchIfEligible(t.target.href))}))}));(window.requestIdleCallback||(e=>setTimeout(e,1)))((()=>setTimeout((()=>document.querySelectorAll("a").forEach((t=>e.observe(t)))),1e3)))}handleMouseDown(e){const t=e.target.closest("a");this.prefetchIfEligible(t?.href)}handleInstantClick(e){const t=e.target.closest("a");!t||e.which>1||e.metaKey||e.ctrlKey||(t.addEventListener("click",(e=>"instantClick"!==e.detail&&e.preventDefault()),{capture:!0,passive:!1,once:!0}),t.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!1,detail:"instantClick"})))}handleHover(e){const t=e.target.closest("a");t&&this.prefetchIfEligible(t.href)&&(t.addEventListener("mouseout",(()=>clearTimeout(this.timerId)),this.eventOptions),this.timerId=setTimeout((()=>this.prefetchIt(t.href)),this.hoverDelay))}prefetchIfEligible(e){return!(!e||this.prefetchedUrls.has(e))&&(e.replace(/\/$/,"")!==location.href.replace(/\/$/,"")&&!this.ignoreKeywords.some((t=>e.includes(t))))}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,document.head.appendChild(t),this.prefetchedUrls.add(e)}}(n).init()})); \ No newline at end of file +document.addEventListener("DOMContentLoaded",(()=>{const e=document.createElement("link"),t=e.relList?.supports?.("prefetch"),i=navigator.connection?.saveData||navigator.connection?.effectiveType?.includes("2g"),s="IntersectionObserver"in window&&"isIntersecting"in IntersectionObserverEntry.prototype;if(!t||i)return;const n=window.LP_CONFIG||{activeOnDesktop:!0,behavior:"mouseHover",hoverDelay:60,instantClick:!0,activeOnMobile:!0,mobileBehavior:"viewport",ignoreKeywords:"wp-admin,#,?"};new class{constructor(e){Object.assign(this,{activeOnDesktop:e.activeOnDesktop,behavior:e.behavior,hoverDelay:parseInt(e.hoverDelay)||60,ignoreKeywords:e.ignoreKeywords.split(","),instantClick:e.instantClick,mobileActive:e.activeOnMobile,isMobile:e.isMobile,mobileBehavior:e.mobileBehavior,prefetchedUrls:new Set,eventOptions:{capture:!0,passive:!0},timerId:null})}init(){const e=navigator.userAgent.includes("Chrome/"),t=e&&parseInt(navigator.userAgent.split("Chrome/")[1]);e&&t<110||this.isMobile&&!this.mobileActive||!this.isMobile&&!this.activeOnDesktop||(this.isMobile||("mouseHover"===this.behavior&&document.addEventListener("mouseover",this.handleHover.bind(this),this.eventOptions),"mouseDown"===this.behavior&&document.addEventListener("mousedown",this.instantClick?this.handleInstantClick.bind(this):this.handleMouseDown.bind(this),this.eventOptions)),this.isMobile&&"viewport"===this.mobileBehavior&&s&&this.setupViewportObserver())}setupViewportObserver(){const e=new IntersectionObserver((t=>{t.forEach((t=>{t.isIntersecting&&(e.unobserve(t.target),this.prefetchIfEligible(t.target.href))}))}));(window.requestIdleCallback||(e=>setTimeout(e,1)))((()=>setTimeout((()=>document.querySelectorAll("a").forEach((t=>e.observe(t)))),1e3)))}handleMouseDown(e){const t=e.target.closest("a");this.prefetchIfEligible(t?.href)&&this.prefetchIt(t?.href)}handleInstantClick(e){const t=e.target.closest("a");!t||e.which>1||e.metaKey||e.ctrlKey||(t.addEventListener("click",(e=>"instantClick"!==e.detail&&e.preventDefault()),{capture:!0,passive:!1,once:!0}),t.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!1,detail:"instantClick"})))}handleHover(e){const t=e.target.closest("a");t&&this.prefetchIfEligible(t.href)&&(t.addEventListener("mouseout",(()=>clearTimeout(this.timerId)),this.eventOptions),this.timerId=setTimeout((()=>this.prefetchIt(t.href)),this.hoverDelay))}prefetchIfEligible(e){return!(!e||this.prefetchedUrls.has(e))&&(e.replace(/\/$/,"")!==location.href.replace(/\/$/,"")&&!this.ignoreKeywords.some((t=>e.includes(t))))}prefetchIt(e){const t=document.createElement("link");t.rel="prefetch",t.href=e,document.head.appendChild(t),this.prefetchedUrls.add(e)}}(n).init()})); \ No newline at end of file