Commit f87fa99f4b4 for woocommerce
commit f87fa99f4b47d242d67c5edfd25563e67983824e
Author: Luigi Teschio <gigitux@gmail.com>
Date: Thu Jul 9 10:33:20 2026 +0200
Load stable WC Admin features directly (#65472)
* Load stable WC Admin features directly
* Refactor legacy WooCommerce Admin feature toggles
* clean up feature flag
* Keep WC Admin shell features always on (#65473)
* Keep WC Admin shell features always on
* fix logic
* clean up changes
* implement check
* Keep WC Admin analytics always on (#65474)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* fix logic
* clean up changes
* address feedback
* Keep WC Admin onboarding tasks always on (#65475)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* Keep WC Admin onboarding tasks always on
* fix logic
* clean up changes
* address feedback
* clean up code
* clean up code
* Update file
* rename folder
* delete woocommerce-shipping-item and rename experimental-woocommerce-shipping-item to woocommerce-shipping-item
* Keep Launch Your Store always on (#65476)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* Keep WC Admin onboarding tasks always on
* Keep Launch Your Store always on
* fix logic
* clean up changes
* address feedback
* clean up code
* clean up code
* clean up feature flag
* restore changes
* remove flag
* Update file
* Keep Mini-Cart interactivity always on (#65477)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* Keep WC Admin onboarding tasks always on
* Keep Launch Your Store always on
* Keep Mini-Cart interactivity always on
* fix logic
* clean up changes
* address feedback
* clean up code
* clean up code
* clean up code
* remove not necessary tests
* clean up feature flag
* restore changes
* refactor: update phpstan baseline by removing and re-adding return type messages for MiniCart blocks
* Update plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* address feedback
* generate baseline
* fix build webpack
* remove flag
* clean up code
* update baseline
* Update file
* remove set-styles file
* clean up webpack configuration
* add comment
* remove cart_item_count duplicate
* address feedback
* fix unit test
* lint code
* fix baseline
---------
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* Keep product pattern features always on (#65478)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* Keep WC Admin onboarding tasks always on
* Keep Launch Your Store always on
* Keep Mini-Cart interactivity always on
* Keep product pattern features always on
* fix logic
* clean up changes
* address feedback
* clean up code
* clean up code
* clean up code
* remove not necessary tests
* clean up feature flag
* restore changes
* refactor: update phpstan baseline by removing and re-adding return type messages for MiniCart blocks
* Update plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* address feedback
* generate baseline
* fix build webpack
* clean up code
* update baseline
* restore changes
---------
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* Keep commerce recommendations always on (#65479)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* Keep WC Admin onboarding tasks always on
* Keep Launch Your Store always on
* Keep Mini-Cart interactivity always on
* Keep product pattern features always on
* Keep commerce recommendations always on
* fix logic
* clean up changes
* address feedback
* clean up code
* clean up code
* clean up code
* remove not necessary tests
* clean up feature flag
* restore changes
* refactor: update phpstan baseline by removing and re-adding return type messages for MiniCart blocks
* lint code
* Update plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* address feedback
* generate baseline
* fix build webpack
* clean up code
* update baseline
* fix unit test
* restore file
* restore changes
---------
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* remove setup for legacy MiniCart E2E tests
* clean up setting file
* fix baseline
* Remove legacy Mini-Cart React frontend modules (#66056)
* Remove stale Mini-Cart cleanup leftovers (#66091)
* Remove stale Mini-Cart cleanup leftovers
* Update lazy-loaded translations docs for Mini-Cart cleanup
* Update WooCommerce Blocks docs references
* restore not related changes
* clean up package.json
* Add deprecated WC Admin feature flag shims (#65636)
* Keep WC Admin shell features always on
* Keep WC Admin analytics always on
* Keep WC Admin onboarding tasks always on
* Keep Launch Your Store always on
* Keep Mini-Cart interactivity always on
* Keep product pattern features always on
* Keep commerce recommendations always on
* fix logic
* clean up changes
* address feedback
* clean up code
* clean up code
* clean up code
* remove not necessary tests
* clean up feature flag
* restore changes
* refactor: update phpstan baseline by removing and re-adding return type messages for MiniCart blocks
* lint code
* Update plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* address feedback
* generate baseline
* fix build webpack
* clean up code
* update baseline
* fix unit test
* Add deprecated WC Admin feature flag shims
* Refactor retired feature flags to include removal versions and update deprecation messages
* remove unit test
* clean up codebase
* clean up code
* use deprecated
* restore change
* refactor: streamline feature loading process by using a dedicated array for always-loaded features
* improve logic
* clean up logic
* clean up code
* fix types
* improve logic
* remove unit test
* fix import
* add comment
* WIP
* bump version
---------
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
* fix baseline
* fix unit test
* fix lint error
* Preserve store alerts as a non-deprecated feature flag and update related configurations
---------
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
diff --git a/docs/block-development/reference/block-references.md b/docs/block-development/reference/block-references.md
index aae0ac5f878..c4d9af106c2 100644
--- a/docs/block-development/reference/block-references.md
+++ b/docs/block-development/reference/block-references.md
@@ -887,7 +887,7 @@ Display a button for shoppers to quickly view their cart.
- **Name:** woocommerce/mini-cart
- **Category:** woocommerce
-- **Supports:** spacing (margin, padding), typography (fontSize), ~~html~~, ~~multiple~~
+- **Supports:** interactivity, spacing (margin, padding), typography (fontSize), ~~html~~, ~~multiple~~
- **Attributes:** addToCartBehaviour, cartAndCheckoutRenderStyle, hasHiddenPrice, iconColor, iconColorValue, miniCartIcon, onCartClickBehaviour, priceColor, priceColorValue, productCountColor, productCountColorValue, productCountVisibility
## Mini-Cart Contents - woocommerce/mini-cart-contents
diff --git a/plugins/woocommerce-beta-tester/userscripts/wc-live-branches.user.js b/plugins/woocommerce-beta-tester/userscripts/wc-live-branches.user.js
index 3b73d46d1ac..fa20f7edb8c 100644
--- a/plugins/woocommerce-beta-tester/userscripts/wc-live-branches.user.js
+++ b/plugins/woocommerce-beta-tester/userscripts/wc-live-branches.user.js
@@ -76,8 +76,7 @@
}
try {
const data = JSON.parse( el.textContent );
- const pr =
- data?.payload?.pullRequestsLayoutRoute?.pullRequest;
+ const pr = data?.payload?.pullRequestsLayoutRoute?.pullRequest;
if ( pr?.headBranch && pr?.state ) {
return {
currentBranch: pr.headBranch,
@@ -102,13 +101,16 @@
if ( ! currentBranch ) {
return null;
}
- const branchStatus = $( '.gh-header-meta .State' )
- .text()
- .trim();
+ const branchStatus = $( '.gh-header-meta .State' ).text().trim();
if ( ! branchStatus ) {
return null;
}
- return { currentBranch, branchStatus, headRepoOwner: '', isDraft: false };
+ return {
+ currentBranch,
+ branchStatus,
+ headRepoOwner: '',
+ isDraft: false,
+ };
}
/** Function. */
@@ -125,8 +127,7 @@
const host = 'https://jurassic.ninja';
const repo = determineRepo();
- const prData =
- getPRDataFromEmbeddedJson() ?? getPRDataFromDom();
+ const prData = getPRDataFromEmbeddedJson() ?? getPRDataFromDom();
if ( ! prData ) {
appendHtml(
markdownBody,
@@ -136,8 +137,7 @@
}
const { currentBranch, branchStatus } = prData;
const branchIsForked = prData.headRepoOwner
- ? prData.headRepoOwner !==
- ( repo ? repo.split( '/' )[ 0 ] : '' )
+ ? prData.headRepoOwner !== ( repo ? repo.split( '/' )[ 0 ] : '' )
: currentBranch.includes( ':' );
if ( branchStatus === 'MERGED' || branchStatus === 'Merged' ) {
@@ -170,7 +170,6 @@
} else {
// TODO: Fetch the list of feature flags dynamically from the API or something.
const featureFlags = [
- 'launch-your-store',
'minified-js',
'product-custom-fields',
'settings',
diff --git a/plugins/woocommerce/bin/set-legacy-minicart-flag.js b/plugins/woocommerce/bin/set-legacy-minicart-flag.js
deleted file mode 100644
index 744cbe3168a..00000000000
--- a/plugins/woocommerce/bin/set-legacy-minicart-flag.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Sets the experimental-iapi-mini-cart feature flag to false in both
- * client/admin/config/core.json and client/admin/config/development.json.
- */
-
-const fs = require( 'fs' );
-const path = require( 'path' );
-
-function setFlag( filePath, key, value ) {
- const json = JSON.parse( fs.readFileSync( filePath, 'utf8' ) );
- if ( ! json.features || typeof json.features !== 'object' ) {
- json.features = {};
- }
- json.features[ key ] = value;
- fs.writeFileSync(
- filePath,
- JSON.stringify( json, null, 2 ) + '\n',
- 'utf8'
- );
-}
-
-function main() {
- const pluginRoot = path.resolve( __dirname, '..' );
- const coreJson = path.join(
- pluginRoot,
- 'client',
- 'admin',
- 'config',
- 'core.json'
- );
- const devJson = path.join(
- pluginRoot,
- 'client',
- 'admin',
- 'config',
- 'development.json'
- );
-
- const flagKey = 'experimental-iapi-mini-cart';
- const flagValue = false;
-
- const files = [ coreJson, devJson ];
- files.forEach( ( file ) => {
- if ( ! fs.existsSync( file ) ) {
- throw new Error( `Config file not found: ${ file }` );
- }
- } );
-
- files.forEach( ( file ) => setFlag( file, flagKey, flagValue ) );
-
- // Output for quick verification in CI logs
- files.forEach( ( file ) => {
- const json = JSON.parse( fs.readFileSync( file, 'utf8' ) );
- // eslint-disable-next-line no-console
- console.log(
- `Set ${ flagKey } to ${
- json.features?.[ flagKey ]
- } in ${ path.relative( process.cwd(), file ) }`
- );
- } );
-}
-
-main();
diff --git a/plugins/woocommerce/changelog/dev-deflag-wc-admin-feature-compatibility-shims b/plugins/woocommerce/changelog/dev-deflag-wc-admin-feature-compatibility-shims
new file mode 100644
index 00000000000..1e004401626
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-deflag-wc-admin-feature-compatibility-shims
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Add deprecated compatibility shims for retired WooCommerce Admin feature flags.
diff --git a/plugins/woocommerce/changelog/dev-deflag-wc-admin-feature-config b/plugins/woocommerce/changelog/dev-deflag-wc-admin-feature-config
new file mode 100644
index 00000000000..da859d75414
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-deflag-wc-admin-feature-config
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Remove stable WooCommerce Admin flags from the legacy feature config and load their classes directly.
diff --git a/plugins/woocommerce/changelog/update-deflag-commerce-recommendations b/plugins/woocommerce/changelog/update-deflag-commerce-recommendations
new file mode 100644
index 00000000000..58dbd86ec35
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-commerce-recommendations
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep WooCommerce Admin commerce recommendations enabled without legacy feature flags.
diff --git a/plugins/woocommerce/changelog/update-deflag-launch-your-store b/plugins/woocommerce/changelog/update-deflag-launch-your-store
new file mode 100644
index 00000000000..46ce6b14c96
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-launch-your-store
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep Launch Your Store and coming soon behavior enabled without legacy feature flags.
diff --git a/plugins/woocommerce/changelog/update-deflag-mini-cart-iapi b/plugins/woocommerce/changelog/update-deflag-mini-cart-iapi
new file mode 100644
index 00000000000..4ed1c52bcc5
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-mini-cart-iapi
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep the Mini-Cart Interactivity API behavior enabled without a legacy feature flag.
diff --git a/plugins/woocommerce/changelog/update-deflag-product-pattern-features b/plugins/woocommerce/changelog/update-deflag-product-pattern-features
new file mode 100644
index 00000000000..3171d8c9180
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-product-pattern-features
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep product editor and pattern toolkit behavior enabled without legacy feature flags.
diff --git a/plugins/woocommerce/changelog/update-deflag-wc-admin-analytics b/plugins/woocommerce/changelog/update-deflag-wc-admin-analytics
new file mode 100644
index 00000000000..efeec0f97b0
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-wc-admin-analytics
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep WooCommerce Admin analytics and scheduled imports enabled without legacy feature flags.
diff --git a/plugins/woocommerce/changelog/update-deflag-wc-admin-onboarding b/plugins/woocommerce/changelog/update-deflag-wc-admin-onboarding
new file mode 100644
index 00000000000..1cd3f68fccc
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-wc-admin-onboarding
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep WooCommerce Admin onboarding tasks enabled without legacy feature flags.
diff --git a/plugins/woocommerce/changelog/update-deflag-wc-admin-shell-features b/plugins/woocommerce/changelog/update-deflag-wc-admin-shell-features
new file mode 100644
index 00000000000..0a1d66e8c14
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-deflag-wc-admin-shell-features
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Keep stable WooCommerce Admin shell features enabled without legacy feature flags.
diff --git a/plugins/woocommerce/client/admin/client/abandoned-cart-recovery/abandoned-cart-recovery-recommendations.tsx b/plugins/woocommerce/client/admin/client/abandoned-cart-recovery/abandoned-cart-recovery-recommendations.tsx
index 53a0d45514e..38c9197c900 100644
--- a/plugins/woocommerce/client/admin/client/abandoned-cart-recovery/abandoned-cart-recovery-recommendations.tsx
+++ b/plugins/woocommerce/client/admin/client/abandoned-cart-recovery/abandoned-cart-recovery-recommendations.tsx
@@ -28,8 +28,8 @@ import './abandoned-cart-recovery-recommendations.scss';
*
* Tracks which plugin slugs are currently being set up so item buttons can show
* a busy state and be disabled while any install is in flight. Mirrors the
- * shipping recommendation hook (`shipping-recommendations.tsx#useInstallPlugin`)
- * with a narrower surface — we only need the combined install+activate path.
+ * shipping recommendation utilities, with a narrower surface — we only need
+ * the combined install+activate path here.
*/
export const useInstallPlugin = () => {
const [ pluginsBeingSetup, setPluginsBeingSetup ] = useState<
diff --git a/plugins/woocommerce/client/admin/client/activity-panel/display-options/index.js b/plugins/woocommerce/client/admin/client/activity-panel/display-options/index.js
index 0ca46f338c7..f742c069b68 100644
--- a/plugins/woocommerce/client/admin/client/activity-panel/display-options/index.js
+++ b/plugins/woocommerce/client/admin/client/activity-panel/display-options/index.js
@@ -19,6 +19,7 @@ import { DisplayIcon } from './icons/display';
import { SingleColumnIcon } from './icons/single-column';
import { TwoColumnsIcon } from './icons/two-columns';
import { isTaskListActive } from '../../hooks/use-tasklists-state';
+import { isFeatureEnabled } from '~/utils/features';
const { Fill, Slot } = createSlotFill( 'DisplayOptions' );
@@ -62,7 +63,7 @@ export const DisplayOptions = () => {
useUserPreferences();
const hasTwoColumnContent =
- ! isTaskListActive( 'setup' ) || window.wcAdminFeatures.analytics;
+ ! isTaskListActive( 'setup' ) || isFeatureEnabled( 'analytics' );
return (
<Slot>
diff --git a/plugins/woocommerce/client/admin/client/activity-panel/display-options/test/index.js b/plugins/woocommerce/client/admin/client/activity-panel/display-options/test/index.js
index 11e5690e94b..28b762b5c20 100644
--- a/plugins/woocommerce/client/admin/client/activity-panel/display-options/test/index.js
+++ b/plugins/woocommerce/client/admin/client/activity-panel/display-options/test/index.js
@@ -9,8 +9,16 @@ import { recordEvent } from '@woocommerce/tracks';
* Internal dependencies
*/
import { DisplayOptions } from '../';
+import { isTaskListActive } from '../../../hooks/use-tasklists-state';
+import { isFeatureEnabled } from '~/utils/features';
jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
+jest.mock( '../../../hooks/use-tasklists-state', () => ( {
+ isTaskListActive: jest.fn().mockReturnValue( false ),
+} ) );
+jest.mock( '~/utils/features', () => ( {
+ isFeatureEnabled: jest.fn().mockReturnValue( true ),
+} ) );
jest.mock( '@woocommerce/data', () => ( {
...jest.requireActual( '@woocommerce/data' ),
useUserPreferences: jest
@@ -32,6 +40,15 @@ jest.mock( '@wordpress/data', () => {
} );
describe( 'Activity Panel - Homescreen Display Options', () => {
+ beforeEach( () => {
+ jest.clearAllMocks();
+ isTaskListActive.mockReturnValue( false );
+ isFeatureEnabled.mockReturnValue( true );
+ useUserPreferences.mockReturnValue( {
+ updateUserPreferences: jest.fn(),
+ } );
+ } );
+
it( 'correctly tracks opening the options', () => {
const { getByRole } = render( <DisplayOptions /> );
@@ -69,4 +86,15 @@ describe( 'Activity Panel - Homescreen Display Options', () => {
homepage_layout: 'two_columns',
} );
} );
+
+ it( 'does not render when setup is active and analytics is disabled', () => {
+ isTaskListActive.mockReturnValue( true );
+ isFeatureEnabled.mockReturnValue( false );
+
+ const { queryByRole } = render( <DisplayOptions /> );
+
+ expect(
+ queryByRole( 'button', { name: 'Display options' } )
+ ).toBeNull();
+ } );
} );
diff --git a/plugins/woocommerce/client/admin/client/activity-panel/index.js b/plugins/woocommerce/client/admin/client/activity-panel/index.js
index bc6bfca23ce..c569876345c 100644
--- a/plugins/woocommerce/client/admin/client/activity-panel/index.js
+++ b/plugins/woocommerce/client/admin/client/activity-panel/index.js
@@ -14,10 +14,7 @@ const excludedPages = [ 'wc-settings' ];
const ActivityPanelHeaderItem = () => (
<WooHeaderItem order={ 20 }>
{ ( { isEmbedded, query } ) => {
- if (
- ! window.wcAdminFeatures[ 'activity-panels' ] ||
- excludedPages.includes( query.page )
- ) {
+ if ( excludedPages.includes( query.page ) ) {
return null;
}
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.tsx b/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.tsx
index 1067dee06ae..3dd1fa9bc7f 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.tsx
+++ b/plugins/woocommerce/client/admin/client/analytics/components/report-header/report-header.tsx
@@ -38,9 +38,7 @@ export default function ReportHeader( props: ReportHeaderProps ): JSX.Element {
<div className="woocommerce-analytics-report-header">
{ /* @ts-expect-error - ReportFilters is a valid component but not typed */ }
<ReportFilters { ...props } />
- { !! window.wcAdminFeatures?.[ 'analytics-scheduled-import' ] && (
- <ImportStatusBar />
- ) }
+ <ImportStatusBar />
</div>
);
}
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx
index 9ffbc015338..0248658b266 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx
+++ b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/index.tsx
@@ -19,11 +19,6 @@ export default function ScheduledUpdatesPromotionNotice() {
const { updateUserPreferences, ...userData } = useUserPreferences();
- // Check if feature flag is enabled
- if ( ! window.wcAdminFeatures?.[ 'analytics-scheduled-import' ] ) {
- return null;
- }
-
const optionValue = wcAdminSettings?.[ SCHEDULED_IMPORT_OPTION ];
// No need to show notice if option is already set.
if ( optionValue === 'yes' || optionValue === 'no' ) {
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx
index 35dc77bc347..2c4626ee0fd 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx
+++ b/plugins/woocommerce/client/admin/client/analytics/components/scheduled-updates-promotion-notice/test/index.tsx
@@ -50,11 +50,6 @@ describe( 'ScheduledUpdatesPromotionNotice', () => {
beforeEach( () => {
jest.clearAllMocks();
- // Set up default feature flag
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': true,
- };
-
// Set up default mocks
mockUseSettings.mockReturnValue( {
wcAdminSettings: {},
@@ -71,47 +66,6 @@ describe( 'ScheduledUpdatesPromotionNotice', () => {
);
} );
- describe( 'Feature flag check', () => {
- test( 'should not render when feature flag is disabled', () => {
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': false,
- };
-
- const { container } = render( <ScheduledUpdatesPromotionNotice /> );
-
- expect( container.firstChild ).toBeNull();
- } );
-
- test( 'should not render when feature flag is undefined', () => {
- ( window as any ).wcAdminFeatures = {};
-
- const { container } = render( <ScheduledUpdatesPromotionNotice /> );
-
- expect( container.firstChild ).toBeNull();
- } );
-
- test( 'should render when feature flag is enabled', () => {
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': true,
- };
-
- render( <ScheduledUpdatesPromotionNotice /> );
-
- expect(
- screen.getByText( ( content, element ) => {
- const textContent = element?.textContent || '';
- return (
- element?.tagName.toLowerCase() === 'p' &&
- textContent.includes(
- 'Analytics now supports scheduled updates, providing improved performance. Enable it in'
- ) &&
- textContent.includes( 'Settings' )
- );
- } )
- ).toBeInTheDocument();
- } );
- } );
-
describe( 'Option value check', () => {
test( 'should not render when option is set to "no"', () => {
mockUseSettings.mockReturnValue( {
@@ -326,10 +280,6 @@ describe( 'ScheduledUpdatesPromotionNotice', () => {
describe( 'Combined conditions', () => {
test( 'should render when all conditions are met', () => {
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': true,
- };
-
mockUseSettings.mockReturnValue( {
wcAdminSettings: {},
} as unknown as ReturnType< typeof useSettings > );
@@ -356,31 +306,7 @@ describe( 'ScheduledUpdatesPromotionNotice', () => {
).toBeInTheDocument();
} );
- test( 'should not render when feature flag is disabled even if other conditions are met', () => {
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': false,
- };
-
- mockUseSettings.mockReturnValue( {
- wcAdminSettings: {},
- } as unknown as ReturnType< typeof useSettings > );
-
- mockUseUserPreferences.mockReturnValue( {
- updateUserPreferences: jest.fn(),
- scheduled_updates_promotion_notice_dismissed: undefined,
- isRequesting: false,
- } as unknown as ReturnType< typeof useUserPreferences > );
-
- const { container } = render( <ScheduledUpdatesPromotionNotice /> );
-
- expect( container.firstChild ).toBeNull();
- } );
-
- test( 'should not render when option is set even if feature flag is enabled', () => {
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': true,
- };
-
+ test( 'should not render when option is set', () => {
mockUseSettings.mockReturnValue( {
wcAdminSettings: {
woocommerce_analytics_scheduled_import: 'no',
@@ -398,11 +324,7 @@ describe( 'ScheduledUpdatesPromotionNotice', () => {
expect( container.firstChild ).toBeNull();
} );
- test( 'should not render when dismissed even if feature flag is enabled and option is not set', () => {
- ( window as any ).wcAdminFeatures = {
- 'analytics-scheduled-import': true,
- };
-
+ test( 'should not render when dismissed and option is not set', () => {
mockUseSettings.mockReturnValue( {
wcAdminSettings: {},
} as unknown as ReturnType< typeof useSettings > );
diff --git a/plugins/woocommerce/client/admin/client/analytics/settings/config.js b/plugins/woocommerce/client/admin/client/analytics/settings/config.js
index 1498ab45f41..c2a3d40d349 100644
--- a/plugins/woocommerce/client/admin/client/analytics/settings/config.js
+++ b/plugins/woocommerce/client/admin/client/analytics/settings/config.js
@@ -155,45 +155,42 @@ const baseConfig = {
},
};
-// Add import mode setting if feature is enabled
-if ( !! window.wcAdminFeatures?.[ 'analytics-scheduled-import' ] ) {
- const importInterval = getAdminSetting(
- 'woocommerce_analytics_import_interval',
- __( '12 hours', 'woocommerce' ) // Default value for the import interval.
- );
+const importInterval = getAdminSetting(
+ 'woocommerce_analytics_import_interval',
+ __( '12 hours', 'woocommerce' ) // Default value for the import interval.
+);
- baseConfig[ SCHEDULED_IMPORT_SETTING_NAME ] = {
- name: SCHEDULED_IMPORT_SETTING_NAME,
- label: __( 'Updates:', 'woocommerce' ),
- inputType: 'radio',
- options: [
- {
- label: __( 'Scheduled (recommended)', 'woocommerce' ),
- value: 'yes',
- description: sprintf(
- /* translators: %s: import interval, e.g. "12 hours" */
- __(
- 'Updates automatically every %s. Lowest impact on your site.',
- 'woocommerce'
- ),
- importInterval
- ),
- },
- {
- label: __( 'Immediately', 'woocommerce' ),
- value: 'no',
- description: __(
- 'Updates as soon as new data is available. May slow busy stores.',
+baseConfig[ SCHEDULED_IMPORT_SETTING_NAME ] = {
+ name: SCHEDULED_IMPORT_SETTING_NAME,
+ label: __( 'Updates:', 'woocommerce' ),
+ inputType: 'radio',
+ options: [
+ {
+ label: __( 'Scheduled (recommended)', 'woocommerce' ),
+ value: 'yes',
+ description: sprintf(
+ /* translators: %s: import interval, e.g. "12 hours" */
+ __(
+ 'Updates automatically every %s. Lowest impact on your site.',
'woocommerce'
),
- },
- ],
- // This default value is primarily used when users click "Reset defaults" for settings.
- // We set 'yes' (Scheduled) as the default for new installs, since it is the recommended, lowest-impact option.
- // Note: The PHP backend defaults to 'no' (Immediate) to preserve legacy behavior for existing stores and avoid disrupting current site operations.
- // This intentional difference ensures new stores use the best-practice default, while existing stores are not affected by updates.
- defaultValue: 'yes',
- };
-}
+ importInterval
+ ),
+ },
+ {
+ label: __( 'Immediately', 'woocommerce' ),
+ value: 'no',
+ description: __(
+ 'Updates as soon as new data is available. May slow busy stores.',
+ 'woocommerce'
+ ),
+ },
+ ],
+ // This default value is primarily used when users click "Reset defaults" for settings.
+ // We set 'yes' (Scheduled) as the default for new installs, since it is the recommended, lowest-impact option.
+ // Note: The PHP backend defaults to 'no' (Immediate) to preserve legacy behavior for existing stores and avoid disrupting current site operations.
+ // This intentional difference ensures new stores use the best-practice default, while existing stores are not affected by updates.
+ defaultValue: 'yes',
+};
export const config = applyFilters( SETTINGS_FILTER, baseConfig );
diff --git a/plugins/woocommerce/client/admin/client/analytics/settings/test/index.test.js b/plugins/woocommerce/client/admin/client/analytics/settings/test/index.test.js
index 10d99c083be..4adf541d8fb 100644
--- a/plugins/woocommerce/client/admin/client/analytics/settings/test/index.test.js
+++ b/plugins/woocommerce/client/admin/client/analytics/settings/test/index.test.js
@@ -19,11 +19,6 @@ jest.mock( '@woocommerce/tracks', () => ( {
recordEvent: jest.fn(),
} ) );
-// Enable the feature flag before mocking config.
-window.wcAdminFeatures = {
- 'analytics-scheduled-import': true,
-};
-
jest.mock( '../config', () => ( {
config: {
woocommerce_analytics_scheduled_import: {
@@ -71,17 +66,11 @@ describe( 'Settings - Import Mode Modal', () => {
[ SCHEDULED_IMPORT_SETTING_NAME ]: 'yes',
},
} );
-
- // Mock window.wcAdminFeatures.
- window.wcAdminFeatures = {
- 'analytics-scheduled-import': true,
- };
} );
afterEach( () => {
delete window.wcAdminFeatures;
} );
-
it( 'renders import mode radio control', () => {
render( <Settings createNotice={ jest.fn() } query={ {} } /> );
diff --git a/plugins/woocommerce/client/admin/client/core-profiler/index.tsx b/plugins/woocommerce/client/admin/client/core-profiler/index.tsx
index 84ea06332f5..fb75195a46e 100644
--- a/plugins/woocommerce/client/admin/client/core-profiler/index.tsx
+++ b/plugins/woocommerce/client/admin/client/core-profiler/index.tsx
@@ -325,9 +325,7 @@ const handleGeolocation = assign( {
const redirectToWooHome = raise( { type: 'REDIRECT_TO_WOO_HOME' } );
const exitToWooHome = fromPromise( async () => {
- if ( window.wcAdminFeatures[ 'launch-your-store' ] ) {
- await dispatch( onboardingStore ).coreProfilerCompleted();
- }
+ await dispatch( onboardingStore ).coreProfilerCompleted();
window.location.href = getNewPath( {}, '/', {} );
} );
@@ -1659,13 +1657,9 @@ export const coreProfilerStateMachineDefinition = createMachine( {
sendToJetpackAuthPage: {
invoke: {
src: fromPromise( async () => {
- if (
- window.wcAdminFeatures[ 'launch-your-store' ]
- ) {
- await dispatch(
- onboardingStore
- ).coreProfilerCompleted();
- }
+ await dispatch(
+ onboardingStore
+ ).coreProfilerCompleted();
return await resolveSelect(
onboardingStore
).getJetpackAuthUrl( {
diff --git a/plugins/woocommerce/client/admin/client/guided-tours/shipping-tour.tsx b/plugins/woocommerce/client/admin/client/guided-tours/shipping-tour.tsx
index 8b5a969e207..95df22163c1 100644
--- a/plugins/woocommerce/client/admin/client/guided-tours/shipping-tour.tsx
+++ b/plugins/woocommerce/client/admin/client/guided-tours/shipping-tour.tsx
@@ -70,7 +70,6 @@ const useShowShippingTour = () => {
return {
isLoading,
show:
- window.wcAdminFeatures[ 'shipping-setting-tour' ] &&
! isLoading &&
hasCreatedDefaultShippingZones &&
! hasReviewedDefaultShippingOptions,
diff --git a/plugins/woocommerce/client/admin/client/header/test/index.test.js b/plugins/woocommerce/client/admin/client/header/test/index.test.js
index 22e299fa504..4ca76d76c06 100644
--- a/plugins/woocommerce/client/admin/client/header/test/index.test.js
+++ b/plugins/woocommerce/client/admin/client/header/test/index.test.js
@@ -44,7 +44,6 @@ jest.mock( '@woocommerce/navigation', () => ( {
} ) );
global.window.wcNavigation = {};
-global.window.wcAdminFeatures = { 'activity-panels': false };
const encodedBreadcrumb = [
[ 'admin.php?page=wc-settings', 'Settings' ],
diff --git a/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js b/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js
index 7828a41f3cf..e794dbf9912 100644
--- a/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js
+++ b/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js
@@ -31,6 +31,7 @@ import {
ActivityCardPlaceholder,
} from '~/activity-panel/activity-card';
import { getAdminSetting } from '~/utils/admin-settings';
+import { isFeatureEnabled } from '~/utils/features';
import './style.scss';
function recordOrderEvent( eventName ) {
@@ -93,7 +94,7 @@ function renderOrders( orders, customers, getFormattedOrderTotal ) {
customers.find( ( c ) => c.user_id === customerId ) || {};
let customerUrl = null;
if ( customer && customer.id ) {
- customerUrl = window.wcAdminFeatures.analytics
+ customerUrl = isFeatureEnabled( 'analytics' )
? getNewPath( {}, '/analytics/customers', {
filter: 'single_customer',
customers: customer.id,
@@ -304,7 +305,7 @@ function OrdersPanel( { unreadOrdersCount, orderStatuses } ) {
} );
if ( isError ) {
- if ( ! orderStatuses.length && window.wcAdminFeatures.analytics ) {
+ if ( ! orderStatuses.length && isFeatureEnabled( 'analytics' ) ) {
return (
<EmptyContent
title={ __(
diff --git a/plugins/woocommerce/client/admin/client/homescreen/layout.js b/plugins/woocommerce/client/admin/client/homescreen/layout.js
index 08214da05b5..3ba8a0e8ab2 100644
--- a/plugins/woocommerce/client/admin/client/homescreen/layout.js
+++ b/plugins/woocommerce/client/admin/client/homescreen/layout.js
@@ -44,6 +44,7 @@ import {
useTaskListsState,
} from '~/hooks/use-tasklists-state';
import { hasTwoColumnLayout } from './utils';
+import { isFeatureEnabled } from '~/utils/features';
const TaskLists = lazy( () =>
import( /* webpackChunkName: "tasks" */ '../task-lists' ).then(
@@ -148,7 +149,7 @@ export const Layout = ( {
<InboxPanel />
</Column>
<Column shouldStick={ shouldStickColumns }>
- { window.wcAdminFeatures.analytics && <StatsOverview /> }
+ { isFeatureEnabled( 'analytics' ) && <StatsOverview /> }
{ ! isSetupTaskListActive && <StoreManagementLinks /> }
</Column>
</>
diff --git a/plugins/woocommerce/client/admin/client/homescreen/test/index.js b/plugins/woocommerce/client/admin/client/homescreen/test/index.js
index 98d3fd1d40c..0ed34c9c3a1 100644
--- a/plugins/woocommerce/client/admin/client/homescreen/test/index.js
+++ b/plugins/woocommerce/client/admin/client/homescreen/test/index.js
@@ -8,6 +8,7 @@ import { useUserPreferences } from '@woocommerce/data';
* Internal dependencies
*/
import { Layout } from '../layout';
+import { isFeatureEnabled } from '~/utils/features';
jest.mock( '../stats-overview', () =>
jest.fn().mockReturnValue( <div>[StatsOverview]</div> )
@@ -32,6 +33,10 @@ jest.mock( '@woocommerce/data', () => ( {
useUserPreferences: jest.fn().mockReturnValue( {} ),
} ) );
+jest.mock( '~/utils/features', () => ( {
+ isFeatureEnabled: jest.fn().mockReturnValue( true ),
+} ) );
+
jest.mock( '@wordpress/element', () => {
return {
...jest.requireActual( '@wordpress/element' ),
@@ -42,6 +47,10 @@ jest.mock( '@wordpress/element', () => {
} );
describe( 'Homescreen Layout', () => {
+ beforeEach( () => {
+ isFeatureEnabled.mockReturnValue( true );
+ } );
+
it( 'should show TaskList inline', () => {
const { container } = render(
<Layout
diff --git a/plugins/woocommerce/client/admin/client/homescreen/utils.tsx b/plugins/woocommerce/client/admin/client/homescreen/utils.tsx
index daa44ae4b8e..b239d0b8343 100644
--- a/plugins/woocommerce/client/admin/client/homescreen/utils.tsx
+++ b/plugins/woocommerce/client/admin/client/homescreen/utils.tsx
@@ -1,10 +1,15 @@
+/**
+ * Internal dependencies
+ */
+import { isFeatureEnabled } from '~/utils/features';
+
export const hasTwoColumnLayout = (
userPrefLayout: string,
defaultHomescreenLayout: string,
isSetupTaskListActive: boolean
) => {
const hasTwoColumnContent =
- ! isSetupTaskListActive || window.wcAdminFeatures.analytics;
+ ! isSetupTaskListActive || isFeatureEnabled( 'analytics' );
return (
( userPrefLayout || defaultHomescreenLayout ) === 'two_columns' &&
diff --git a/plugins/woocommerce/client/admin/client/launch-your-store/hooks/use-launch-your-store.tsx b/plugins/woocommerce/client/admin/client/launch-your-store/hooks/use-launch-your-store.tsx
index d151da81864..315cbcf323c 100644
--- a/plugins/woocommerce/client/admin/client/launch-your-store/hooks/use-launch-your-store.tsx
+++ b/plugins/woocommerce/client/admin/client/launch-your-store/hooks/use-launch-your-store.tsx
@@ -56,8 +56,7 @@ export const useLaunchYourStore = (
storePagesOnly: getOption( 'woocommerce_store_pages_only' ),
privateLink: getOption( 'woocommerce_private_link' ),
shareKey: getOption( 'woocommerce_share_key' ),
- launchYourStoreEnabled:
- window.wcAdminFeatures[ 'launch-your-store' ],
+ launchYourStoreEnabled: true,
};
},
[ enabled ]
diff --git a/plugins/woocommerce/client/admin/client/layout/controller.js b/plugins/woocommerce/client/admin/client/layout/controller.js
index 27cfe057534..a76c6de8f1f 100644
--- a/plugins/woocommerce/client/admin/client/layout/controller.js
+++ b/plugins/woocommerce/client/admin/client/layout/controller.js
@@ -25,6 +25,7 @@ import { useReports } from '../analytics/report/use-reports';
import { getAdminSetting } from '~/utils/admin-settings';
import { useFilterHook } from '~/utils/use-filter-hook';
import { NoMatch } from './NoMatch';
+import { isFeatureEnabled } from '~/utils/features';
const AnalyticsReport = lazy( () =>
import( /* webpackChunkName: "analytics-report" */ '../analytics/report' )
@@ -90,7 +91,7 @@ export const getPages = ( reports = [] ) => {
capability: 'manage_woocommerce',
} );
- if ( window.wcAdminFeatures.analytics ) {
+ if ( isFeatureEnabled( 'analytics' ) ) {
pages.push( {
container: Dashboard,
path: '/analytics/overview',
@@ -153,22 +154,20 @@ export const getPages = ( reports = [] ) => {
} );
}
- if ( window.wcAdminFeatures.marketing ) {
- pages.push( {
- container: MarketingOverviewMultichannel,
- path: '/marketing',
- breadcrumbs: [
- ...initialBreadcrumbs,
- [ '/marketing', __( 'Marketing', 'woocommerce' ) ],
- __( 'Overview', 'woocommerce' ),
- ],
- wpOpenMenu: 'toplevel_page_woocommerce-marketing',
- navArgs: {
- id: 'woocommerce-marketing-overview',
- },
- capability: 'view_woocommerce_reports',
- } );
- }
+ pages.push( {
+ container: MarketingOverviewMultichannel,
+ path: '/marketing',
+ breadcrumbs: [
+ ...initialBreadcrumbs,
+ [ '/marketing', __( 'Marketing', 'woocommerce' ) ],
+ __( 'Overview', 'woocommerce' ),
+ ],
+ wpOpenMenu: 'toplevel_page_woocommerce-marketing',
+ navArgs: {
+ id: 'woocommerce-marketing-overview',
+ },
+ capability: 'view_woocommerce_reports',
+ } );
pages.push( {
container: Marketplace,
@@ -187,90 +186,74 @@ export const getPages = ( reports = [] ) => {
},
} );
- if ( window.wcAdminFeatures.onboarding ) {
- pages.push( {
- container: CoreProfiler,
- path: '/setup-wizard',
- breadcrumbs: [
- ...initialBreadcrumbs,
- __( 'Profiler', 'woocommerce' ),
- ],
- capability: 'manage_woocommerce',
- layout: {
- header: false,
- footer: false,
- showNotices: true,
- showStoreAlerts: false,
- showPluginArea: false,
- },
- } );
- }
+ pages.push( {
+ container: CoreProfiler,
+ path: '/setup-wizard',
+ breadcrumbs: [ ...initialBreadcrumbs, __( 'Profiler', 'woocommerce' ) ],
+ capability: 'manage_woocommerce',
+ layout: {
+ header: false,
+ footer: false,
+ showNotices: true,
+ showStoreAlerts: false,
+ showPluginArea: false,
+ },
+ } );
- if ( window.wcAdminFeatures[ 'core-profiler' ] ) {
- pages.push( {
- container: CoreProfiler,
- path: '/profiler',
- breadcrumbs: [
- ...initialBreadcrumbs,
- __( 'Profiler', 'woocommerce' ),
- ],
- capability: 'manage_woocommerce',
- } );
- }
+ pages.push( {
+ container: CoreProfiler,
+ path: '/profiler',
+ breadcrumbs: [ ...initialBreadcrumbs, __( 'Profiler', 'woocommerce' ) ],
+ capability: 'manage_woocommerce',
+ } );
- if ( window.wcAdminFeatures[ 'customize-store' ] ) {
- pages.push( {
- container: CustomizeStore,
- path: '/customize-store/*',
- breadcrumbs: [
- ...initialBreadcrumbs,
- __( 'Customize Your Store', 'woocommerce' ),
- ],
- layout: {
- header: false,
- footer: true,
- showNotices: true,
- showStoreAlerts: false,
- showPluginArea: false,
- },
- capability: 'manage_woocommerce',
- } );
- }
+ pages.push( {
+ container: CustomizeStore,
+ path: '/customize-store/*',
+ breadcrumbs: [
+ ...initialBreadcrumbs,
+ __( 'Customize Your Store', 'woocommerce' ),
+ ],
+ layout: {
+ header: false,
+ footer: true,
+ showNotices: true,
+ showStoreAlerts: false,
+ showPluginArea: false,
+ },
+ capability: 'manage_woocommerce',
+ } );
- if ( window.wcAdminFeatures[ 'launch-your-store' ] ) {
- pages.push( {
- container: LaunchStore,
- path: '/launch-your-store/*',
- breadcrumbs: [
- ...initialBreadcrumbs,
- __( 'Launch Your Store', 'woocommerce' ),
- ],
- layout: {
- header: false,
- footer: true,
- showNotices: true,
- showStoreAlerts: false,
- showPluginArea: false,
- },
- capability: 'manage_woocommerce',
- } );
- }
+ pages.push( {
+ container: LaunchStore,
+ path: '/launch-your-store/*',
+ breadcrumbs: [
+ ...initialBreadcrumbs,
+ __( 'Launch Your Store', 'woocommerce' ),
+ ],
+ layout: {
+ header: false,
+ footer: true,
+ showNotices: true,
+ showStoreAlerts: false,
+ showPluginArea: false,
+ },
+ capability: 'manage_woocommerce',
+ } );
- if ( window.wcAdminFeatures[ 'wc-pay-welcome-page' ] ) {
- pages.push( {
- container: WCPaymentsWelcomePage,
- path: '/wc-pay-welcome-page',
- breadcrumbs: [
- [ '/wc-pay-welcome-page', __( 'WooPayments', 'woocommerce' ) ],
- __( 'WooPayments', 'woocommerce' ),
- ],
- navArgs: {
- id: 'woocommerce-wc-pay-welcome-page',
- },
- wpOpenMenu: 'toplevel_page_woocommerce-wc-pay-welcome-page',
- capability: 'manage_woocommerce',
- } );
- }
+ pages.push( {
+ container: WCPaymentsWelcomePage,
+ path: '/wc-pay-welcome-page',
+ breadcrumbs: [
+ [ '/wc-pay-welcome-page', __( 'WooPayments', 'woocommerce' ) ],
+ __( 'WooPayments', 'woocommerce' ),
+ ],
+ navArgs: {
+ id: 'woocommerce-wc-pay-welcome-page',
+ },
+ wpOpenMenu: 'toplevel_page_woocommerce-wc-pay-welcome-page',
+ capability: 'manage_woocommerce',
+ } );
pages.push( {
container: MobileAppLoginPage,
diff --git a/plugins/woocommerce/client/admin/client/layout/test/controller.test.js b/plugins/woocommerce/client/admin/client/layout/test/controller.test.js
index 945afb67e77..e5a97509099 100644
--- a/plugins/woocommerce/client/admin/client/layout/test/controller.test.js
+++ b/plugins/woocommerce/client/admin/client/layout/test/controller.test.js
@@ -6,7 +6,8 @@ import * as navigation from '@woocommerce/navigation';
/**
* Internal dependencies
*/
-import { updateLinkHref } from '../controller';
+import { getPages, updateLinkHref } from '../controller';
+import { isFeatureEnabled } from '~/utils/features';
jest.mock( '@woocommerce/navigation', () => {
const actual = jest.requireActual( '@woocommerce/navigation' );
@@ -16,6 +17,41 @@ jest.mock( '@woocommerce/navigation', () => {
};
} );
+jest.mock( '~/utils/features', () => ( {
+ isFeatureEnabled: jest.fn().mockReturnValue( true ),
+} ) );
+
+describe( 'getPages', () => {
+ const analyticsPaths = [
+ '/analytics/overview',
+ '/analytics/settings',
+ '/customers',
+ '/analytics/:report',
+ ];
+
+ beforeEach( () => {
+ isFeatureEnabled.mockReturnValue( true );
+ } );
+
+ it( 'registers analytics pages when analytics is enabled', () => {
+ const paths = getPages().map( ( page ) => page.path );
+
+ analyticsPaths.forEach( ( path ) => {
+ expect( paths ).toContain( path );
+ } );
+ } );
+
+ it( 'does not register analytics pages when analytics is disabled', () => {
+ isFeatureEnabled.mockReturnValue( false );
+
+ const paths = getPages().map( ( page ) => page.path );
+
+ analyticsPaths.forEach( ( path ) => {
+ expect( paths ).not.toContain( path );
+ } );
+ } );
+} );
+
describe( 'updateLinkHref', () => {
const timeExcludedScreens = [ 'stock', 'settings', 'customers' ];
diff --git a/plugins/woocommerce/client/admin/client/payments/payment-recommendations.tsx b/plugins/woocommerce/client/admin/client/payments/payment-recommendations.tsx
index 8eacc8134c2..c22d58777b4 100644
--- a/plugins/woocommerce/client/admin/client/payments/payment-recommendations.tsx
+++ b/plugins/woocommerce/client/admin/client/payments/payment-recommendations.tsx
@@ -166,8 +166,7 @@ const PaymentRecommendations = () => {
return (
! installedPaymentGateways[ plugin.id ] &&
plugin.plugins?.length &&
- ( ! window.wcAdminFeatures[ 'wc-pay-promotion' ] ||
- ! plugin.id.startsWith( 'woocommerce_payments' ) )
+ ! plugin.id.startsWith( 'woocommerce_payments' )
);
} )
.map( ( plugin: Plugin ) => {
diff --git a/plugins/woocommerce/client/admin/client/shared.tsx b/plugins/woocommerce/client/admin/client/shared.tsx
index 9013eb0b64c..89bad225c90 100644
--- a/plugins/woocommerce/client/admin/client/shared.tsx
+++ b/plugins/woocommerce/client/admin/client/shared.tsx
@@ -12,14 +12,6 @@ import debugFactory from 'debug';
const debug = debugFactory( 'wc-admin:client' );
export const renderCustomerEffortScoreTracks = ( root: HTMLElement ) => {
- // Render the CustomerEffortScoreTracksContainer only if the feature flag is enabled.
- if (
- ! window.wcAdminFeatures ||
- window.wcAdminFeatures[ 'customer-effort-score-tracks' ] !== true
- ) {
- return;
- }
-
if ( ! root ) {
debug( 'Customer Effort Score Tracks root not found' );
return;
diff --git a/plugins/woocommerce/client/admin/client/shipping/experimental-shipping-recommendations.tsx b/plugins/woocommerce/client/admin/client/shipping/experimental-shipping-recommendations.tsx
deleted file mode 100644
index 465fddbcefd..00000000000
--- a/plugins/woocommerce/client/admin/client/shipping/experimental-shipping-recommendations.tsx
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * External dependencies
- */
-import { useSelect } from '@wordpress/data';
-import { useEffect, useRef } from '@wordpress/element';
-import {
- pluginsStore,
- settingsStore,
- onboardingStore,
-} from '@woocommerce/data';
-import { recordEvent } from '@woocommerce/tracks';
-
-/**
- * Internal dependencies
- */
-import { getCountryCode } from '~/dashboard/utils';
-import WooCommerceShippingItem from './experimental-woocommerce-shipping-item';
-import ShipStationItem from './shipstation-item';
-import PacklinkItem from './packlink-item';
-import {
- ShippingRecommendationsList,
- useInstallPlugin,
-} from './shipping-recommendations';
-import './shipping-recommendations.scss';
-import { ShippingTour } from '../guided-tours/shipping-tour';
-
-type ExtensionId = 'woocommerce-shipping' | 'shipstation' | 'packlink';
-
-const COUNTRY_EXTENSIONS_MAP: Record< string, ExtensionId[] > = {
- US: [ 'woocommerce-shipping', 'shipstation' ],
- CA: [ 'shipstation' ],
- FR: [ 'packlink' ],
- ES: [ 'packlink' ],
- IT: [ 'packlink' ],
- DE: [ 'packlink' ],
- GB: [ 'shipstation' ],
- NL: [ 'packlink' ],
- AT: [ 'packlink' ],
- BE: [ 'packlink' ],
- AU: [ 'shipstation' ],
- NZ: [ 'shipstation' ],
- IE: [ 'packlink' ],
- PT: [ 'packlink' ],
-};
-
-const EXTENSION_PLUGIN_SLUGS: Record< ExtensionId, string > = {
- 'woocommerce-shipping': 'woocommerce-shipping',
- shipstation: 'woocommerce-shipstation-integration',
- packlink: 'packlink-pro-shipping',
-};
-
-const ShippingRecommendations = () => {
- const [ pluginsBeingSetup, , handleInstall, handleActivate ] =
- useInstallPlugin();
-
- const {
- installedPlugins,
- activePlugins,
- countryCode,
- isSellingDigitalProductsOnly,
- } = useSelect( ( select ) => {
- const settings = select( settingsStore ).getSettings( 'general' );
-
- const { getInstalledPlugins, getActivePlugins } =
- select( pluginsStore );
-
- const profileItems =
- select( onboardingStore ).getProfileItems()?.product_types;
-
- return {
- installedPlugins: getInstalledPlugins(),
- activePlugins: getActivePlugins(),
- countryCode: getCountryCode(
- settings.general?.woocommerce_default_country
- ),
- isSellingDigitalProductsOnly:
- profileItems?.length === 1 && profileItems[ 0 ] === 'downloads',
- };
- }, [] );
-
- const normalizedCountry = countryCode ?? '';
-
- const extensionsForCountry =
- COUNTRY_EXTENSIONS_MAP[ normalizedCountry ] ?? [];
-
- // Render every country-mapped recommendation regardless of which partner
- // is already installed: the settings page is meant to surface alternatives
- // the merchant can evaluate and switch to. The onboarding wizard keeps a
- // narrower selection because installing every option there at once is not
- // desired during initial setup.
- const visibleExtensions = isSellingDigitalProductsOnly
- ? []
- : extensionsForCountry;
-
- const visiblePluginSlugs = visibleExtensions
- .map( ( ext ) => EXTENSION_PLUGIN_SLUGS[ ext ] )
- .join( ',' );
-
- const impressionFired = useRef( false );
- useEffect( () => {
- if ( visibleExtensions.length > 0 && ! impressionFired.current ) {
- recordEvent( 'shipping_partner_impression', {
- context: 'settings',
- country: normalizedCountry,
- plugins: visiblePluginSlugs,
- } );
- impressionFired.current = true;
- }
- }, [ visibleExtensions.length, normalizedCountry, visiblePluginSlugs ] );
-
- if ( isSellingDigitalProductsOnly ) {
- return <ShippingTour showShippingRecommendationsStep={ false } />;
- }
-
- if ( visibleExtensions.length === 0 ) {
- return <ShippingTour showShippingRecommendationsStep={ false } />;
- }
-
- return (
- <div style={ { paddingBottom: 60 } }>
- <ShippingTour showShippingRecommendationsStep={ true } />
- <ShippingRecommendationsList>
- { visibleExtensions.map( ( ext ) => {
- const isPluginInstalled = installedPlugins.includes(
- EXTENSION_PLUGIN_SLUGS[ ext ]
- );
- const isPluginActive = activePlugins.includes(
- EXTENSION_PLUGIN_SLUGS[ ext ]
- );
- const trackingProps = {
- context: 'settings' as const,
- country: normalizedCountry,
- plugins: visiblePluginSlugs,
- };
- switch ( ext ) {
- case 'woocommerce-shipping':
- return (
- <WooCommerceShippingItem
- key={ ext }
- isPluginInstalled={ isPluginInstalled }
- isPluginActive={ isPluginActive }
- pluginsBeingSetup={ pluginsBeingSetup }
- onInstallClick={ handleInstall }
- onActivateClick={ handleActivate }
- tracking={ trackingProps }
- />
- );
- case 'shipstation':
- return (
- <ShipStationItem
- key={ ext }
- isPluginInstalled={ isPluginInstalled }
- isPluginActive={ isPluginActive }
- pluginsBeingSetup={ pluginsBeingSetup }
- onInstallClick={ handleInstall }
- onActivateClick={ handleActivate }
- tracking={ trackingProps }
- />
- );
- case 'packlink':
- return (
- <PacklinkItem
- key={ ext }
- isPluginInstalled={ isPluginInstalled }
- isPluginActive={ isPluginActive }
- pluginsBeingSetup={ pluginsBeingSetup }
- onInstallClick={ handleInstall }
- onActivateClick={ handleActivate }
- tracking={ trackingProps }
- />
- );
- default:
- return null;
- }
- } ) }
- </ShippingRecommendationsList>
- </div>
- );
-};
-
-export default ShippingRecommendations;
diff --git a/plugins/woocommerce/client/admin/client/shipping/experimental-woocommerce-shipping-item.tsx b/plugins/woocommerce/client/admin/client/shipping/experimental-woocommerce-shipping-item.tsx
deleted file mode 100644
index 3606d8e9930..00000000000
--- a/plugins/woocommerce/client/admin/client/shipping/experimental-woocommerce-shipping-item.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * External dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { Button, ExternalLink } from '@wordpress/components';
-import { Pill } from '@woocommerce/components';
-import { recordEvent } from '@woocommerce/tracks';
-
-/**
- * Internal dependencies
- */
-import './woocommerce-shipping-item.scss';
-import WooIcon from './woo-icon.svg';
-
-const WOOCOMMERCE_SHIPPING_PLUGIN_SLUG = 'woocommerce-shipping';
-
-export type ShippingPartnerTrackingProps = {
- context: 'settings';
- country: string;
- plugins: string;
-};
-
-const WooCommerceShippingItem = ( {
- isPluginInstalled,
- isPluginActive,
- onInstallClick,
- onActivateClick,
- pluginsBeingSetup,
- tracking,
-}: {
- isPluginInstalled: boolean;
- isPluginActive: boolean;
- pluginsBeingSetup: Array< string >;
- onInstallClick: ( slugs: string[] ) => PromiseLike< void >;
- onActivateClick: ( slugs: string[] ) => PromiseLike< void >;
- tracking?: ShippingPartnerTrackingProps;
-} ) => {
- const { createSuccessNotice } = useDispatch( 'core/notices' );
-
- const handleClick = () => {
- const trackingBase = {
- ...( tracking ?? {} ),
- selected_plugin: WOOCOMMERCE_SHIPPING_PLUGIN_SLUG,
- };
-
- recordEvent( 'shipping_partner_click', trackingBase );
- recordEvent( 'settings_shipping_recommendation_setup_click', {
- plugin: WOOCOMMERCE_SHIPPING_PLUGIN_SLUG,
- action: isPluginInstalled ? 'activate' : 'install',
- } );
-
- const action = isPluginInstalled ? onActivateClick : onInstallClick;
- const eventName = isPluginInstalled
- ? 'shipping_partner_activate'
- : 'shipping_partner_install';
-
- action( [ WOOCOMMERCE_SHIPPING_PLUGIN_SLUG ] ).then(
- () => {
- recordEvent( eventName, {
- ...trackingBase,
- success: true,
- } );
- createSuccessNotice(
- isPluginInstalled
- ? __( 'WooCommerce Shipping activated!', 'woocommerce' )
- : __(
- 'WooCommerce Shipping is installed!',
- 'woocommerce'
- ),
- {}
- );
- },
- () => {
- recordEvent( eventName, {
- ...trackingBase,
- success: false,
- } );
- }
- );
- };
-
- return (
- <div className="woocommerce-list__item-inner woocommerce-shipping-plugin-item">
- <div className="woocommerce-list__item-before">
- <img
- className="woocommerce-shipping-plugin-item__logo"
- src={ WooIcon }
- alt="WooCommerce Shipping Logo"
- />
- </div>
- <div className="woocommerce-list__item-text">
- <span className="woocommerce-list__item-title">
- { __( 'WooCommerce Shipping', 'woocommerce' ) }
- <Pill>{ __( 'Recommended', 'woocommerce' ) }</Pill>
- </span>
- <span className="woocommerce-list__item-content">
- { __(
- 'Print USPS, UPS, and DHL Express labels straight from your WooCommerce dashboard and save on shipping.',
- 'woocommerce'
- ) }
- <br />
- <ExternalLink href="https://woocommerce.com/woocommerce-shipping/">
- { __( 'Learn more', 'woocommerce' ) }
- </ExternalLink>
- </span>
- </div>
- <div className="woocommerce-list__item-after">
- { isPluginActive ? (
- <Button
- variant="secondary"
- aria-disabled="true"
- aria-label={ __(
- 'WooCommerce Shipping is already active',
- 'woocommerce'
- ) }
- >
- { __( 'Active', 'woocommerce' ) }
- </Button>
- ) : (
- <Button
- variant={ isPluginInstalled ? 'primary' : 'secondary' }
- onClick={ handleClick }
- isBusy={ pluginsBeingSetup.includes(
- WOOCOMMERCE_SHIPPING_PLUGIN_SLUG
- ) }
- disabled={ pluginsBeingSetup.length > 0 }
- >
- { isPluginInstalled
- ? __( 'Activate', 'woocommerce' )
- : __( 'Install', 'woocommerce' ) }
- </Button>
- ) }
- </div>
- </div>
- );
-};
-
-export default WooCommerceShippingItem;
diff --git a/plugins/woocommerce/client/admin/client/shipping/packlink-item.tsx b/plugins/woocommerce/client/admin/client/shipping/packlink-item.tsx
index a704032a813..5b08dbc0884 100644
--- a/plugins/woocommerce/client/admin/client/shipping/packlink-item.tsx
+++ b/plugins/woocommerce/client/admin/client/shipping/packlink-item.tsx
@@ -10,7 +10,7 @@ import { recordEvent } from '@woocommerce/tracks';
* Internal dependencies
*/
import './woocommerce-shipping-item.scss';
-import type { ShippingPartnerTrackingProps } from './experimental-woocommerce-shipping-item';
+import type { ShippingPartnerTrackingProps } from './woocommerce-shipping-item';
const PACKLINK_PLUGIN_SLUG = 'packlink-pro-shipping';
diff --git a/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-utils.tsx b/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-utils.tsx
new file mode 100644
index 00000000000..c1a7ab75b05
--- /dev/null
+++ b/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-utils.tsx
@@ -0,0 +1,123 @@
+/**
+ * External dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { useState, Children } from '@wordpress/element';
+import { Text } from '@woocommerce/experimental';
+import { PluginNames, pluginsStore } from '@woocommerce/data';
+import { getAdminLink } from '@woocommerce/settings';
+import { CardFooter } from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import { createNoticesFromResponse } from '../lib/notices';
+import {
+ DismissableList,
+ DismissableListHeading,
+} from '../settings-recommendations/dismissable-list';
+import { TrackedLink } from '~/components/tracked-link/tracked-link';
+import { useOptionDismiss } from '~/hooks/use-option-dismiss';
+
+export const useInstallPlugin = () => {
+ const [ pluginsBeingSetup, setPluginsBeingSetup ] = useState<
+ Array< string >
+ >( [] );
+
+ const { installPlugins, activatePlugins } = useDispatch( pluginsStore );
+
+ const handleInstall = ( slugs: string[] ): PromiseLike< void > => {
+ if ( pluginsBeingSetup.length > 0 ) {
+ return Promise.resolve();
+ }
+
+ setPluginsBeingSetup( slugs );
+
+ return installPlugins( slugs as Partial< PluginNames >[] )
+ .then( () => {
+ setPluginsBeingSetup( [] );
+ } )
+ .catch( ( response: { errors: Record< string, string > } ) => {
+ createNoticesFromResponse( response );
+ setPluginsBeingSetup( [] );
+
+ return Promise.reject();
+ } );
+ };
+
+ const handleActivate = ( slugs: string[] ): PromiseLike< void > => {
+ if ( pluginsBeingSetup.length > 0 ) {
+ return Promise.resolve();
+ }
+
+ setPluginsBeingSetup( slugs );
+
+ return activatePlugins( slugs as Partial< PluginNames >[] )
+ .then( () => {
+ setPluginsBeingSetup( [] );
+ } )
+ .catch( ( response: { errors: Record< string, string > } ) => {
+ createNoticesFromResponse( response );
+ setPluginsBeingSetup( [] );
+
+ return Promise.reject();
+ } );
+ };
+
+ return [ pluginsBeingSetup, handleInstall, handleActivate ] as const;
+};
+
+export const ShippingRecommendationsList = ( {
+ children,
+}: {
+ children: React.ReactNode;
+} ) => {
+ const { isDismissed, onDismiss } = useOptionDismiss(
+ 'woocommerce_settings_shipping_recommendations_hidden'
+ );
+
+ return (
+ <DismissableList
+ className="woocommerce-recommended-shipping-extensions"
+ isDismissed={ isDismissed }
+ >
+ <DismissableListHeading onDismiss={ onDismiss }>
+ <Text variant="title.small" as="p" size="20" lineHeight="28px">
+ { __( 'Recommended shipping solutions', 'woocommerce' ) }
+ </Text>
+ <Text
+ className="woocommerce-recommended-shipping__header-heading"
+ variant="caption"
+ as="p"
+ size="12"
+ lineHeight="16px"
+ >
+ { __(
+ 'We recommend adding one of the following shipping extensions to your store.',
+ 'woocommerce'
+ ) }
+ </Text>
+ </DismissableListHeading>
+ <ul className="woocommerce-list">
+ { Children.map( children, ( item ) => (
+ <li className="woocommerce-list__item">{ item }</li>
+ ) ) }
+ </ul>
+ <CardFooter>
+ <TrackedLink
+ message={ __(
+ // translators: {{Link}} is a placeholder for a html element.
+ 'Visit {{Link}}the WooCommerce Marketplace{{/Link}} to find more shipping, delivery, and fulfillment solutions.',
+ 'woocommerce'
+ ) }
+ targetUrl={ getAdminLink(
+ 'admin.php?page=wc-admin&tab=extensions&path=/extensions&category=shipping-delivery-and-fulfillment'
+ ) }
+ linkType="wc-admin"
+ eventName="settings_shipping_recommendation_visit_marketplace_click"
+ />
+ </CardFooter>
+ </DismissableList>
+ );
+};
diff --git a/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-wrapper.tsx b/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-wrapper.tsx
index 3eaca7674c6..228ee995ca0 100644
--- a/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-wrapper.tsx
+++ b/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations-wrapper.tsx
@@ -10,12 +10,6 @@ import { EmbeddedBodyProps } from '../embedded-body-layout/embedded-body-props';
import RecommendationsEligibilityWrapper from '../settings-recommendations/recommendations-eligibility-wrapper';
const ShippingRecommendationsLoader = lazy( () => {
- if ( window.wcAdminFeatures[ 'shipping-smart-defaults' ] ) {
- return import(
- /* webpackChunkName: "shipping-recommendations" */ './experimental-shipping-recommendations'
- );
- }
-
return import(
/* webpackChunkName: "shipping-recommendations" */ './shipping-recommendations'
);
diff --git a/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations.tsx b/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations.tsx
index 9900ada1d6b..abc40fbedc3 100644
--- a/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations.tsx
+++ b/plugins/woocommerce/client/admin/client/shipping/shipping-recommendations.tsx
@@ -1,173 +1,180 @@
/**
* External dependencies
*/
-import { __ } from '@wordpress/i18n';
-import { useSelect, useDispatch } from '@wordpress/data';
-import { useState, Children } from '@wordpress/element';
-import { Text } from '@woocommerce/experimental';
-import { PluginNames, pluginsStore } from '@woocommerce/data';
-import { getAdminLink } from '@woocommerce/settings';
-import { CardFooter } from '@wordpress/components';
+import { useSelect } from '@wordpress/data';
+import { useEffect, useRef } from '@wordpress/element';
+import {
+ pluginsStore,
+ settingsStore,
+ onboardingStore,
+} from '@woocommerce/data';
+import { recordEvent } from '@woocommerce/tracks';
/**
* Internal dependencies
*/
-import { createNoticesFromResponse } from '../lib/notices';
+import { getCountryCode } from '~/dashboard/utils';
+import WooCommerceShippingItem from './woocommerce-shipping-item';
+import ShipStationItem from './shipstation-item';
+import PacklinkItem from './packlink-item';
import {
- DismissableList,
- DismissableListHeading,
-} from '../settings-recommendations/dismissable-list';
-import WoocommerceShippingItem from './woocommerce-shipping-item';
+ ShippingRecommendationsList,
+ useInstallPlugin,
+} from './shipping-recommendations-utils';
import './shipping-recommendations.scss';
-import { TrackedLink } from '~/components/tracked-link/tracked-link';
-import { useOptionDismiss } from '~/hooks/use-option-dismiss';
-
-export const useInstallPlugin = () => {
- const [ pluginsBeingSetup, setPluginsBeingSetup ] = useState<
- Array< string >
- >( [] );
-
- const { installAndActivatePlugins, installPlugins, activatePlugins } =
- useDispatch( pluginsStore );
-
- const handleSetup = ( slugs: string[] ): PromiseLike< void > => {
- if ( pluginsBeingSetup.length > 0 ) {
- return Promise.resolve();
- }
-
- setPluginsBeingSetup( slugs );
-
- return installAndActivatePlugins( slugs )
- .then( () => {
- setPluginsBeingSetup( [] );
- } )
- .catch( ( response: { errors: Record< string, string > } ) => {
- createNoticesFromResponse( response );
- setPluginsBeingSetup( [] );
-
- return Promise.reject();
- } );
- };
-
- const handleInstall = ( slugs: string[] ): PromiseLike< void > => {
- if ( pluginsBeingSetup.length > 0 ) {
- return Promise.resolve();
- }
-
- setPluginsBeingSetup( slugs );
-
- return installPlugins( slugs as Partial< PluginNames >[] )
- .then( () => {
- setPluginsBeingSetup( [] );
- } )
- .catch( ( response: { errors: Record< string, string > } ) => {
- createNoticesFromResponse( response );
- setPluginsBeingSetup( [] );
-
- return Promise.reject();
- } );
- };
-
- const handleActivate = ( slugs: string[] ): PromiseLike< void > => {
- if ( pluginsBeingSetup.length > 0 ) {
- return Promise.resolve();
- }
-
- setPluginsBeingSetup( slugs );
-
- return activatePlugins( slugs as Partial< PluginNames >[] )
- .then( () => {
- setPluginsBeingSetup( [] );
- } )
- .catch( ( response: { errors: Record< string, string > } ) => {
- createNoticesFromResponse( response );
- setPluginsBeingSetup( [] );
-
- return Promise.reject();
- } );
- };
-
- return [
- pluginsBeingSetup,
- handleSetup,
- handleInstall,
- handleActivate,
- ] as const;
+import { ShippingTour } from '~/guided-tours/shipping-tour';
+
+type ExtensionId = 'woocommerce-shipping' | 'shipstation' | 'packlink';
+
+const COUNTRY_EXTENSIONS_MAP: Record< string, ExtensionId[] > = {
+ US: [ 'woocommerce-shipping', 'shipstation' ],
+ CA: [ 'shipstation' ],
+ FR: [ 'packlink' ],
+ ES: [ 'packlink' ],
+ IT: [ 'packlink' ],
+ DE: [ 'packlink' ],
+ GB: [ 'shipstation' ],
+ NL: [ 'packlink' ],
+ AT: [ 'packlink' ],
+ BE: [ 'packlink' ],
+ AU: [ 'shipstation' ],
+ NZ: [ 'shipstation' ],
+ IE: [ 'packlink' ],
+ PT: [ 'packlink' ],
};
-export const ShippingRecommendationsList = ( {
- children,
-}: {
- children: React.ReactNode;
-} ) => {
- const { isDismissed, onDismiss } = useOptionDismiss(
- 'woocommerce_settings_shipping_recommendations_hidden'
- );
-
- return (
- <DismissableList
- className="woocommerce-recommended-shipping-extensions"
- isDismissed={ isDismissed }
- >
- <DismissableListHeading onDismiss={ onDismiss }>
- <Text variant="title.small" as="p" size="20" lineHeight="28px">
- { __( 'Recommended shipping solutions', 'woocommerce' ) }
- </Text>
- <Text
- className="woocommerce-recommended-shipping__header-heading"
- variant="caption"
- as="p"
- size="12"
- lineHeight="16px"
- >
- { __(
- 'We recommend adding one of the following shipping extensions to your store.',
- 'woocommerce'
- ) }
- </Text>
- </DismissableListHeading>
- <ul className="woocommerce-list">
- { Children.map( children, ( item ) => (
- <li className="woocommerce-list__item">{ item }</li>
- ) ) }
- </ul>
- <CardFooter>
- <TrackedLink
- message={ __(
- // translators: {{Link}} is a placeholder for a html element.
- 'Visit {{Link}}the WooCommerce Marketplace{{/Link}} to find more shipping, delivery, and fulfillment solutions.',
- 'woocommerce'
- ) }
- targetUrl={ getAdminLink(
- 'admin.php?page=wc-admin&tab=extensions&path=/extensions&category=shipping-delivery-and-fulfillment'
- ) }
- linkType="wc-admin"
- eventName="settings_shipping_recommendation_visit_marketplace_click"
- />
- </CardFooter>
- </DismissableList>
- );
+const EXTENSION_PLUGIN_SLUGS: Record< ExtensionId, string > = {
+ 'woocommerce-shipping': 'woocommerce-shipping',
+ shipstation: 'woocommerce-shipstation-integration',
+ packlink: 'packlink-pro-shipping',
};
const ShippingRecommendations = () => {
- const [ pluginsBeingSetup, setupPlugin ] = useInstallPlugin();
+ const [ pluginsBeingSetup, handleInstall, handleActivate ] =
+ useInstallPlugin();
+
+ const {
+ installedPlugins,
+ activePlugins,
+ countryCode,
+ isSellingDigitalProductsOnly,
+ } = useSelect( ( select ) => {
+ const settings = select( settingsStore ).getSettings( 'general' );
+
+ const { getInstalledPlugins, getActivePlugins } =
+ select( pluginsStore );
+
+ const profileItems =
+ select( onboardingStore ).getProfileItems()?.product_types;
+
+ return {
+ installedPlugins: getInstalledPlugins(),
+ activePlugins: getActivePlugins(),
+ countryCode: getCountryCode(
+ settings.general?.woocommerce_default_country
+ ),
+ isSellingDigitalProductsOnly:
+ profileItems?.length === 1 && profileItems[ 0 ] === 'downloads',
+ };
+ }, [] );
+
+ const normalizedCountry = countryCode ?? '';
+
+ const extensionsForCountry =
+ COUNTRY_EXTENSIONS_MAP[ normalizedCountry ] ?? [];
+
+ // Render every country-mapped recommendation regardless of which partner
+ // is already installed: the settings page is meant to surface alternatives
+ // the merchant can evaluate and switch to. The onboarding wizard keeps a
+ // narrower selection because installing every option there at once is not
+ // desired during initial setup.
+ const visibleExtensions = isSellingDigitalProductsOnly
+ ? []
+ : extensionsForCountry;
+
+ const visiblePluginSlugs = visibleExtensions
+ .map( ( ext ) => EXTENSION_PLUGIN_SLUGS[ ext ] )
+ .join( ',' );
+
+ const impressionFired = useRef( false );
+ useEffect( () => {
+ if ( visibleExtensions.length > 0 && ! impressionFired.current ) {
+ recordEvent( 'shipping_partner_impression', {
+ context: 'settings',
+ country: normalizedCountry,
+ plugins: visiblePluginSlugs,
+ } );
+ impressionFired.current = true;
+ }
+ }, [ visibleExtensions.length, normalizedCountry, visiblePluginSlugs ] );
- const activePlugins = useSelect(
- ( select ) => select( pluginsStore ).getActivePlugins(),
- []
- );
+ if ( isSellingDigitalProductsOnly ) {
+ return <ShippingTour showShippingRecommendationsStep={ false } />;
+ }
- if ( activePlugins.includes( 'woocommerce-shipping' ) ) {
- return null;
+ if ( visibleExtensions.length === 0 ) {
+ return <ShippingTour showShippingRecommendationsStep={ false } />;
}
return (
- <ShippingRecommendationsList>
- <WoocommerceShippingItem
- pluginsBeingSetup={ pluginsBeingSetup }
- onSetupClick={ setupPlugin }
- />
- </ShippingRecommendationsList>
+ <div style={ { paddingBottom: 60 } }>
+ <ShippingTour showShippingRecommendationsStep={ true } />
+ <ShippingRecommendationsList>
+ { visibleExtensions.map( ( ext ) => {
+ const isPluginInstalled = installedPlugins.includes(
+ EXTENSION_PLUGIN_SLUGS[ ext ]
+ );
+ const isPluginActive = activePlugins.includes(
+ EXTENSION_PLUGIN_SLUGS[ ext ]
+ );
+ const trackingProps = {
+ context: 'settings' as const,
+ country: normalizedCountry,
+ plugins: visiblePluginSlugs,
+ };
+ switch ( ext ) {
+ case 'woocommerce-shipping':
+ return (
+ <WooCommerceShippingItem
+ key={ ext }
+ isPluginInstalled={ isPluginInstalled }
+ isPluginActive={ isPluginActive }
+ pluginsBeingSetup={ pluginsBeingSetup }
+ onInstallClick={ handleInstall }
+ onActivateClick={ handleActivate }
+ tracking={ trackingProps }
+ />
+ );
+ case 'shipstation':
+ return (
+ <ShipStationItem
+ key={ ext }
+ isPluginInstalled={ isPluginInstalled }
+ isPluginActive={ isPluginActive }
+ pluginsBeingSetup={ pluginsBeingSetup }
+ onInstallClick={ handleInstall }
+ onActivateClick={ handleActivate }
+ tracking={ trackingProps }
+ />
+ );
+ case 'packlink':
+ return (
+ <PacklinkItem
+ key={ ext }
+ isPluginInstalled={ isPluginInstalled }
+ isPluginActive={ isPluginActive }
+ pluginsBeingSetup={ pluginsBeingSetup }
+ onInstallClick={ handleInstall }
+ onActivateClick={ handleActivate }
+ tracking={ trackingProps }
+ />
+ );
+ default:
+ return null;
+ }
+ } ) }
+ </ShippingRecommendationsList>
+ </div>
);
};
diff --git a/plugins/woocommerce/client/admin/client/shipping/shipstation-item.tsx b/plugins/woocommerce/client/admin/client/shipping/shipstation-item.tsx
index 85b93a8e734..d279ac7bce1 100644
--- a/plugins/woocommerce/client/admin/client/shipping/shipstation-item.tsx
+++ b/plugins/woocommerce/client/admin/client/shipping/shipstation-item.tsx
@@ -10,7 +10,7 @@ import { recordEvent } from '@woocommerce/tracks';
* Internal dependencies
*/
import './woocommerce-shipping-item.scss';
-import type { ShippingPartnerTrackingProps } from './experimental-woocommerce-shipping-item';
+import type { ShippingPartnerTrackingProps } from './woocommerce-shipping-item';
const SHIPSTATION_PLUGIN_SLUG = 'woocommerce-shipstation-integration';
diff --git a/plugins/woocommerce/client/admin/client/shipping/test/experimental-shipping-recommendations.tsx b/plugins/woocommerce/client/admin/client/shipping/test/experimental-shipping-recommendations.tsx
deleted file mode 100644
index db8693c4b02..00000000000
--- a/plugins/woocommerce/client/admin/client/shipping/test/experimental-shipping-recommendations.tsx
+++ /dev/null
@@ -1,832 +0,0 @@
-/**
- * External dependencies
- */
-import { render, screen, fireEvent, waitFor } from '@testing-library/react';
-import { useSelect, useDispatch } from '@wordpress/data';
-import { recordEvent } from '@woocommerce/tracks';
-import userEvent from '@testing-library/user-event';
-
-/**
- * Internal dependencies
- */
-import ShippingRecommendations from '../experimental-shipping-recommendations';
-
-jest.mock( '@wordpress/data', () => ( {
- ...jest.requireActual( '@wordpress/data' ),
- useSelect: jest.fn(),
- useDispatch: jest.fn(),
-} ) );
-jest.mock( '../../settings-recommendations/dismissable-list', () => ( {
- DismissableList: ( ( { children } ) => children ) as React.FC,
- DismissableListHeading: ( ( { children } ) => children ) as React.FC,
-} ) );
-jest.mock( '../../lib/notices', () => ( {
- createNoticesFromResponse: () => null,
-} ) );
-jest.mock( '@woocommerce/admin-layout', () => {
- const mockContext = {
- layoutPath: [ 'home' ],
- layoutString: 'home',
- extendLayout: () => {},
- isDescendantOf: () => false,
- };
- return {
- ...jest.requireActual( '@woocommerce/admin-layout' ),
- useLayoutContext: jest.fn().mockReturnValue( mockContext ),
- useExtendLayout: jest.fn().mockReturnValue( mockContext ),
- };
-} );
-jest.mock( '@woocommerce/tracks', () => ( {
- recordEvent: jest.fn(),
-} ) );
-jest.mock( '~/utils/features', () => ( {
- isFeatureEnabled: jest.fn(),
-} ) );
-
-const defaultSelectReturn = {
- getActivePlugins: () => [],
- getInstalledPlugins: () => [],
- getSettings: () => ( {
- general: {
- woocommerce_default_country: 'US',
- },
- } ),
- getProfileItems: () => ( {} ),
- hasFinishedResolution: jest.fn(),
- getOption: jest.fn(),
-};
-
-const mockSelectForCountry = (
- countryCode: string,
- activePlugins: string[] = [],
- overrides: Record< string, unknown > = {}
-) => {
- ( useSelect as jest.Mock ).mockImplementation( ( fn ) =>
- fn( () => ( {
- ...defaultSelectReturn,
- getActivePlugins: () => activePlugins,
- getSettings: () => ( {
- general: {
- woocommerce_default_country: countryCode,
- },
- } ),
- ...overrides,
- } ) )
- );
-};
-
-describe( 'ShippingRecommendations', () => {
- beforeEach( () => {
- ( useSelect as jest.Mock ).mockImplementation( ( fn ) =>
- fn( () => ( { ...defaultSelectReturn } ) )
- );
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: () => Promise.resolve(),
- installPlugins: () => Promise.resolve(),
- activatePlugins: () => Promise.resolve(),
- createSuccessNotice: () => null,
- } );
- } );
-
- describe( 'country-based filtering', () => {
- it( 'should show WooCommerce Shipping and ShipStation for US', () => {
- mockSelectForCountry( 'US' );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- expect(
- screen.queryByText( 'Packlink PRO' )
- ).not.toBeInTheDocument();
- } );
-
- it( 'should show only ShipStation for CA', () => {
- mockSelectForCountry( 'CA' );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).not.toBeInTheDocument();
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- } );
-
- it( 'should show only Packlink PRO for FR', () => {
- mockSelectForCountry( 'FR' );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'ShipStation' )
- ).not.toBeInTheDocument();
- expect( screen.queryByText( 'Packlink PRO' ) ).toBeInTheDocument();
- } );
-
- it( 'should show only Packlink PRO for DE', () => {
- mockSelectForCountry( 'DE' );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).not.toBeInTheDocument();
- expect(
- screen.queryByText( 'ShipStation' )
- ).not.toBeInTheDocument();
- expect( screen.queryByText( 'Packlink PRO' ) ).toBeInTheDocument();
- } );
-
- it( 'should show only ShipStation for GB', () => {
- mockSelectForCountry( 'GB' );
- render( <ShippingRecommendations /> );
-
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- expect(
- screen.queryByText( 'Packlink PRO' )
- ).not.toBeInTheDocument();
- } );
-
- it( 'should show only ShipStation for AU', () => {
- mockSelectForCountry( 'AU' );
- render( <ShippingRecommendations /> );
-
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- expect(
- screen.queryByText( 'Packlink PRO' )
- ).not.toBeInTheDocument();
- } );
-
- it( 'should show only ShipStation for NZ', () => {
- mockSelectForCountry( 'NZ' );
- render( <ShippingRecommendations /> );
-
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- } );
-
- it.each( [ 'ES', 'IT', 'NL', 'AT', 'BE', 'IE', 'PT' ] )(
- 'should show only Packlink PRO for %s',
- ( country ) => {
- mockSelectForCountry( country );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'Packlink PRO' )
- ).toBeInTheDocument();
- expect(
- screen.queryByText( 'ShipStation' )
- ).not.toBeInTheDocument();
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).not.toBeInTheDocument();
- }
- );
-
- it( 'should not render recommendations for unsupported countries', () => {
- mockSelectForCountry( 'JP' );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).not.toBeInTheDocument();
- expect(
- screen.queryByText( 'ShipStation' )
- ).not.toBeInTheDocument();
- expect(
- screen.queryByText( 'Packlink PRO' )
- ).not.toBeInTheDocument();
- } );
- } );
-
- describe( 'rendering when partners are already active', () => {
- it( 'should still show WooCommerce Shipping when it is already active', () => {
- mockSelectForCountry( 'US', [ 'woocommerce-shipping' ] );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- } );
-
- it( 'should still show ShipStation when it is already active', () => {
- mockSelectForCountry( 'US', [
- 'woocommerce-shipstation-integration',
- ] );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- } );
-
- it( 'should still show Packlink PRO when it is already active', () => {
- mockSelectForCountry( 'FR', [ 'packlink-pro-shipping' ] );
- render( <ShippingRecommendations /> );
-
- expect( screen.queryByText( 'Packlink PRO' ) ).toBeInTheDocument();
- } );
-
- it( 'should still render all recommendations when every extension for a country is active', () => {
- mockSelectForCountry( 'US', [
- 'woocommerce-shipping',
- 'woocommerce-shipstation-integration',
- ] );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- expect( screen.queryByText( 'ShipStation' ) ).toBeInTheDocument();
- } );
-
- it( 'should render "Active" pills instead of CTA buttons for partners that are already active', () => {
- mockSelectForCountry(
- 'US',
- [
- 'woocommerce-shipping',
- 'woocommerce-shipstation-integration',
- ],
- {
- getInstalledPlugins: () => [
- 'woocommerce-shipping',
- 'woocommerce-shipstation-integration',
- ],
- }
- );
- render( <ShippingRecommendations /> );
-
- expect( screen.queryAllByText( 'Active' ) ).toHaveLength( 2 );
- expect(
- screen.queryByRole( 'button', { name: 'Install' } )
- ).not.toBeInTheDocument();
- expect(
- screen.queryByRole( 'button', { name: 'Activate' } )
- ).not.toBeInTheDocument();
- } );
-
- it( 'should render an "Active" pill only for the active partner and keep CTAs for inactive ones', () => {
- mockSelectForCountry( 'US', [ 'woocommerce-shipping' ] );
- render( <ShippingRecommendations /> );
-
- // WooCommerce Shipping is active → "Active" pill.
- // ShipStation is neither installed nor active → Install button shown.
- expect( screen.queryAllByText( 'Active' ) ).toHaveLength( 1 );
- const installButtons = screen.queryAllByRole( 'button', {
- name: 'Install',
- } );
- expect( installButtons ).toHaveLength( 1 );
- expect(
- screen.queryByRole( 'button', { name: 'Activate' } )
- ).not.toBeInTheDocument();
- } );
- } );
-
- describe( 'digital products only', () => {
- it( 'should not render when store sells digital products only', () => {
- ( useSelect as jest.Mock ).mockImplementation( ( fn ) =>
- fn( () => ( {
- ...defaultSelectReturn,
- getProfileItems: () => ( {
- product_types: [ 'downloads' ],
- } ),
- } ) )
- );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).not.toBeInTheDocument();
- } );
- } );
-
- describe( 'impression tracking', () => {
- it( 'should fire shipping_partner_impression on mount for US', () => {
- mockSelectForCountry( 'US' );
- render( <ShippingRecommendations /> );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_impression',
- {
- context: 'settings',
- country: 'US',
- plugins:
- 'woocommerce-shipping,woocommerce-shipstation-integration',
- }
- );
- } );
-
- it( 'should fire shipping_partner_impression with correct plugins for DE', () => {
- ( recordEvent as jest.Mock ).mockClear();
- mockSelectForCountry( 'DE' );
- render( <ShippingRecommendations /> );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_impression',
- {
- context: 'settings',
- country: 'DE',
- plugins: 'packlink-pro-shipping',
- }
- );
- } );
-
- it( 'should not fire shipping_partner_impression for unsupported countries', () => {
- ( recordEvent as jest.Mock ).mockClear();
- mockSelectForCountry( 'JP' );
- render( <ShippingRecommendations /> );
-
- expect( recordEvent ).not.toHaveBeenCalledWith(
- 'shipping_partner_impression',
- expect.anything()
- );
- } );
-
- it( 'should not fire shipping_partner_impression when selling digital products only', () => {
- ( recordEvent as jest.Mock ).mockClear();
- ( useSelect as jest.Mock ).mockImplementation( ( fn ) =>
- fn( () => ( {
- ...defaultSelectReturn,
- getProfileItems: () => ( {
- product_types: [ 'downloads' ],
- } ),
- } ) )
- );
- render( <ShippingRecommendations /> );
-
- expect( recordEvent ).not.toHaveBeenCalledWith(
- 'shipping_partner_impression',
- expect.anything()
- );
- } );
- } );
-
- describe( 'WooCommerce Shipping item', () => {
- it( 'should render WC Shipping when not installed', () => {
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- } );
-
- it( 'should trigger event settings_shipping_recommendation_visit_marketplace_click when clicking the WooCommerce Marketplace link', () => {
- render( <ShippingRecommendations /> );
-
- fireEvent.click(
- screen.getByText( 'the WooCommerce Marketplace' )
- );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'settings_shipping_recommendation_visit_marketplace_click',
- {}
- );
- } );
-
- it( 'should navigate to the marketplace when clicking the WooCommerce Marketplace link', async () => {
- const { isFeatureEnabled } = jest.requireMock( '~/utils/features' );
- const originalLocation = global.window.location;
- ( isFeatureEnabled as jest.Mock ).mockReturnValue( true );
-
- const mockLocation = {
- href: 'test',
- } as Location;
-
- mockLocation.href = 'test';
- Object.defineProperty( global.window, 'location', {
- value: mockLocation,
- } );
-
- render( <ShippingRecommendations /> );
-
- fireEvent.click(
- screen.getByText( 'the WooCommerce Marketplace' )
- );
-
- expect( mockLocation.href ).toContain(
- 'admin.php?page=wc-admin&tab=extensions&path=/extensions&category=shipping'
- );
-
- Object.defineProperty( global.window, 'location', {
- value: originalLocation,
- } );
- } );
- } );
-
- describe( 'plugin installation', () => {
- it( 'allows to install WooCommerce Shipping', async () => {
- const installPluginsMock = jest.fn().mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: installPluginsMock,
- activatePlugins: jest.fn().mockResolvedValue( undefined ),
- createSuccessNotice: successNoticeMock,
- } );
- mockSelectForCountry( 'US', [
- 'woocommerce-shipstation-integration',
- ] );
- render( <ShippingRecommendations /> );
-
- // Both cards are now rendered for US; the first "Install" button
- // belongs to the WooCommerce Shipping card (first entry in the
- // COUNTRY_EXTENSIONS_MAP for US).
- userEvent.click( screen.getAllByText( 'Install' )[ 0 ] );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_click',
- {
- context: 'settings',
- country: 'US',
- plugins:
- 'woocommerce-shipping,woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipping',
- }
- );
- expect( installPluginsMock ).toHaveBeenCalledWith( [
- 'woocommerce-shipping',
- ] );
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- 'WooCommerce Shipping is installed!',
- expect.anything()
- );
- } );
- } );
-
- it( 'allows to install ShipStation', async () => {
- const installPluginsMock = jest.fn().mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: installPluginsMock,
- activatePlugins: jest.fn().mockResolvedValue( undefined ),
- createSuccessNotice: successNoticeMock,
- } );
- mockSelectForCountry( 'CA' );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Install' ) );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_click',
- {
- context: 'settings',
- country: 'CA',
- plugins: 'woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipstation-integration',
- }
- );
- expect( installPluginsMock ).toHaveBeenCalledWith( [
- 'woocommerce-shipstation-integration',
- ] );
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- 'ShipStation is installed!',
- expect.anything()
- );
- } );
- } );
-
- it( 'allows to install Packlink PRO', async () => {
- const installPluginsMock = jest.fn().mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: installPluginsMock,
- activatePlugins: jest.fn().mockResolvedValue( undefined ),
- createSuccessNotice: successNoticeMock,
- } );
- mockSelectForCountry( 'FR' );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Install' ) );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_click',
- {
- context: 'settings',
- country: 'FR',
- plugins: 'packlink-pro-shipping',
- selected_plugin: 'packlink-pro-shipping',
- }
- );
- expect( installPluginsMock ).toHaveBeenCalledWith( [
- 'packlink-pro-shipping',
- ] );
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- 'Packlink PRO is installed!',
- expect.anything()
- );
- } );
- } );
- } );
-
- describe( 'install result tracking', () => {
- it( 'should fire shipping_partner_install with success on successful install', async () => {
- ( recordEvent as jest.Mock ).mockClear();
- const installPluginsMock = jest.fn().mockResolvedValue( undefined );
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: installPluginsMock,
- activatePlugins: jest.fn().mockResolvedValue( undefined ),
- createSuccessNotice: jest.fn(),
- } );
- mockSelectForCountry( 'CA' );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Install' ) );
-
- await waitFor( () => {
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_install',
- {
- context: 'settings',
- country: 'CA',
- plugins: 'woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipstation-integration',
- success: true,
- }
- );
- } );
- } );
-
- it( 'should fire shipping_partner_install with failure on failed install', async () => {
- ( recordEvent as jest.Mock ).mockClear();
- const installPluginsMock = jest.fn().mockRejectedValue( {
- errors: { plugin: 'Install failed' },
- } );
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: installPluginsMock,
- activatePlugins: jest.fn().mockResolvedValue( undefined ),
- createSuccessNotice: jest.fn(),
- } );
- mockSelectForCountry( 'CA' );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Install' ) );
-
- await waitFor( () => {
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_install',
- {
- context: 'settings',
- country: 'CA',
- plugins: 'woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipstation-integration',
- success: false,
- }
- );
- } );
- } );
- } );
-
- describe( 'activate result tracking', () => {
- it( 'should fire shipping_partner_activate with success on successful activation', async () => {
- ( recordEvent as jest.Mock ).mockClear();
- const activatePluginsMock = jest
- .fn()
- .mockResolvedValue( undefined );
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: jest.fn().mockResolvedValue( undefined ),
- activatePlugins: activatePluginsMock,
- createSuccessNotice: jest.fn(),
- } );
- mockSelectForCountry( 'CA', [], {
- getInstalledPlugins: () => [
- 'woocommerce-shipstation-integration',
- ],
- } );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Activate' ) );
-
- await waitFor( () => {
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_activate',
- {
- context: 'settings',
- country: 'CA',
- plugins: 'woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipstation-integration',
- success: true,
- }
- );
- } );
- } );
-
- it( 'should fire shipping_partner_activate with failure on failed activation', async () => {
- ( recordEvent as jest.Mock ).mockClear();
- const activatePluginsMock = jest.fn().mockRejectedValue( {
- errors: { plugin: 'Activate failed' },
- } );
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: jest.fn().mockResolvedValue( undefined ),
- activatePlugins: activatePluginsMock,
- createSuccessNotice: jest.fn(),
- } );
- mockSelectForCountry( 'CA', [], {
- getInstalledPlugins: () => [
- 'woocommerce-shipstation-integration',
- ],
- } );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Activate' ) );
-
- await waitFor( () => {
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_activate',
- {
- context: 'settings',
- country: 'CA',
- plugins: 'woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipstation-integration',
- success: false,
- }
- );
- } );
- } );
- } );
-
- describe( 'plugin activation (installed but not active)', () => {
- it( 'shows Activate button for WooCommerce Shipping when installed but not active', () => {
- mockSelectForCountry( 'US', [], {
- getInstalledPlugins: () => [ 'woocommerce-shipping' ],
- } );
- render( <ShippingRecommendations /> );
-
- const buttons = screen.getAllByText( 'Activate' );
- expect( buttons ).toHaveLength( 1 );
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- } );
-
- it( 'shows Activate button for ShipStation when installed but not active', () => {
- mockSelectForCountry( 'CA', [], {
- getInstalledPlugins: () => [
- 'woocommerce-shipstation-integration',
- ],
- } );
- render( <ShippingRecommendations /> );
-
- expect( screen.getByText( 'Activate' ) ).toBeInTheDocument();
- expect( screen.queryByText( 'Install' ) ).not.toBeInTheDocument();
- } );
-
- it( 'shows Activate button for Packlink PRO when installed but not active', () => {
- mockSelectForCountry( 'FR', [], {
- getInstalledPlugins: () => [ 'packlink-pro-shipping' ],
- } );
- render( <ShippingRecommendations /> );
-
- expect( screen.getByText( 'Activate' ) ).toBeInTheDocument();
- expect( screen.queryByText( 'Install' ) ).not.toBeInTheDocument();
- } );
-
- it( 'shows activated notice for WooCommerce Shipping when activating installed plugin', async () => {
- const activatePluginsMock = jest
- .fn()
- .mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: jest.fn().mockResolvedValue( undefined ),
- activatePlugins: activatePluginsMock,
- createSuccessNotice: successNoticeMock,
- } );
- mockSelectForCountry(
- 'US',
- [ 'woocommerce-shipstation-integration' ],
- {
- getInstalledPlugins: () => [ 'woocommerce-shipping' ],
- }
- );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Activate' ) );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_click',
- {
- context: 'settings',
- country: 'US',
- plugins:
- 'woocommerce-shipping,woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipping',
- }
- );
- expect( activatePluginsMock ).toHaveBeenCalledWith( [
- 'woocommerce-shipping',
- ] );
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- 'WooCommerce Shipping activated!',
- expect.anything()
- );
- } );
- } );
-
- it( 'shows activated notice for ShipStation when activating installed plugin', async () => {
- const activatePluginsMock = jest
- .fn()
- .mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: jest.fn().mockResolvedValue( undefined ),
- activatePlugins: activatePluginsMock,
- createSuccessNotice: successNoticeMock,
- } );
- mockSelectForCountry( 'CA', [], {
- getInstalledPlugins: () => [
- 'woocommerce-shipstation-integration',
- ],
- } );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Activate' ) );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_click',
- {
- context: 'settings',
- country: 'CA',
- plugins: 'woocommerce-shipstation-integration',
- selected_plugin: 'woocommerce-shipstation-integration',
- }
- );
- expect( activatePluginsMock ).toHaveBeenCalledWith( [
- 'woocommerce-shipstation-integration',
- ] );
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- 'ShipStation activated!',
- expect.anything()
- );
- } );
- } );
-
- it( 'shows activated notice for Packlink PRO when activating installed plugin', async () => {
- const activatePluginsMock = jest
- .fn()
- .mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- ( useDispatch as jest.Mock ).mockReturnValue( {
- installAndActivatePlugins: jest
- .fn()
- .mockResolvedValue( undefined ),
- installPlugins: jest.fn().mockResolvedValue( undefined ),
- activatePlugins: activatePluginsMock,
- createSuccessNotice: successNoticeMock,
- } );
- mockSelectForCountry( 'FR', [], {
- getInstalledPlugins: () => [ 'packlink-pro-shipping' ],
- } );
- render( <ShippingRecommendations /> );
-
- userEvent.click( screen.getByText( 'Activate' ) );
-
- expect( recordEvent ).toHaveBeenCalledWith(
- 'shipping_partner_click',
- {
- context: 'settings',
- country: 'FR',
- plugins: 'packlink-pro-shipping',
- selected_plugin: 'packlink-pro-shipping',
- }
- );
- expect( activatePluginsMock ).toHaveBeenCalledWith( [
- 'packlink-pro-shipping',
- ] );
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- 'Packlink PRO activated!',
- expect.anything()
- );
- } );
- } );
- } );
-} );
diff --git a/plugins/woocommerce/client/admin/client/shipping/test/shipping-recommendations.test.js b/plugins/woocommerce/client/admin/client/shipping/test/shipping-recommendations.test.js
deleted file mode 100644
index b7ec962e7f7..00000000000
--- a/plugins/woocommerce/client/admin/client/shipping/test/shipping-recommendations.test.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * External dependencies
- */
-import { render, screen, waitFor } from '@testing-library/react';
-import { useDispatch, useSelect } from '@wordpress/data';
-import userEvent from '@testing-library/user-event';
-
-/**
- * Internal dependencies
- */
-import ShippingRecommendations from '../shipping-recommendations';
-
-jest.mock( '@wordpress/data', () => ( {
- ...jest.requireActual( '@wordpress/data' ),
- useSelect: jest.fn(),
- useDispatch: jest.fn(),
-} ) );
-jest.mock( '../../settings-recommendations/dismissable-list', () => ( {
- DismissableList: ( { children } ) => children,
- DismissableListHeading: ( { children } ) => children,
-} ) );
-jest.mock( '../../lib/notices', () => ( {
- createNoticesFromResponse: () => null,
-} ) );
-jest.mock( '~/hooks/use-option-dismiss', () => ( {
- useOptionDismiss: () => ( { isDismissed: false, onDismiss: jest.fn() } ),
-} ) );
-
-describe( 'ShippingRecommendations', () => {
- beforeEach( () => {
- useSelect.mockImplementation( ( fn ) =>
- fn( () => ( {
- getActivePlugins: () => [],
- isJetpackConnected: () => false,
- } ) )
- );
- useDispatch.mockReturnValue( {
- installAndActivatePlugins: () => Promise.resolve(),
- createSuccessNotice: () => null,
- } );
- } );
-
- it( 'should render when WCS&T is installed', () => {
- useSelect.mockImplementation( ( fn ) =>
- fn( () => ( {
- getActivePlugins: () => [ 'woocommerce-services' ],
- isJetpackConnected: () => false,
- } ) )
- );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- } );
-
- it( 'should not render when the WooCommerce Shipping plugin is active', () => {
- useSelect.mockImplementation( ( fn ) =>
- fn( () => ( {
- getActivePlugins: () => [ 'woocommerce-shipping' ],
- } ) )
- );
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).not.toBeInTheDocument();
- } );
-
- it( 'should render when WooCommerce Shipping is not installed', () => {
- render( <ShippingRecommendations /> );
-
- expect(
- screen.queryByText( 'WooCommerce Shipping' )
- ).toBeInTheDocument();
- } );
-
- it( 'allows to install WooCommerce Shipping', async () => {
- const installAndActivatePluginsMock = jest
- .fn()
- .mockResolvedValue( undefined );
- const successNoticeMock = jest.fn();
- useDispatch.mockReturnValue( {
- installAndActivatePlugins: installAndActivatePluginsMock,
- isJetpackConnected: () => false,
- createSuccessNotice: successNoticeMock,
- } );
- render( <ShippingRecommendations /> );
-
- expect( installAndActivatePluginsMock ).not.toHaveBeenCalled();
- expect( successNoticeMock ).not.toHaveBeenCalled();
-
- userEvent.click( screen.getByText( 'Get started' ) );
-
- expect( installAndActivatePluginsMock ).toHaveBeenCalled();
- await waitFor( () => {
- expect( successNoticeMock ).toHaveBeenCalledWith(
- '🎉 WooCommerce Shipping is installed!',
- expect.anything()
- );
- } );
- } );
-} );
diff --git a/plugins/woocommerce/client/admin/client/shipping/test/experimental-woocommerce-shipping-item.tsx b/plugins/woocommerce/client/admin/client/shipping/test/woocommerce-shipping-item.tsx
similarity index 99%
rename from plugins/woocommerce/client/admin/client/shipping/test/experimental-woocommerce-shipping-item.tsx
rename to plugins/woocommerce/client/admin/client/shipping/test/woocommerce-shipping-item.tsx
index 16399c20086..0e6eabe158c 100644
--- a/plugins/woocommerce/client/admin/client/shipping/test/experimental-woocommerce-shipping-item.tsx
+++ b/plugins/woocommerce/client/admin/client/shipping/test/woocommerce-shipping-item.tsx
@@ -8,7 +8,7 @@ import { recordEvent } from '@woocommerce/tracks';
/**
* Internal dependencies
*/
-import WooCommerceShippingItem from '../experimental-woocommerce-shipping-item';
+import WooCommerceShippingItem from '../woocommerce-shipping-item';
jest.mock( '@wordpress/data', () => ( {
...jest.requireActual( '@wordpress/data' ),
useDispatch: jest.fn(),
diff --git a/plugins/woocommerce/client/admin/client/shipping/woocommerce-shipping-item.tsx b/plugins/woocommerce/client/admin/client/shipping/woocommerce-shipping-item.tsx
index d24439fcfcb..3606d8e9930 100644
--- a/plugins/woocommerce/client/admin/client/shipping/woocommerce-shipping-item.tsx
+++ b/plugins/woocommerce/client/admin/client/shipping/woocommerce-shipping-item.tsx
@@ -2,11 +2,10 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
-import { useSelect, useDispatch } from '@wordpress/data';
+import { useDispatch } from '@wordpress/data';
import { Button, ExternalLink } from '@wordpress/components';
import { Pill } from '@woocommerce/components';
-import { pluginsStore } from '@woocommerce/data';
-import { getAdminLink } from '@woocommerce/settings';
+import { recordEvent } from '@woocommerce/tracks';
/**
* Internal dependencies
@@ -14,42 +13,71 @@ import { getAdminLink } from '@woocommerce/settings';
import './woocommerce-shipping-item.scss';
import WooIcon from './woo-icon.svg';
-const WoocommerceShippingItem = ( {
- onSetupClick,
+const WOOCOMMERCE_SHIPPING_PLUGIN_SLUG = 'woocommerce-shipping';
+
+export type ShippingPartnerTrackingProps = {
+ context: 'settings';
+ country: string;
+ plugins: string;
+};
+
+const WooCommerceShippingItem = ( {
+ isPluginInstalled,
+ isPluginActive,
+ onInstallClick,
+ onActivateClick,
pluginsBeingSetup,
+ tracking,
}: {
+ isPluginInstalled: boolean;
+ isPluginActive: boolean;
pluginsBeingSetup: Array< string >;
- onSetupClick: ( slugs: string[] ) => PromiseLike< void >;
+ onInstallClick: ( slugs: string[] ) => PromiseLike< void >;
+ onActivateClick: ( slugs: string[] ) => PromiseLike< void >;
+ tracking?: ShippingPartnerTrackingProps;
} ) => {
const { createSuccessNotice } = useDispatch( 'core/notices' );
- const isSiteConnectedToJetpack = useSelect(
- ( select ) => select( pluginsStore ).isJetpackConnected(),
- []
- );
+ const handleClick = () => {
+ const trackingBase = {
+ ...( tracking ?? {} ),
+ selected_plugin: WOOCOMMERCE_SHIPPING_PLUGIN_SLUG,
+ };
- const handleSetupClick = () => {
- onSetupClick( [ 'woocommerce-shipping' ] ).then( () => {
- const actions = [];
- if ( ! isSiteConnectedToJetpack ) {
- actions.push( {
- url: getAdminLink(
- 'admin.php?page=wc-settings&tab=shipping§ion=woocommerce-shipping-settings'
- ),
- label: __(
- 'Finish the setup by connecting your store to WordPress.com.',
- 'woocommerce'
- ),
+ recordEvent( 'shipping_partner_click', trackingBase );
+ recordEvent( 'settings_shipping_recommendation_setup_click', {
+ plugin: WOOCOMMERCE_SHIPPING_PLUGIN_SLUG,
+ action: isPluginInstalled ? 'activate' : 'install',
+ } );
+
+ const action = isPluginInstalled ? onActivateClick : onInstallClick;
+ const eventName = isPluginInstalled
+ ? 'shipping_partner_activate'
+ : 'shipping_partner_install';
+
+ action( [ WOOCOMMERCE_SHIPPING_PLUGIN_SLUG ] ).then(
+ () => {
+ recordEvent( eventName, {
+ ...trackingBase,
+ success: true,
+ } );
+ createSuccessNotice(
+ isPluginInstalled
+ ? __( 'WooCommerce Shipping activated!', 'woocommerce' )
+ : __(
+ 'WooCommerce Shipping is installed!',
+ 'woocommerce'
+ ),
+ {}
+ );
+ },
+ () => {
+ recordEvent( eventName, {
+ ...trackingBase,
+ success: false,
} );
}
-
- createSuccessNotice(
- __( '🎉 WooCommerce Shipping is installed!', 'woocommerce' ),
- {
- actions,
- }
- );
- } );
+ );
};
return (
@@ -58,7 +86,7 @@ const WoocommerceShippingItem = ( {
<img
className="woocommerce-shipping-plugin-item__logo"
src={ WooIcon }
- alt=""
+ alt="WooCommerce Shipping Logo"
/>
</div>
<div className="woocommerce-list__item-text">
@@ -78,19 +106,34 @@ const WoocommerceShippingItem = ( {
</span>
</div>
<div className="woocommerce-list__item-after">
- <Button
- isSecondary
- onClick={ handleSetupClick }
- isBusy={ pluginsBeingSetup.includes(
- 'woocommerce-shipping'
- ) }
- disabled={ pluginsBeingSetup.length > 0 }
- >
- { __( 'Get started', 'woocommerce' ) }
- </Button>
+ { isPluginActive ? (
+ <Button
+ variant="secondary"
+ aria-disabled="true"
+ aria-label={ __(
+ 'WooCommerce Shipping is already active',
+ 'woocommerce'
+ ) }
+ >
+ { __( 'Active', 'woocommerce' ) }
+ </Button>
+ ) : (
+ <Button
+ variant={ isPluginInstalled ? 'primary' : 'secondary' }
+ onClick={ handleClick }
+ isBusy={ pluginsBeingSetup.includes(
+ WOOCOMMERCE_SHIPPING_PLUGIN_SLUG
+ ) }
+ disabled={ pluginsBeingSetup.length > 0 }
+ >
+ { isPluginInstalled
+ ? __( 'Activate', 'woocommerce' )
+ : __( 'Install', 'woocommerce' ) }
+ </Button>
+ ) }
</div>
</div>
);
};
-export default WoocommerceShippingItem;
+export default WooCommerceShippingItem;
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/index.ts b/plugins/woocommerce/client/admin/client/task-lists/fills/index.ts
index d57d3954d93..78defe1a018 100644
--- a/plugins/woocommerce/client/admin/client/task-lists/fills/index.ts
+++ b/plugins/woocommerce/client/admin/client/task-lists/fills/index.ts
@@ -21,9 +21,4 @@ const possiblyImportProductTask = async () => {
possiblyImportProductTask();
-if (
- window.wcAdminFeatures &&
- window.wcAdminFeatures[ 'shipping-smart-defaults' ]
-) {
- import( './experimental-shipping-recommendation' );
-}
+import( './shipping-recommendation' );
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/products/index.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/products/index.tsx
index 569539dc48d..3b701d1a143 100644
--- a/plugins/woocommerce/client/admin/client/task-lists/fills/products/index.tsx
+++ b/plugins/woocommerce/client/admin/client/task-lists/fills/products/index.tsx
@@ -145,7 +145,6 @@ export const Products = () => {
];
if (
- !! window.wcAdminFeatures?.printful &&
! isRequestingPlugins &&
! installedPlugins.includes( 'printful-shipping-for-woocommerce' )
) {
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/products/test/index.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/products/test/index.tsx
index 7e26cb6b2f1..403eb3e4fd3 100644
--- a/plugins/woocommerce/client/admin/client/task-lists/fills/products/test/index.tsx
+++ b/plugins/woocommerce/client/admin/client/task-lists/fills/products/test/index.tsx
@@ -52,10 +52,6 @@ jest.mock( '../use-create-product-by-type', () => ( {
.mockReturnValue( { createProductByType: jest.fn() } ),
} ) );
-jest.mock( '~/utils/features', () => ( {
- isFeatureEnabled: jest.fn(),
-} ) );
-
global.fetch = jest.fn().mockImplementation( () =>
Promise.resolve( {
json: () => Promise.resolve( {} ),
@@ -76,11 +72,6 @@ describe( 'Products', () => {
// Reset location.href
mockLocation.href = '';
-
- // @ts-expect-error -- partial mock
- window.wcAdminFeatures = {
- printful: true,
- };
} );
it( 'should render default products types when onboardingData.profile.productType is null', () => {
@@ -296,9 +287,6 @@ describe( 'Products', () => {
} );
it( 'should navigate to the marketplace when clicking the WooCommerce Marketplace link', async () => {
- const { isFeatureEnabled } = jest.requireMock( '~/utils/features' );
- ( isFeatureEnabled as jest.Mock ).mockReturnValue( true );
-
mockLocation.href = 'test';
Object.defineProperty( global.window, 'location', {
value: mockLocation,
@@ -349,25 +337,6 @@ describe( 'Products', () => {
} );
} );
- it( 'should hide Printful banner when feature is disabled', async () => {
- ( useSelect as jest.Mock ).mockImplementation( ( callback ) =>
- callback( () => ( {
- getInstalledPlugins: () => [],
- isPluginsRequesting: () => false,
- } ) )
- );
-
- window.wcAdminFeatures.printful = false;
-
- const { queryByText } = render( <Products /> );
-
- await waitFor( () => {
- expect(
- queryByText( 'Print-on-demand products' )
- ).not.toBeInTheDocument();
- } );
- } );
-
it( 'should hide Printful banner while plugins are being requested', async () => {
( useSelect as jest.Mock ).mockImplementation( ( callback ) =>
callback( () => ( {
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/connect.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/connect.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/connect.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/connect.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/plugin-banner.scss b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/plugin-banner.scss
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/plugin-banner.scss
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/plugin-banner.scss
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/plugin-banner.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/plugin-banner.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/plugin-banner.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/plugin-banner.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/plugins.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/plugins.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/plugins.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/plugins.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/store-location.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/store-location.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/store-location.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/store-location.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/wcs-banner.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/wcs-banner.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/components/wcs-banner.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/components/wcs-banner.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/discount.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/discount.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/discount.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/discount.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/paper.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/paper.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/paper.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/paper.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/printer.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/printer.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/printer.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/printer.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/shipstation.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/shipstation.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/shipstation.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/shipstation.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/star.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/star.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/star.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/star.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/timer.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/timer.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/timer.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/timer.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/wcs.svg b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/wcs.svg
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/images/wcs.svg
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/images/wcs.svg
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/index.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/index.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/index.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/index.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/shipping-recommendation.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/shipping-recommendation.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/shipping-recommendation.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/shipping-recommendation.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/test/shipping-recommendation.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/test/shipping-recommendation.tsx
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/test/shipping-recommendation.tsx
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/test/shipping-recommendation.tsx
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/types.ts b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/types.ts
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/types.ts
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/types.ts
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/utils.ts b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/utils.ts
similarity index 100%
rename from plugins/woocommerce/client/admin/client/task-lists/fills/experimental-shipping-recommendation/utils.ts
rename to plugins/woocommerce/client/admin/client/task-lists/fills/shipping-recommendation/utils.ts
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/index.js b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/index.js
index 11936c2685e..ffa4ec57862 100644
--- a/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/index.js
+++ b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/index.js
@@ -59,10 +59,6 @@ export class Shipping extends Component {
this.state = this.initialState;
this.completeStep = this.completeStep.bind( this );
- this.shippingSmartDefaultsEnabled =
- window.wcAdminFeatures &&
- window.wcAdminFeatures[ 'shipping-smart-defaults' ];
-
this.storeLocationCompleted = false;
this.shippingPartners = props.shippingPartners;
this.impressionFired = false;
@@ -230,14 +226,9 @@ export class Shipping extends Component {
);
if ( step === 'store_location' && isCompleteAddress ) {
- if (
- this.shippingSmartDefaultsEnabled &&
- ! this.storeLocationCompleted
- ) {
+ if ( ! this.storeLocationCompleted ) {
this.completeStep();
this.storeLocationCompleted = true;
- } else if ( ! this.shippingSmartDefaultsEnabled ) {
- this.completeStep();
}
}
}
@@ -335,11 +326,7 @@ export class Shipping extends Component {
recordEvent( 'tasklist_shipping_set_location', {
country,
} );
-
- // Don't need to trigger completeStep here as it's triggered by the address updates in the componentDidUpdate function.
- if ( this.shippingSmartDefaultsEnabled ) {
- this.completeStep();
- }
+ this.completeStep();
} }
/>
),
@@ -485,279 +472,257 @@ export class Shipping extends Component {
];
// Override the step fields for the smart shipping defaults.
- if ( this.shippingSmartDefaultsEnabled ) {
- const shippingSmartDefaultsSteps = {
- rates: {
- label: __( 'Review your shipping options', 'woocommerce' ),
- description: __(
- 'We recommend the following shipping options based on your location. You can manage your shipping options again at any time in WooCommerce Shipping settings.',
- 'woocommerce'
- ),
- onClick:
- this.state.step !== 'rates'
- ? () => {
- this.setState( { step: 'rates' } );
- }
- : undefined,
- content: (
- <ShippingRates
- buttonText={ __(
- 'Save shipping options',
+ const shippingSmartDefaultsSteps = {
+ rates: {
+ label: __( 'Review your shipping options', 'woocommerce' ),
+ description: __(
+ 'We recommend the following shipping options based on your location. You can manage your shipping options again at any time in WooCommerce Shipping settings.',
+ 'woocommerce'
+ ),
+ onClick:
+ this.state.step !== 'rates'
+ ? () => {
+ this.setState( { step: 'rates' } );
+ }
+ : undefined,
+ content: (
+ <ShippingRates
+ buttonText={ __(
+ 'Save shipping options',
+ 'woocommerce'
+ ) }
+ shippingZones={ this.state.shippingZones }
+ onComplete={ () => {
+ const { id } = task;
+ optimisticallyCompleteTask( id );
+ invalidateResolutionForStoreSelector();
+ this.completeStep();
+ } }
+ createNotice={ createNotice }
+ />
+ ),
+ },
+ label_printing: {
+ label: __(
+ 'Enable shipping label printing and discounted rates',
+ 'woocommerce'
+ ),
+ description:
+ pluginsToPromote.length === 1
+ ? getSinglePluginDescription(
+ pluginsToPromote[ 0 ].name,
+ pluginsToPromote[ 0 ].learn_more_link
+ )
+ : __(
+ 'Save time and money by printing your shipping labels right from your computer with one of these shipping solutions.',
'woocommerce'
- ) }
- shippingZones={ this.state.shippingZones }
- onComplete={ () => {
- const { id } = task;
- optimisticallyCompleteTask( id );
- invalidateResolutionForStoreSelector();
- this.completeStep();
- } }
- createNotice={ createNotice }
- />
- ),
- },
- label_printing: {
- label: __(
- 'Enable shipping label printing and discounted rates',
- 'woocommerce'
- ),
- description:
- pluginsToPromote.length === 1
- ? getSinglePluginDescription(
- pluginsToPromote[ 0 ].name,
- pluginsToPromote[ 0 ].learn_more_link
- )
- : __(
- 'Save time and money by printing your shipping labels right from your computer with one of these shipping solutions.',
- 'woocommerce'
- ),
-
- content: (
- <>
- { pluginsToPromote.length === 1 ? (
- <ShippingLayoutColumn
- shippingMethod={ pluginsToPromote[ 0 ] }
- />
- ) : (
- <div className="woocommerce-task-shipping-recommendation_plugins-install-container">
- { pluginsToPromote.map(
- ( shippingMethod ) => {
- const pluginsForPartner = [
- shippingMethod?.slug,
- ...( shippingMethod?.dependencies ??
- [] ),
- ].filter(
- ( element ) =>
- element !== undefined
- ); // remove undefineds
- return (
- <ShippingLayoutRow
- shippingMethod={
- shippingMethod
- }
- key={ shippingMethod.name }
- >
- <div className="woocommerce-task-shipping-recommendations_plugins-buttons">
- <Plugins
- onComplete={ (
- response
- ) => {
- createNoticesFromResponse(
- response
- );
- recordEvent(
- 'tasklist_shipping_label_printing',
- {
- install: true,
- plugins_to_activate:
- pluginsForPartner,
- }
- );
- this.recordInstallAndActivateEvents(
- shippingMethod.slug,
- true
- );
- invalidateResolutionForStoreSelector();
- this.completeStep();
- } }
- onError={ (
- errors,
- response
- ) => {
- createNoticesFromResponse(
- response
- );
- this.recordInstallAndActivateEvents(
- shippingMethod.slug,
- false
- );
- } }
- onClick={ () => {
- recordEvent(
- 'shipping_partner_click',
- {
- ...this.getShippingPartnerTrackingProps(),
- selected_plugin:
- shippingMethod.slug,
- }
- );
- } }
- installText={ __(
- 'Install and enable',
- 'woocommerce'
- ) }
- learnMoreLink={
- shippingMethod.learn_more_link
+ ),
+
+ content: (
+ <>
+ { pluginsToPromote.length === 1 ? (
+ <ShippingLayoutColumn
+ shippingMethod={ pluginsToPromote[ 0 ] }
+ />
+ ) : (
+ <div className="woocommerce-task-shipping-recommendation_plugins-install-container">
+ { pluginsToPromote.map( ( shippingMethod ) => {
+ const pluginsForPartner = [
+ shippingMethod?.slug,
+ ...( shippingMethod?.dependencies ??
+ [] ),
+ ].filter(
+ ( element ) => element !== undefined
+ ); // remove undefineds
+ return (
+ <ShippingLayoutRow
+ shippingMethod={ shippingMethod }
+ key={ shippingMethod.name }
+ >
+ <div className="woocommerce-task-shipping-recommendations_plugins-buttons">
+ <Plugins
+ onComplete={ (
+ response
+ ) => {
+ createNoticesFromResponse(
+ response
+ );
+ recordEvent(
+ 'tasklist_shipping_label_printing',
+ {
+ install: true,
+ plugins_to_activate:
+ pluginsForPartner,
}
- onLearnMore={ () => {
- recordEvent(
- 'tasklist_shipping_label_printing_learn_more',
- {
- plugin: shippingMethod.slug,
- }
- );
- } }
- pluginSlugs={
- pluginsForPartner
+ );
+ this.recordInstallAndActivateEvents(
+ shippingMethod.slug,
+ true
+ );
+ invalidateResolutionForStoreSelector();
+ this.completeStep();
+ } }
+ onError={ (
+ errors,
+ response
+ ) => {
+ createNoticesFromResponse(
+ response
+ );
+ this.recordInstallAndActivateEvents(
+ shippingMethod.slug,
+ false
+ );
+ } }
+ onClick={ () => {
+ recordEvent(
+ 'shipping_partner_click',
+ {
+ ...this.getShippingPartnerTrackingProps(),
+ selected_plugin:
+ shippingMethod.slug,
}
- installButtonVariant={
- 'secondary'
+ );
+ } }
+ installText={ __(
+ 'Install and enable',
+ 'woocommerce'
+ ) }
+ learnMoreLink={
+ shippingMethod.learn_more_link
+ }
+ onLearnMore={ () => {
+ recordEvent(
+ 'tasklist_shipping_label_printing_learn_more',
+ {
+ plugin: shippingMethod.slug,
}
- />
- </div>
- </ShippingLayoutRow>
- );
- }
- ) }
- </div>
+ );
+ } }
+ pluginSlugs={
+ pluginsForPartner
+ }
+ installButtonVariant={
+ 'secondary'
+ }
+ />
+ </div>
+ </ShippingLayoutRow>
+ );
+ } ) }
+ </div>
+ ) }
+ { pluginsToPromote.length === 1 &&
+ ! hasInstallableSlug( pluginsToPromote[ 0 ] ) && ( // if it doesn't have a slug we just show a download button
+ <a
+ href={
+ pluginsToPromote[ 0 ].learn_more_link
+ }
+ target="_blank"
+ rel="noreferrer"
+ >
+ <Button variant="primary">
+ { __( 'Download', 'woocommerce' ) }
+ </Button>
+ </a>
) }
- { pluginsToPromote.length === 1 &&
- ! hasInstallableSlug(
- pluginsToPromote[ 0 ]
- ) && ( // if it doesn't have a slug we just show a download button
- <a
- href={
- pluginsToPromote[ 0 ]
- .learn_more_link
- }
- target="_blank"
- rel="noreferrer"
- >
- <Button variant="primary">
- { __( 'Download', 'woocommerce' ) }
- </Button>
- </a>
- ) }
- { pluginsToPromote.length === 1 &&
- hasInstallableSlug( pluginsToPromote[ 0 ] ) ? (
- <>
- { ! isJetpackConnected &&
- pluginsToPromote[ 0 ].slug ===
- 'woocommerce-services' && (
- <TermsOfService
- buttonText={ __(
- 'Install and enable',
- 'woocommerce'
- ) }
- />
- ) }
- <Plugins
- onComplete={ ( _plugins, response ) => {
- createNoticesFromResponse(
- response
- );
- recordEvent(
- 'tasklist_shipping_label_printing',
- {
- install: true,
- plugins_to_activate:
- pluginsToActivate,
- }
- );
- this.recordInstallAndActivateEvents(
- pluginsToPromote[ 0 ]?.slug,
- true
- );
- invalidateResolutionForStoreSelector();
- this.completeStep();
- } }
- onError={ ( errors, response ) => {
- createNoticesFromResponse(
- response
- );
- this.recordInstallAndActivateEvents(
+ { pluginsToPromote.length === 1 &&
+ hasInstallableSlug( pluginsToPromote[ 0 ] ) ? (
+ <>
+ { ! isJetpackConnected &&
+ pluginsToPromote[ 0 ].slug ===
+ 'woocommerce-services' && (
+ <TermsOfService
+ buttonText={ __(
+ 'Install and enable',
+ 'woocommerce'
+ ) }
+ />
+ ) }
+ <Plugins
+ onComplete={ ( _plugins, response ) => {
+ createNoticesFromResponse( response );
+ recordEvent(
+ 'tasklist_shipping_label_printing',
+ {
+ install: true,
+ plugins_to_activate:
+ pluginsToActivate,
+ }
+ );
+ this.recordInstallAndActivateEvents(
+ pluginsToPromote[ 0 ]?.slug,
+ true
+ );
+ invalidateResolutionForStoreSelector();
+ this.completeStep();
+ } }
+ onError={ ( errors, response ) => {
+ createNoticesFromResponse( response );
+ this.recordInstallAndActivateEvents(
+ pluginsToPromote[ 0 ]?.slug,
+ false
+ );
+ } }
+ onClick={ () => {
+ recordEvent( 'shipping_partner_click', {
+ ...this.getShippingPartnerTrackingProps(),
+ selected_plugin:
pluginsToPromote[ 0 ]?.slug,
- false
- );
- } }
- onClick={ () => {
- recordEvent(
- 'shipping_partner_click',
- {
- ...this.getShippingPartnerTrackingProps(),
- selected_plugin:
- pluginsToPromote[ 0 ]
- ?.slug,
- }
- );
- } }
- onSkip={
- onShippingPluginInstalltionSkip
- }
- pluginSlugs={ pluginsToActivate }
- installText={ __(
- 'Install and enable',
- 'woocommerce'
- ) }
- />
- </>
- ) : (
- <Button
- isTertiary
- onClick={ onShippingPluginInstalltionSkip }
- className={ clsx(
- 'woocommerce-task-shipping-recommendations_skip-button',
- pluginsToPromote.length === 2
- ? 'dual'
- : ''
+ } );
+ } }
+ onSkip={ onShippingPluginInstalltionSkip }
+ pluginSlugs={ pluginsToActivate }
+ installText={ __(
+ 'Install and enable',
+ 'woocommerce'
) }
- >
- { __( 'No Thanks', 'woocommerce' ) }
- </Button>
- ) }
- </>
- ),
- },
- store_location: {
- label: __( 'Set your store location', 'woocommerce' ),
- description: __(
- 'Add your store location to help us calculate shipping rates and the best shipping options for you. You can manage your store location again at any time in WooCommerce Settings General.',
- 'woocommerce'
- ),
- onClick:
- this.state.step !== 'store_location'
- ? () => {
- this.setState( { step: 'store_location' } );
- }
- : undefined,
- buttonText: __( 'Save store location', 'woocommerce' ),
- },
- };
-
- steps = steps.map( ( step ) => {
- if ( shippingSmartDefaultsSteps.hasOwnProperty( step.key ) ) {
- step = {
- ...step,
- ...shippingSmartDefaultsSteps[ step.key ],
- };
- }
- // Empty description field if it's not the current step.
- if ( step.key !== this.state.step ) {
- step.description = '';
- }
- return step;
- } );
- }
+ />
+ </>
+ ) : (
+ <Button
+ isTertiary
+ onClick={ onShippingPluginInstalltionSkip }
+ className={ clsx(
+ 'woocommerce-task-shipping-recommendations_skip-button',
+ pluginsToPromote.length === 2 ? 'dual' : ''
+ ) }
+ >
+ { __( 'No Thanks', 'woocommerce' ) }
+ </Button>
+ ) }
+ </>
+ ),
+ },
+ store_location: {
+ label: __( 'Set your store location', 'woocommerce' ),
+ description: __(
+ 'Add your store location to help us calculate shipping rates and the best shipping options for you. You can manage your store location again at any time in WooCommerce Settings General.',
+ 'woocommerce'
+ ),
+ onClick:
+ this.state.step !== 'store_location'
+ ? () => {
+ this.setState( { step: 'store_location' } );
+ }
+ : undefined,
+ buttonText: __( 'Save store location', 'woocommerce' ),
+ },
+ };
+
+ steps = steps.map( ( step ) => {
+ if ( shippingSmartDefaultsSteps.hasOwnProperty( step.key ) ) {
+ step = {
+ ...step,
+ ...shippingSmartDefaultsSteps[ step.key ],
+ };
+ }
+ // Empty description field if it's not the current step.
+ if ( step.key !== this.state.step ) {
+ step.description = '';
+ }
+ return step;
+ } );
return filter( steps, ( step ) => step.visible );
}
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/shipping-providers/partners.tsx b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/shipping-providers/partners.tsx
index 1be3bae388f..a03be24faf5 100644
--- a/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/shipping-providers/partners.tsx
+++ b/plugins/woocommerce/client/admin/client/task-lists/fills/shipping/shipping-providers/partners.tsx
@@ -6,7 +6,7 @@ import { ShippingMethod } from '@woocommerce/data';
/**
* Internal dependencies
*/
-import { PluginBanner } from '../../experimental-shipping-recommendation/components/plugin-banner';
+import { PluginBanner } from '../../shipping-recommendation/components/plugin-banner';
/**
* Renders a column layout for the shipping method. Used for rendering a single shipping partner.
diff --git a/plugins/woocommerce/client/admin/client/task-lists/fills/utils.js b/plugins/woocommerce/client/admin/client/task-lists/fills/utils.js
index 020b923287f..0a966447ac6 100644
--- a/plugins/woocommerce/client/admin/client/task-lists/fills/utils.js
+++ b/plugins/woocommerce/client/admin/client/task-lists/fills/utils.js
@@ -10,7 +10,6 @@ const onboardingData = getAdminSetting( 'onboarding' );
*/
export const isImportProduct = () => {
return (
- window?.wcAdminFeatures?.[ 'import-products-task' ] &&
onboardingData?.profile?.business_choice &&
onboardingData?.profile?.business_choice === 'im_already_selling'
);
diff --git a/plugins/woocommerce/client/admin/client/typings/global.d.ts b/plugins/woocommerce/client/admin/client/typings/global.d.ts
index dc8fbcd9b30..1cf666dbe7e 100644
--- a/plugins/woocommerce/client/admin/client/typings/global.d.ts
+++ b/plugins/woocommerce/client/admin/client/typings/global.d.ts
@@ -1,3 +1,66 @@
+type DeprecatedWcAdminFeatureFlags = {
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'activity-panels': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ analytics: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'analytics-scheduled-import': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'experimental-iapi-mini-cart': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ coupons: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'core-profiler': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'customize-store': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'customer-effort-score-tracks': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'import-products-task': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'experimental-fashion-sample-products': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'shipping-smart-defaults': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'shipping-setting-tour': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ homescreen: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ marketing: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'mobile-app-banner': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ onboarding: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'onboarding-tasks': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'pattern-toolkit-full-composability': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'payment-gateway-suggestions': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'product-custom-fields': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ printful: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'remote-inbox-notifications': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'remote-free-extensions': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'shipping-label-banner': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ subscriptions: boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'transient-notices': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'wc-pay-promotion': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'wc-pay-welcome-page': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'woo-mobile-welcome': boolean;
+ /** @deprecated Deprecated since WooCommerce 11.1. This WC Admin feature flag shim will be removed in a future version of WooCommerce. */
+ 'launch-your-store': boolean;
+};
+
declare global {
interface Window {
location: Location;
@@ -48,38 +111,15 @@ declare global {
siteVisibilitySettings: Record< string, string >;
};
};
- wcAdminFeatures: {
- 'analytics-scheduled-import': boolean;
- 'activity-panels': boolean;
- analytics: boolean;
- coupons: boolean;
- 'customer-effort-score-tracks': boolean;
- homescreen: boolean;
- marketing: boolean;
+ wcAdminFeatures: DeprecatedWcAdminFeatureFlags & {
+ 'product-data-views': boolean;
+ 'experimental-blocks': boolean;
'minified-js': boolean;
- 'mobile-app-banner': boolean;
- navigation: boolean;
- onboarding: boolean;
- 'onboarding-tasks': boolean;
- 'payment-gateway-suggestions': boolean;
- 'pattern-toolkit-full-composability': boolean;
- printful: boolean;
- 'product-custom-fields': boolean;
- 'remote-inbox-notifications': boolean;
- 'remote-free-extensions': boolean;
- settings: boolean;
'settings-ui': boolean;
- 'shipping-label-banner': boolean;
- subscriptions: boolean;
'store-alerts': boolean;
- 'transient-notices': boolean;
- 'wc-pay-promotion': boolean;
- 'wc-pay-welcome-page': boolean;
- 'woo-mobile-welcome': boolean;
- 'shipping-smart-defaults': boolean;
- 'shipping-setting-tour': boolean;
- 'launch-your-store': boolean;
- blueprint: boolean;
+ 'rest-api-v4': boolean;
+ 'order-detail-redesign': boolean;
+ 'product-variations-classic-redesign': boolean;
};
wp: {
updates?: {
diff --git a/plugins/woocommerce/client/admin/client/utils/features/features.ts b/plugins/woocommerce/client/admin/client/utils/features/features.ts
index 6b101c0f790..2f540be3b91 100644
--- a/plugins/woocommerce/client/admin/client/utils/features/features.ts
+++ b/plugins/woocommerce/client/admin/client/utils/features/features.ts
@@ -3,8 +3,43 @@
*/
import { getAdminSetting } from '../admin-settings';
import { Feature } from './types';
+import {
+ isRetiredFeatureFlag,
+ warnRetiredFeatureFlag,
+} from './retired-feature-flags';
const ADMIN_SETTINGS_FEATURES_NAME = 'features';
+const WC_ADMIN_FEATURES_PROXY_MARKER = '__wcRetiredFeatureFlagsProxy';
+
+// Keep retired feature flags available while warning on direct wcAdminFeatures access.
+if (
+ typeof window !== 'undefined' &&
+ window.wcAdminFeatures &&
+ ! ( window.wcAdminFeatures as Record< string, boolean > )[
+ WC_ADMIN_FEATURES_PROXY_MARKER
+ ]
+) {
+ window.wcAdminFeatures = new Proxy( window.wcAdminFeatures, {
+ get( target, property, receiver ) {
+ if (
+ typeof property === 'string' &&
+ isRetiredFeatureFlag( property )
+ ) {
+ warnRetiredFeatureFlag( property );
+ }
+
+ return Reflect.get( target, property, receiver );
+ },
+ } );
+
+ Object.defineProperty(
+ window.wcAdminFeatures,
+ WC_ADMIN_FEATURES_PROXY_MARKER,
+ {
+ value: true,
+ }
+ );
+}
/**
* Get the feature flag from admin settings.
diff --git a/plugins/woocommerce/client/admin/client/utils/features/retired-feature-flags.ts b/plugins/woocommerce/client/admin/client/utils/features/retired-feature-flags.ts
new file mode 100644
index 00000000000..8f787b1afb8
--- /dev/null
+++ b/plugins/woocommerce/client/admin/client/utils/features/retired-feature-flags.ts
@@ -0,0 +1,169 @@
+/**
+ * External dependencies
+ */
+import deprecated from '@wordpress/deprecated';
+
+type RetiredFeatureFlagMetadata = {
+ deprecatedSince: string;
+ removedIn: string | null;
+};
+
+// Keep this dictionary in sync with $retired_feature_compatibility_versions in
+// plugins/woocommerce/src/Admin/Features/Features.php.
+export const RETIRED_FEATURE_FLAGS = {
+ 'activity-panels': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ analytics: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'analytics-scheduled-import': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'experimental-iapi-mini-cart': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ coupons: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'core-profiler': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'customize-store': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'customer-effort-score-tracks': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'import-products-task': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'experimental-fashion-sample-products': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'shipping-smart-defaults': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'shipping-setting-tour': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ homescreen: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ marketing: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'mobile-app-banner': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ onboarding: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'onboarding-tasks': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'pattern-toolkit-full-composability': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'payment-gateway-suggestions': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'product-custom-fields': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ printful: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'remote-inbox-notifications': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'remote-free-extensions': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'shipping-label-banner': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ subscriptions: {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'transient-notices': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'wc-pay-promotion': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'wc-pay-welcome-page': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'woo-mobile-welcome': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+ 'launch-your-store': {
+ deprecatedSince: '11.1.0',
+ removedIn: null,
+ },
+} as const satisfies Record< string, RetiredFeatureFlagMetadata >;
+
+type RetiredFeatureFlag = keyof typeof RETIRED_FEATURE_FLAGS;
+
+export const getRetiredFeatureFlagDeprecationVersion = (
+ featureId: string
+): string | undefined =>
+ RETIRED_FEATURE_FLAGS[ featureId as RetiredFeatureFlag ]?.deprecatedSince;
+
+export const getRetiredFeatureFlagRemovalVersion = (
+ featureId: string
+): string | null | undefined =>
+ RETIRED_FEATURE_FLAGS[ featureId as RetiredFeatureFlag ]?.removedIn;
+
+export const isRetiredFeatureFlag = ( featureId: string ): boolean =>
+ Object.hasOwn( RETIRED_FEATURE_FLAGS, featureId );
+
+export const warnRetiredFeatureFlag = ( featureId: string ): void => {
+ const deprecationVersion =
+ getRetiredFeatureFlagDeprecationVersion( featureId );
+
+ if ( ! deprecationVersion ) {
+ return;
+ }
+ const removalVersion = getRetiredFeatureFlagRemovalVersion( featureId );
+
+ deprecated( `wcAdminFeatures.${ featureId }`, {
+ since: deprecationVersion,
+ plugin: 'WooCommerce',
+ hint: `The ${ featureId } WC Admin feature flag shim will be removed in ${
+ removalVersion
+ ? `WooCommerce ${ removalVersion }`
+ : 'a future version of WooCommerce'
+ }.`,
+ } );
+};
diff --git a/plugins/woocommerce/client/admin/client/utils/test/admin-settings.js b/plugins/woocommerce/client/admin/client/utils/test/admin-settings.js
index 248336b7e04..f86cc9ed86f 100644
--- a/plugins/woocommerce/client/admin/client/utils/test/admin-settings.js
+++ b/plugins/woocommerce/client/admin/client/utils/test/admin-settings.js
@@ -1,7 +1,7 @@
/**
* Internal dependencies
*/
-import { getAdminSetting } from '../admin-settings'; // Adjust the import path
+import { deprecatedAdminProperties, getAdminSetting } from '../admin-settings';
describe( 'getAdminSetting', () => {
let consoleWarnSpy;
@@ -79,4 +79,17 @@ describe( 'getAdminSetting', () => {
process.env.NODE_ENV = _originalNodeEnv; // Restore ENV
} );
+
+ it( 'should not treat admin features as deprecated settings', () => {
+ const features = getAdminSetting( 'features', {
+ 'launch-your-store': {
+ is_enabled: true,
+ },
+ } );
+
+ void features[ 'launch-your-store' ];
+
+ expect( deprecatedAdminProperties.features ).toBeUndefined();
+ expect( consoleWarnSpy ).not.toHaveBeenCalled();
+ } );
} );
diff --git a/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/index.tsx b/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/index.tsx
index 0362e4f973d..4610ee8325c 100644
--- a/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/index.tsx
+++ b/plugins/woocommerce/client/admin/client/wp-admin-scripts/settings-embed/index.tsx
@@ -78,9 +78,8 @@ const registerSlotFills = () => {
registerPaymentsSettingsBannerFill();
const features = window.wcAdminFeatures;
- if ( features?.[ 'launch-your-store' ] === true ) {
- registerSiteVisibilitySlotFill();
- }
+
+ registerSiteVisibilitySlotFill();
if ( isFeatureEnabled( 'blueprint' ) ) {
registerBlueprintSlotfill();
diff --git a/plugins/woocommerce/client/admin/config/core.json b/plugins/woocommerce/client/admin/config/core.json
index 4b77768bce3..ff38978a764 100644
--- a/plugins/woocommerce/client/admin/config/core.json
+++ b/plugins/woocommerce/client/admin/config/core.json
@@ -1,40 +1,10 @@
{
"features": {
- "activity-panels": true,
- "analytics": true,
- "analytics-scheduled-import": true,
"product-data-views": false,
"experimental-blocks": false,
- "experimental-iapi-mini-cart": true,
- "coupons": true,
- "core-profiler": true,
- "customize-store": true,
- "customer-effort-score-tracks": true,
- "import-products-task": true,
- "experimental-fashion-sample-products": true,
- "shipping-smart-defaults": true,
- "shipping-setting-tour": true,
- "homescreen": true,
- "marketing": true,
"minified-js": false,
- "mobile-app-banner": true,
- "onboarding": true,
- "onboarding-tasks": true,
- "pattern-toolkit-full-composability": true,
- "product-custom-fields": true,
- "remote-inbox-notifications": true,
- "remote-free-extensions": true,
- "payment-gateway-suggestions": true,
- "printful": true,
"settings-ui": false,
- "shipping-label-banner": true,
- "subscriptions": true,
"store-alerts": true,
- "transient-notices": true,
- "woo-mobile-welcome": true,
- "wc-pay-promotion": true,
- "wc-pay-welcome-page": true,
- "launch-your-store": true,
"rest-api-v4": false,
"order-detail-redesign": false,
"product-variations-classic-redesign": false
diff --git a/plugins/woocommerce/client/admin/config/development.json b/plugins/woocommerce/client/admin/config/development.json
index b125fd1bbce..5bf4274537f 100644
--- a/plugins/woocommerce/client/admin/config/development.json
+++ b/plugins/woocommerce/client/admin/config/development.json
@@ -1,40 +1,10 @@
{
"features": {
- "activity-panels": true,
- "analytics": true,
- "analytics-scheduled-import": true,
"product-data-views": false,
"experimental-blocks": true,
- "experimental-iapi-mini-cart": true,
- "coupons": true,
- "core-profiler": true,
- "customize-store": true,
- "customer-effort-score-tracks": true,
- "import-products-task": true,
- "experimental-fashion-sample-products": true,
- "shipping-smart-defaults": true,
- "shipping-setting-tour": true,
- "homescreen": true,
- "marketing": true,
"minified-js": true,
- "mobile-app-banner": true,
- "onboarding": true,
- "onboarding-tasks": true,
- "pattern-toolkit-full-composability": true,
- "payment-gateway-suggestions": true,
- "product-custom-fields": true,
- "printful": true,
- "remote-inbox-notifications": true,
- "remote-free-extensions": true,
"settings-ui": false,
- "shipping-label-banner": true,
- "subscriptions": true,
"store-alerts": true,
- "transient-notices": true,
- "woo-mobile-welcome": true,
- "wc-pay-promotion": true,
- "wc-pay-welcome-page": true,
- "launch-your-store": true,
"rest-api-v4": false,
"order-detail-redesign": false,
"product-variations-classic-redesign": false
diff --git a/plugins/woocommerce/client/admin/package.json b/plugins/woocommerce/client/admin/package.json
index a2539e4f775..3c033df7386 100644
--- a/plugins/woocommerce/client/admin/package.json
+++ b/plugins/woocommerce/client/admin/package.json
@@ -84,6 +84,7 @@
"@wordpress/data-controls": "catalog:wp-min",
"@wordpress/dataviews": "catalog:wp-bundled",
"@wordpress/date": "catalog:wp-min",
+ "@wordpress/deprecated": "catalog:wp-min",
"@wordpress/dom": "catalog:wp-min",
"@wordpress/dom-ready": "catalog:wp-min",
"@wordpress/edit-site": "5.15.0",
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/customer-account/frontend.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/customer-account/frontend.ts
index 18e45e4a477..6e7f2cd7271 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/customer-account/frontend.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/customer-account/frontend.ts
@@ -35,8 +35,7 @@ const focusTrigger = () => {
trigger?.focus();
};
-// Set the background color from body so it's reliable. Pattern used in other blocks too
-// e.g. Mini Cart (see mini-cart/utils/set-styles.ts).
+// Set the background color from body so it's reliable.
const getBodyBackgroundColor = (): string => {
const color = getComputedStyle( document.body ).backgroundColor;
if ( ! color || color === 'rgba(0, 0, 0, 0)' || color === 'transparent' ) {
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.json b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.json
index e2aca50db7a..ffaf4f8ad7e 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.json
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.json
@@ -7,6 +7,9 @@
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"textdomain": "woocommerce",
+ "viewScriptModule": "woocommerce/mini-cart",
+ "style": "file:../woocommerce/mini-cart-style.css",
+ "editorStyle": "file:../woocommerce/mini-cart-editor.css",
"supports": {
"html": false,
"multiple": false,
@@ -16,7 +19,8 @@
"spacing": {
"margin": true,
"padding": true
- }
+ },
+ "interactivity": true
},
"example": {
"attributes": {
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.tsx
deleted file mode 100644
index 247751754e3..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/block.tsx
+++ /dev/null
@@ -1,312 +0,0 @@
-/**
- * External dependencies
- */
-import { renderParentBlock } from '@woocommerce/atomic-utils';
-import Drawer from '@woocommerce/base-components/drawer';
-import { useStoreCart } from '@woocommerce/base-context/hooks';
-import {
- getValidBlockAttributes,
- translateJQueryEventToNative,
-} from '@woocommerce/base-utils';
-import { getRegisteredBlockComponents } from '@woocommerce/blocks-registry';
-import {
- formatPrice,
- getCurrencyFromPriceResponse,
-} from '@woocommerce/price-format';
-import { getSettingWithCoercion } from '@woocommerce/settings';
-import {
- isBoolean,
- isString,
- isCartResponseTotals,
- isNumber,
-} from '@woocommerce/types';
-import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
-import { sprintf, _n } from '@wordpress/i18n';
-import clsx from 'clsx';
-import { CHECKOUT_URL } from '@woocommerce/block-settings';
-import type { ReactRootWithContainer } from '@woocommerce/base-utils';
-
-/**
- * Internal dependencies
- */
-import type { BlockAttributes } from './types';
-import QuantityBadge from './quantity-badge';
-import { MiniCartContentsBlock } from './mini-cart-contents/block';
-import './style.scss';
-import {
- blockName,
- attributes as miniCartContentsAttributes,
-} from './mini-cart-contents/attributes';
-import { metadata as miniCartContentsMetadata } from './mini-cart-contents/metadata';
-import { defaultColorItem } from './utils/defaults';
-
-type Props = BlockAttributes;
-
-function getScrollbarWidth() {
- return window.innerWidth - document.documentElement.clientWidth;
-}
-
-const MiniCartBlock = ( attributes: Props ): JSX.Element => {
- const {
- initialCartItemsCount,
- initialCartTotals,
- isInitiallyOpen = false,
- colorClassNames,
- contents = '',
- miniCartIcon,
- addToCartBehaviour = 'none',
- onCartClickBehaviour = 'open_drawer',
- hasHiddenPrice = true,
- priceColor = defaultColorItem,
- iconColor = defaultColorItem,
- productCountColor = defaultColorItem,
- productCountVisibility = 'greater_than_zero',
- } = attributes;
-
- const {
- cartItemsCount: cartItemsCountFromApi,
- cartIsLoading,
- cartTotals: cartTotalsFromApi,
- } = useStoreCart();
-
- const cartIsLoadingForTheFirstTime = useRef( cartIsLoading );
-
- useEffect( () => {
- if ( cartIsLoadingForTheFirstTime.current && ! cartIsLoading ) {
- cartIsLoadingForTheFirstTime.current = false;
- }
- }, [ cartIsLoading, cartIsLoadingForTheFirstTime ] );
-
- const [ isOpen, setIsOpen ] = useState< boolean >( isInitiallyOpen );
- // We already rendered the HTML drawer placeholder, so we want to skip the
- // slide in animation.
- const [ skipSlideIn, setSkipSlideIn ] =
- useState< boolean >( isInitiallyOpen );
- const [ contentsNode, setContentsNode ] = useState< HTMLDivElement | null >(
- null
- );
-
- const contentsRef = useCallback( ( node ) => {
- setContentsNode( node );
- }, [] );
-
- const rootRef = useRef< ReactRootWithContainer[] | null >( null );
-
- useEffect( () => {
- const body = document.querySelector( 'body' );
- if ( body ) {
- const scrollBarWidth = getScrollbarWidth();
- if ( isOpen ) {
- Object.assign( body.style, {
- overflow: 'hidden',
- paddingRight: scrollBarWidth + 'px',
- } );
- } else {
- Object.assign( body.style, { overflow: '', paddingRight: 0 } );
- }
- }
- }, [ isOpen ] );
-
- useEffect( () => {
- if ( contentsNode instanceof Element ) {
- const container = contentsNode.querySelector(
- '.wp-block-woocommerce-mini-cart-contents'
- );
- if ( ! container ) {
- return;
- }
- if ( isOpen ) {
- const renderedBlock = renderParentBlock( {
- Block: MiniCartContentsBlock,
- blockName,
- getProps: ( el: Element ) => {
- return {
- attributes: getValidBlockAttributes(
- miniCartContentsAttributes,
- /* eslint-disable @typescript-eslint/no-explicit-any */
- ( el instanceof HTMLElement
- ? el.dataset
- : {} ) as any
- ),
- };
- },
- selector: '.wp-block-woocommerce-mini-cart-contents',
- blockMap: getRegisteredBlockComponents( blockName ),
- options: {
- multiple:
- miniCartContentsMetadata.supports?.multiple ??
- false,
- },
- } );
- rootRef.current = renderedBlock;
- }
- }
-
- return () => {
- if ( contentsNode instanceof Element && isOpen ) {
- const unmountingContainer = contentsNode.querySelector(
- '.wp-block-woocommerce-mini-cart-contents'
- );
-
- if ( unmountingContainer ) {
- const foundRoot = rootRef?.current?.find(
- ( { container } ) => unmountingContainer === container
- );
- if ( typeof foundRoot?.root?.unmount === 'function' ) {
- setTimeout( () => {
- foundRoot.root.unmount();
- } );
- }
- }
- }
- };
- }, [ isOpen, contentsNode ] );
-
- useEffect( () => {
- const openMiniCart = () => {
- if ( addToCartBehaviour === 'open_drawer' ) {
- setSkipSlideIn( false );
- setIsOpen( true );
- }
- };
-
- // Make it so we can read jQuery events triggered by WC Core elements.
- const removeJQueryAddedToCartEvent = translateJQueryEventToNative(
- 'added_to_cart',
- 'wc-blocks_added_to_cart'
- );
-
- document.body.addEventListener(
- 'wc-blocks_added_to_cart',
- openMiniCart
- );
-
- return () => {
- removeJQueryAddedToCartEvent();
-
- document.body.removeEventListener(
- 'wc-blocks_added_to_cart',
- openMiniCart
- );
- };
- }, [ addToCartBehaviour ] );
-
- const showIncludingTax = getSettingWithCoercion(
- 'displayCartPricesIncludingTax',
- false,
- isBoolean
- );
-
- const taxLabel = getSettingWithCoercion( 'taxLabel', '', isString );
-
- const cartTotals =
- cartIsLoadingForTheFirstTime.current &&
- isCartResponseTotals( initialCartTotals )
- ? initialCartTotals
- : cartTotalsFromApi;
-
- const cartItemsCount =
- cartIsLoadingForTheFirstTime.current &&
- isNumber( initialCartItemsCount )
- ? initialCartItemsCount
- : cartItemsCountFromApi;
-
- const subTotal = showIncludingTax
- ? parseInt( cartTotals.total_items, 10 ) +
- parseInt( cartTotals.total_items_tax, 10 )
- : parseInt( cartTotals.total_items, 10 );
-
- const ariaLabel = hasHiddenPrice
- ? sprintf(
- /* translators: %1$d is the number of products in the cart. */
- _n(
- '%1$d item in cart',
- '%1$d items in cart',
- cartItemsCount,
- 'woocommerce'
- ),
- cartItemsCount
- )
- : sprintf(
- /* translators: %1$d is the number of products in the cart. %2$s is the cart total */
- _n(
- '%1$d item in cart, total price of %2$s',
- '%1$d items in cart, total price of %2$s',
- cartItemsCount,
- 'woocommerce'
- ),
- cartItemsCount,
- formatPrice(
- subTotal,
- getCurrencyFromPriceResponse( cartTotals )
- )
- );
-
- return (
- <>
- <button
- className={ `wc-block-mini-cart__button ${ colorClassNames }` }
- onClick={ () => {
- if ( onCartClickBehaviour === 'navigate_to_checkout' ) {
- window.location.href = CHECKOUT_URL;
- return;
- }
-
- if ( ! isOpen ) {
- setIsOpen( true );
- setSkipSlideIn( false );
- }
- } }
- aria-label={ ariaLabel }
- >
- <QuantityBadge
- count={ cartItemsCount }
- icon={ miniCartIcon }
- iconColor={ iconColor }
- productCountColor={ productCountColor }
- productCountVisibility={ productCountVisibility }
- />
- { ! hasHiddenPrice && (
- <span
- translate="no"
- className="wc-block-mini-cart__amount"
- style={ { color: priceColor.color } }
- >
- { formatPrice(
- subTotal,
- getCurrencyFromPriceResponse( cartTotals )
- ) }
- </span>
- ) }
- { taxLabel !== '' && subTotal !== 0 && ! hasHiddenPrice && (
- <small
- className="wc-block-mini-cart__tax-label"
- style={ { color: priceColor.color } }
- >
- { taxLabel }
- </small>
- ) }
- </button>
- <Drawer
- className={ clsx( 'wc-block-mini-cart__drawer', 'is-mobile', {
- 'is-loading': cartIsLoading,
- } ) }
- isOpen={ isOpen }
- onClose={ () => {
- setIsOpen( false );
- } }
- slideIn={ ! skipSlideIn }
- >
- <div
- className="wc-block-mini-cart__template-part"
- ref={ contentsRef }
- // This string is sanitized by the backend https://github.com/woocommerce/woocommerce/blob/ec9274030f2f9d854e23ac332f3303c445c4c4c2/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php#L474-L475
- // eslint-disable-next-line react/no-danger
- dangerouslySetInnerHTML={ { __html: contents } }
- ></div>
- </Drawer>
- </>
- );
-};
-
-export default MiniCartBlock;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/component-frontend.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/component-frontend.tsx
deleted file mode 100644
index 0905993ece3..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/component-frontend.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * External dependencies
- */
-import { renderFrontend } from '@woocommerce/base-utils';
-
-/**
- * Internal dependencies
- */
-import MiniCartBlock from './block';
-import './style.scss';
-
-const renderMiniCartFrontend = () => {
- // Check if button is focused. In that case, we want to refocus it after we
- // replace it with the React equivalent.
- let focusedMiniCartBlock: HTMLElement | null = null;
- /* eslint-disable @wordpress/no-global-active-element */
- if (
- document.activeElement &&
- document.activeElement.classList.contains(
- 'wc-block-mini-cart__button'
- ) &&
- document.activeElement.parentNode instanceof HTMLElement
- ) {
- focusedMiniCartBlock = document.activeElement.parentNode;
- }
- /* eslint-enable @wordpress/no-global-active-element */
-
- renderFrontend( {
- selector: '.wc-block-mini-cart',
- Block: MiniCartBlock,
- getProps: ( el ) => {
- let colorClassNames = '';
- const button = el.querySelector( '.wc-block-mini-cart__button' );
-
- if ( button instanceof HTMLButtonElement ) {
- colorClassNames = button.classList
- .toString()
- .replace( 'wc-block-mini-cart__button', '' );
- }
- return {
- initialCartTotals: el.dataset.cartTotals
- ? JSON.parse( el.dataset.cartTotals )
- : null,
- initialCartItemsCount: el.dataset.cartItemsCount
- ? parseInt( el.dataset.cartItemsCount, 10 )
- : 0,
- isInitiallyOpen: el.dataset.isInitiallyOpen === 'true',
- colorClassNames,
- style: el.dataset.style ? JSON.parse( el.dataset.style ) : {},
- miniCartIcon: el.dataset.miniCartIcon,
- addToCartBehaviour: el.dataset.addToCartBehaviour || 'none',
- onCartClickBehaviour:
- el.dataset.onCartClickBehaviour || 'open_drawer',
- hasHiddenPrice: el.dataset.hasHiddenPrice !== 'false',
- priceColor: el.dataset.priceColor
- ? JSON.parse( el.dataset.priceColor )
- : {},
- iconColor: el.dataset.iconColor
- ? JSON.parse( el.dataset.iconColor )
- : {},
- productCountColor: el.dataset.productCountColor
- ? JSON.parse( el.dataset.productCountColor )
- : {},
- contents:
- el.querySelector( '.wc-block-mini-cart__template-part' )
- ?.innerHTML ?? '',
- productCountVisibility: el.dataset.productCountVisibility,
- };
- },
- } );
-
- // Refocus previously focused button if drawer is not open.
- if (
- focusedMiniCartBlock instanceof HTMLElement &&
- ! focusedMiniCartBlock.dataset.isInitiallyOpen
- ) {
- const innerButton = focusedMiniCartBlock.querySelector(
- '.wc-block-mini-cart__button'
- );
- if ( innerButton instanceof HTMLElement ) {
- innerButton.focus();
- }
- }
-};
-
-renderMiniCartFrontend();
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts
index 0580999e2df..00a58ee82d2 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts
@@ -1,212 +1,1095 @@
/**
* External dependencies
*/
-import preloadScript from '@woocommerce/base-utils/preload-script';
-import lazyLoadScript from '@woocommerce/base-utils/lazy-load-script';
-import getNavigationType from '@woocommerce/base-utils/get-navigation-type';
-import { translateJQueryEventToNative } from '@woocommerce/base-utils/legacy-events';
-import { select, subscribe } from '@wordpress/data';
-import { cartStore } from '@woocommerce/block-data';
+import {
+ store,
+ getContext,
+ getConfig,
+ getElement,
+ useLayoutEffect,
+ useRef,
+ withSyncEvent,
+} from '@wordpress/interactivity';
+import '@woocommerce/stores/woocommerce/cart';
+import '@woocommerce/stores/store-notices';
+import type {
+ Store as WooCommerce,
+ WooCommerceConfig,
+} from '@woocommerce/stores/woocommerce/cart';
/**
* Internal dependencies
*/
-import { updateTotals } from './utils/data';
-import setStyles from './utils/set-styles';
-
-interface dependencyData {
- src: string;
- version?: string;
- after?: string;
- before?: string;
- translations?: string;
-}
+import {
+ formatPriceWithCurrency,
+ normalizeCurrencyResponse,
+} from '../../../../packages/prices/utils/currency';
+import { CartItem, Currency } from '../../types';
+import { translateJQueryEventToNative } from '../../base/stores/woocommerce/legacy-events';
+
+const universalLock =
+ 'I acknowledge that using a private store means my plugin will inevitably break on the next store release.';
+
+const {
+ currency,
+ placeholderImgSrc,
+ nonOptimisticProperties = [],
+} = getConfig( 'woocommerce' ) as WooCommerceConfig;
+const {
+ onCartClickBehaviour,
+ checkoutUrl,
+ displayCartPriceIncludingTax,
+ buttonAriaLabelTemplate,
+} = getConfig( 'woocommerce/mini-cart' );
+const {
+ reduceQuantityLabel,
+ increaseQuantityLabel,
+ quantityDescriptionLabel,
+ removeFromCartLabel,
+} = getConfig( 'woocommerce/mini-cart-products-table-block' );
+const { itemsInCartTextTemplate } = getConfig(
+ 'woocommerce/mini-cart-title-items-counter-block'
+);
-setStyles();
+type ScalePriceArgs = {
+ price: number;
+ inputDecimals: number;
+ outputDecimals?: number;
+};
-declare global {
- interface Window {
- wcBlocksMiniCartFrontendDependencies: Record< string, dependencyData >;
+const scalePrice = ( {
+ price,
+ inputDecimals,
+ outputDecimals = 0,
+}: ScalePriceArgs ) => {
+ const scaledPrice = price * Math.pow( 10, outputDecimals - inputDecimals );
+ // Remove extra decimals.
+ return Math.round( scaledPrice );
+};
+
+/**
+ * Recursively traverses the DOM hierarchy to find the closest non-transparent color.
+ *
+ * @param element The starting element to check.
+ * @param colorType Either 'color' (text) or 'backgroundColor'.
+ * @return The computed color as an RGB string, or null if not found.
+ */
+function getClosestColor(
+ element: Element | null,
+ colorType: 'color' | 'backgroundColor'
+): string | null {
+ if ( ! element ) {
+ return null;
+ }
+ const color = window.getComputedStyle( element )[ colorType ];
+ if ( color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent' ) {
+ const matches = color.match( /\d+/g );
+ if ( ! matches || matches.length < 3 ) {
+ return null;
+ }
+ const [ r, g, b ] = matches.slice( 0, 3 );
+ return `rgb(${ r }, ${ g }, ${ b })`;
}
+ return getClosestColor( element.parentElement, colorType );
}
-window.addEventListener( 'load', () => {
- // Update the totals immediately on load.
- updateTotals( select( cartStore ).getCartData() );
+type MiniCart = {
+ state: {
+ isHydrated: boolean;
+ isOpen: boolean;
+ totalItemsInCart: number;
+ formattedSubtotal: string;
+ drawerOverlayClass: string;
+ badgeIsVisible: boolean;
+ cartIsEmpty: boolean;
+ drawerRole: string | null;
+ drawerTabIndex: string | null;
+ buttonAriaLabel: string;
+ shouldShowTaxLabel: boolean;
+ miniCartButtonRef: HTMLElement | null;
+ contentsBackgroundColor: string;
+ badgeBackgroundColor: string | undefined;
+ badgeTextColor: string | undefined;
+ productCountColor: string;
+ };
+ actions: {
+ openDrawer: () => void;
+ closeDrawer: () => void;
+ overlayCloseDrawer: ( e: MouseEvent ) => void;
+ handleOverlayKeydown: ( e: KeyboardEvent ) => void;
+ };
+ callbacks: {
+ markAsHydrated: () => void;
+ setupJQueryEventBridge: () => void;
+ disableScrollingOnBody: () => void;
+ focusFirstElement: () => void;
+ };
+};
+
+type MiniCartContext = {
+ productCountVisibility: 'never' | 'always' | 'greater_than_zero';
+};
- // Triggers JS event whenever the cart store is updated.
- subscribe( () => {
- updateTotals( select( cartStore ).getCartData() );
- }, cartStore );
+type CartItemContext = {
+ cartItem: CartItem;
+};
- const miniCartBlocks = document.querySelectorAll( '.wc-block-mini-cart' );
- let wasLoadScriptsCalled = false;
+type ItemData = {
+ raw_attribute?: string | undefined;
+ value?: string | undefined;
+ display?: string;
+ attribute?: string;
+ hidden?: boolean | string | number;
+} & ( { key: string; name?: never } | { key?: never; name: string } );
- if ( miniCartBlocks.length === 0 ) {
- return;
- }
+type CartItemDataAttr = {
+ value: string;
+ name: string;
+ className: string;
+ hidden: boolean;
+};
- const dependencies = window.wcBlocksMiniCartFrontendDependencies;
+type DataProperty = 'item_data' | 'variation';
- // Preload scripts
- for ( const dependencyHandle in dependencies ) {
- const dependency = dependencies[ dependencyHandle ];
- preloadScript( {
- handle: dependencyHandle,
- ...dependency,
- } );
+const trimWords = ( html: string, maxWords = 15 ): string => {
+ const words = html.trim().split( /\s+/ );
+ if ( words.length <= maxWords ) {
+ return html;
}
+ return words.slice( 0, maxWords ).join( ' ' ) + '…';
+};
- // Make it so we can read jQuery events triggered by WC Core elements.
- const removeJQueryAddingToCartEvent = translateJQueryEventToNative(
- 'adding_to_cart',
- 'wc-blocks_adding_to_cart'
- );
- const removeJQueryAddedToCartEvent = translateJQueryEventToNative(
- 'added_to_cart',
- 'wc-blocks_added_to_cart'
- );
- const removeJQueryRemovedFromCartEvent = translateJQueryEventToNative(
- 'removed_from_cart',
- 'wc-blocks_removed_from_cart'
- );
-
- const loadScripts = async () => {
- // Ensure we only call loadScripts once.
- if ( wasLoadScriptsCalled ) {
- return;
- }
- wasLoadScriptsCalled = true;
+const focusableSelectors = `
+ a[href],
+ input:not([disabled]):not([type="hidden"]):not([aria-hidden]),
+ select:not([disabled]):not([aria-hidden]),
+ textarea:not([disabled]):not([aria-hidden]),
+ button:not([disabled]):not([aria-hidden]),
+ [contenteditable],
+ [tabindex]:not([tabindex^="-"])
+`;
- // Remove adding to cart event handler.
- document.body.removeEventListener(
- 'wc-blocks_adding_to_cart',
- loadScripts
- );
- removeJQueryAddingToCartEvent();
-
- // Lazy load scripts.
- for ( const dependencyHandle in dependencies ) {
- const dependency = dependencies[ dependencyHandle ];
- await lazyLoadScript( {
- handle: dependencyHandle,
- ...dependency,
- } );
- }
- };
+const getFocusableElements = ( container: HTMLElement | null ) =>
+ container
+ ? Array.from(
+ container.querySelectorAll< HTMLElement >( focusableSelectors )
+ ).filter( ( el ) => el.offsetParent !== null )
+ : [];
- document.body.addEventListener( 'wc-blocks_adding_to_cart', loadScripts );
+const { state: woocommerceState, actions } = store< WooCommerce >(
+ 'woocommerce',
+ {},
+ { lock: universalLock }
+);
- // Load scripts if a page is reloaded via the back button (potentially out of date cart data).
- // Based on refreshCachedCartData() in assets/js/base/context/cart-checkout/cart/index.js.
- window.addEventListener(
- 'pageshow',
- ( event: PageTransitionEvent ): void => {
- if ( event?.persisted || getNavigationType() === 'back_forward' ) {
- loadScripts();
- }
- }
- );
-
- // Check if any Mini-Cart block has 'open_drawer' behavior enabled.
- const shouldOpenDrawerOnAddToCart = Array.from( miniCartBlocks ).some(
- ( block ) => {
- if ( ! ( block instanceof HTMLElement ) ) {
- return false;
- }
- return block.dataset.addToCartBehaviour === 'open_drawer';
- }
- );
+const { state: miniCartState, actions: miniCartActions } = store< MiniCart >(
+ 'woocommerce/mini-cart',
+ {},
+ { lock: true }
+);
- miniCartBlocks.forEach( ( miniCartBlock, i ) => {
- if ( ! ( miniCartBlock instanceof HTMLElement ) ) {
- return;
- }
+// Getters cannot access `state` during hydration if it is not declared
+// beforehand. This will be removed once the iAPI allows this case.
+const { state } = store< MiniCart >(
+ 'woocommerce/mini-cart',
+ {},
+ { lock: universalLock }
+);
- const miniCartButton = miniCartBlock.querySelector(
- '.wc-block-mini-cart__button'
- );
- const miniCartDrawerPlaceholderOverlay = miniCartBlock.querySelector(
- '.wc-block-components-drawer__screen-overlay'
+store< MiniCart >(
+ 'woocommerce/mini-cart',
+ {
+ state: {
+ isHydrated: false,
+ get totalItemsInCart() {
+ if ( nonOptimisticProperties.includes( 'cart.items_count' ) ) {
+ return woocommerceState.cart.items_count as number;
+ }
+ return woocommerceState.cart.items.reduce< number >(
+ ( total, { quantity } ) => total + quantity,
+ 0
+ );
+ },
+
+ get formattedSubtotal(): string {
+ if ( ! currency ) {
+ return '';
+ }
+
+ const subtotal = displayCartPriceIncludingTax
+ ? parseInt( woocommerceState.cart.totals.total_items, 10 ) +
+ parseInt(
+ woocommerceState.cart.totals.total_items_tax,
+ 10
+ )
+ : parseInt( woocommerceState.cart.totals.total_items, 10 );
+
+ const normalizedCurrency = normalizeCurrencyResponse(
+ woocommerceState.cart.totals,
+ currency
+ );
+
+ return formatPriceWithCurrency( subtotal, normalizedCurrency );
+ },
+
+ get drawerRole() {
+ return state.isOpen ? 'dialog' : null;
+ },
+
+ get drawerTabIndex() {
+ return state.isOpen ? '-1' : null;
+ },
+
+ get drawerOverlayClass() {
+ const baseClasses =
+ 'wc-block-components-drawer__screen-overlay wc-block-components-drawer__screen-overlay--with-slide-out';
+ return state.isOpen
+ ? `${ baseClasses } wc-block-components-drawer__screen-overlay--with-slide-in`
+ : `${ baseClasses } wc-block-components-drawer__screen-overlay--is-hidden`;
+ },
+
+ get badgeIsVisible(): boolean {
+ const cartHasItems = miniCartState.totalItemsInCart > 0;
+ const { productCountVisibility } =
+ getContext< MiniCartContext >();
+
+ return (
+ productCountVisibility === 'always' ||
+ ( productCountVisibility === 'greater_than_zero' &&
+ cartHasItems )
+ );
+ },
+
+ get cartIsEmpty(): boolean {
+ return miniCartState.totalItemsInCart === 0;
+ },
+
+ get buttonAriaLabel(): string {
+ return buttonAriaLabelTemplate
+ .replace( '%d', state.totalItemsInCart )
+ .replace( '%1$d', state.totalItemsInCart )
+ .replace( '%2$s', state.formattedSubtotal );
+ },
+
+ get shouldShowTaxLabel(): boolean {
+ return (
+ parseInt(
+ woocommerceState.cart.totals.total_items_tax,
+ 10
+ ) > 0
+ );
+ },
+
+ get contentsBackgroundColor(): string {
+ return (
+ getComputedStyle( document.body ).backgroundColor || '#fff'
+ );
+ },
+
+ get badgeBackgroundColor(): string | undefined {
+ if ( state.isHydrated ) {
+ if ( state.productCountColor ) {
+ return state.productCountColor;
+ }
+ const { ref } = getElement();
+ return getClosestColor( ref, 'color' ) || '#000';
+ }
+ },
+
+ get badgeTextColor(): string | undefined {
+ if ( state.isHydrated ) {
+ const { ref } = getElement();
+ return getClosestColor( ref, 'backgroundColor' ) || '#fff';
+ }
+ },
+ },
+
+ actions: {
+ openDrawer() {
+ if ( onCartClickBehaviour === 'navigate_to_checkout' ) {
+ window.location.href = checkoutUrl;
+ return;
+ }
+ const { ref } = getElement();
+ state.miniCartButtonRef = ref;
+ state.isOpen = true;
+ },
+
+ closeDrawer() {
+ state.isOpen = false;
+ state.miniCartButtonRef?.focus();
+ },
+
+ overlayCloseDrawer( e: MouseEvent ) {
+ // Only close the drawer if the overlay itself was clicked.
+ if ( e.target === e.currentTarget ) {
+ miniCartActions.closeDrawer();
+ }
+ },
+
+ handleOverlayKeydown: withSyncEvent( ( e: KeyboardEvent ) => {
+ if ( state.isOpen ) {
+ if ( e.key === 'Escape' ) {
+ miniCartActions.closeDrawer();
+ }
+
+ // Trap focus if it is an overlay (main menu).
+ if ( e.key === 'Tab' ) {
+ const { ref } = getElement();
+ const focusableElements = getFocusableElements( ref );
+ const activeElement = ref?.ownerDocument.activeElement;
+
+ if (
+ e.shiftKey &&
+ activeElement === focusableElements?.[ 0 ]
+ ) {
+ // Focus last element when shift+tab in the first one.
+ e.preventDefault();
+ focusableElements[
+ focusableElements.length - 1
+ ]?.focus();
+ } else if (
+ ! e.shiftKey &&
+ activeElement ===
+ focusableElements?.[
+ focusableElements.length - 1
+ ]
+ ) {
+ // Focus first element when tab in the last one.
+ e.preventDefault();
+ focusableElements?.[ 0 ]?.focus();
+ }
+ }
+ }
+ } ),
+ },
+
+ callbacks: {
+ *setupJQueryEventBridge() {
+ if ( ! ( 'jQuery' in window ) ) {
+ return;
+ }
+
+ // Make it so we can read jQuery events triggered by WC Core elements.
+ const removeJQueryAddedToCartEvent =
+ translateJQueryEventToNative(
+ 'added_to_cart',
+ 'wc-blocks_added_to_cart',
+ true
+ );
+ const removeJQueryRemovedFromCartEvent =
+ translateJQueryEventToNative(
+ 'removed_from_cart',
+ 'wc-blocks_removed_from_cart',
+ true
+ );
+
+ return () => {
+ removeJQueryAddedToCartEvent();
+ removeJQueryRemovedFromCartEvent();
+ };
+ },
+
+ disableScrollingOnBody() {
+ if ( state.isOpen ) {
+ Object.assign( document.body.style, {
+ overflow: 'hidden',
+ paddingRight:
+ window.innerWidth -
+ document.documentElement.clientWidth +
+ 'px',
+ } );
+ } else {
+ Object.assign( document.body.style, {
+ overflow: '',
+ paddingRight: 0,
+ } );
+ }
+ },
+
+ focusFirstElement() {
+ if ( state.isOpen ) {
+ const { ref } = getElement();
+ // Focus first element when the minicart is opened.
+ getFocusableElements( ref )[ 0 ]?.focus();
+ }
+ },
+ markAsHydrated() {
+ state.isHydrated = true;
+ },
+ },
+ },
+ { lock: universalLock }
+);
+
+/**
+ * Returns the raw API value for an item_data field. Used by both innerHTML
+ * callbacks and the cartItemDataAttr getter.
+ */
+function getItemDataRaw( field: 'name' | 'value' ): string {
+ const { itemData, dataProperty } = getContext< {
+ itemData: ItemData;
+ dataProperty: DataProperty;
+ } >();
+
+ const dataItemAttr =
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
+ itemData || cartItemState.cartItem[ dataProperty ]?.[ 0 ];
+
+ if ( ! dataItemAttr ) {
+ return '';
+ }
+
+ if ( field === 'name' ) {
+ return (
+ dataItemAttr.key ||
+ dataItemAttr.attribute ||
+ dataItemAttr.name ||
+ ''
);
+ }
- if ( ! miniCartButton || ! miniCartDrawerPlaceholderOverlay ) {
- // Markup is not correct, abort.
- return;
- }
+ return dataItemAttr.display || dataItemAttr.value || '';
+}
- const loadContents = () => {
- if ( ! wasLoadScriptsCalled ) {
- loadScripts();
- }
- document.body.removeEventListener(
- 'wc-blocks_added_to_cart',
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
- funcOnAddToCart
- );
- document.body.removeEventListener(
- 'wc-blocks_removed_from_cart',
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
- loadContentsWithRefresh
- );
- removeJQueryAddedToCartEvent();
- removeJQueryRemovedFromCartEvent();
- };
-
- const openDrawer = () => {
- miniCartBlock.dataset.isInitiallyOpen = 'true';
-
- miniCartDrawerPlaceholderOverlay.classList.add(
- 'wc-block-components-drawer__screen-overlay--with-slide-in'
- );
- miniCartDrawerPlaceholderOverlay.classList.remove(
- 'wc-block-components-drawer__screen-overlay--is-hidden'
- );
-
- loadContents();
- };
-
- const openDrawerWithRefresh = () => {
- openDrawer();
- };
-
- const loadContentsWithRefresh = () => {
- miniCartBlock.dataset.isInitiallyOpen = 'false';
- loadContents();
- };
-
- // Load the scripts if a device is touch-enabled. We don't get the mouseover or focus events on touch devices,
- // so the event listeners below won't work.
- if (
- 'ontouchstart' in window ||
- navigator.maxTouchPoints > 0 ||
- window.matchMedia( '(pointer:coarse)' ).matches
- ) {
- loadScripts();
- } else {
- miniCartButton.addEventListener( 'mouseover', loadScripts );
- miniCartButton.addEventListener( 'focus', loadScripts );
- }
+const { state: cartItemState } = store(
+ 'woocommerce/mini-cart-products-table-block',
+ {
+ state: {
+ // As a workaround for a bug in context of wp-each we use state to
+ // find the cart item. Where we need reactivity for the wp-each, use
+ // state.cartItem to get the cart item.
+ get cartItem() {
+ const {
+ cartItem: { id, key, variation },
+ } = getContext< CartItemContext >( 'woocommerce' );
- miniCartButton.addEventListener( 'click', openDrawer );
-
- // Open drawer if any of the mini cart block on the page
- // has 'open_drawer' behavior enabled.
- const funcOnAddToCart = shouldOpenDrawerOnAddToCart
- ? openDrawerWithRefresh
- : loadContentsWithRefresh;
-
- // There might be more than one Mini-Cart block in the page. Make sure
- // only one opens when adding a product to the cart.
- if ( i === 0 ) {
- document.body.addEventListener(
- 'wc-blocks_added_to_cart',
- funcOnAddToCart
- );
- document.body.addEventListener(
- 'wc-blocks_removed_from_cart',
- loadContentsWithRefresh
- );
- }
- } );
-} );
+ const cartItem = ( woocommerceState.findItemInCart( {
+ id,
+ key,
+ variation,
+ } ) || {} ) as CartItem;
+
+ cartItem.variation = cartItem.variation || [];
+ cartItem.item_data = cartItem.item_data || [];
+
+ return cartItem;
+ },
+
+ get currency(): Currency {
+ return normalizeCurrencyResponse(
+ woocommerceState.cart.totals,
+ currency as Currency
+ );
+ },
+
+ get lineItemDiscount(): string {
+ const { quantity, extensions } = cartItemState.cartItem;
+
+ const totalLineItemDiscount =
+ ( cartItemState.regularAmountSingle -
+ cartItemState.purchaseAmountSingle ) *
+ quantity;
+
+ const price = formatPriceWithCurrency(
+ totalLineItemDiscount,
+ cartItemState.currency
+ );
+
+ // TODO: Add deprecation notice urging to replace with a
+ // `data-wp-text` directive or an alternative solution.
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
+ ) {
+ const priceText =
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
+ {
+ filterName: 'saleBadgePriceFormat',
+ defaultValue: '<price/>',
+ extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ }
+ );
+
+ return priceText.replace( '<price/>', price );
+ }
+
+ return price;
+ },
+
+ get cartItemHasDiscount(): boolean {
+ const { raw_prices: rawPrices } = cartItemState.cartItem.prices;
+ return (
+ parseInt( rawPrices.regular_price, 10 ) >
+ parseInt( rawPrices.price, 10 )
+ );
+ },
+
+ get minimumReached(): boolean {
+ const {
+ quantity,
+ quantity_limits: { minimum, multiple_of: multipleOf = 1 },
+ } = cartItemState.cartItem;
+
+ return quantity - multipleOf < minimum;
+ },
+
+ get maximumReached(): boolean {
+ const {
+ quantity,
+ quantity_limits: { maximum, multiple_of: multipleOf = 1 },
+ } = cartItemState.cartItem;
+ return quantity + multipleOf > maximum;
+ },
+
+ get reduceQuantityLabel(): string {
+ return reduceQuantityLabel.replace(
+ '%s',
+ cartItemState.cartItemName
+ );
+ },
+
+ get increaseQuantityLabel(): string {
+ return increaseQuantityLabel.replace(
+ '%s',
+ cartItemState.cartItemName
+ );
+ },
+
+ get quantityDescriptionLabel(): string {
+ return quantityDescriptionLabel.replace(
+ '%s',
+ cartItemState.cartItemName
+ );
+ },
+
+ get removeFromCartLabel(): string {
+ return removeFromCartLabel.replace(
+ '%s',
+ cartItemState.cartItemName
+ );
+ },
+
+ get cartItemName(): string {
+ const txt = document.createElement( 'textarea' );
+ let { name } = cartItemState.cartItem;
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
+ ) {
+ name =
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
+ {
+ filterName: 'itemName',
+ defaultValue: name,
+ extensions: cartItemState.cartItem.extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ }
+ );
+ }
+ txt.innerHTML = name;
+ return txt.value;
+ },
+
+ get itemThumbnail(): string {
+ return (
+ cartItemState.cartItem.images[ 0 ]?.thumbnail ||
+ placeholderImgSrc ||
+ ''
+ );
+ },
+
+ get itemSrcset(): string {
+ return (
+ cartItemState.cartItem.images[ 0 ]?.thumbnail_srcset || ''
+ );
+ },
+
+ get itemSizes(): string {
+ return cartItemState.cartItem.images[ 0 ]?.thumbnail_srcset
+ ? '64px'
+ : '';
+ },
+
+ get priceWithoutDiscount(): string {
+ const { raw_prices: rawPrices } = cartItemState.cartItem.prices;
+ const priceWithoutDiscount = scalePrice( {
+ price: parseInt( rawPrices.regular_price, 10 ),
+ inputDecimals: rawPrices.precision,
+ outputDecimals: cartItemState.currency.minorUnit,
+ } );
+
+ return formatPriceWithCurrency(
+ priceWithoutDiscount,
+ cartItemState.currency
+ );
+ },
+
+ get regularAmountSingle(): number {
+ const { prices } = cartItemState.cartItem;
+
+ return scalePrice( {
+ price: parseInt( prices.raw_prices.regular_price, 10 ),
+ inputDecimals: prices.raw_prices.precision,
+ outputDecimals: cartItemState.currency.minorUnit,
+ } );
+ },
+
+ get purchaseAmountSingle(): number {
+ const { prices } = cartItemState.cartItem;
+
+ return scalePrice( {
+ price: parseInt( prices.raw_prices.price, 10 ),
+ inputDecimals: prices.raw_prices.precision,
+ outputDecimals: cartItemState.currency.minorUnit,
+ } );
+ },
+
+ get beforeItemPrice(): string | null {
+ // TODO: Add deprecation notice urging to replace with a
+ // `data-wp-text` directive or an alternative solution.
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
+ ) {
+ const priceText =
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
+ {
+ filterName: 'subtotalPriceFormat',
+ defaultValue: '<price/>',
+ extensions: cartItemState.cartItem.extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ }
+ );
+ return priceText.split( '<price/>' )[ 0 ];
+ }
+ return null;
+ },
+
+ get afterItemPrice(): string | null {
+ // TODO: Add deprecation notice urging to replace with a
+ // `data-wp-text` directive or an alternative solution.
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
+ ) {
+ const priceText =
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
+ {
+ filterName: 'subtotalPriceFormat',
+ defaultValue: '<price/>',
+ extensions: cartItemState.cartItem.extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ }
+ );
+ return priceText.split( '<price/>' )[ 1 ];
+ }
+ return null;
+ },
+
+ get itemPrice(): string {
+ const { raw_prices: rawPrices } = cartItemState.cartItem.prices;
+ const itemPrice = scalePrice( {
+ price: parseInt( rawPrices.price, 10 ),
+ inputDecimals: rawPrices.precision,
+ outputDecimals: cartItemState.currency.minorUnit,
+ } );
+
+ return formatPriceWithCurrency(
+ itemPrice,
+ cartItemState.currency
+ );
+ },
+
+ get lineItemTotal(): string {
+ const { totals } = cartItemState.cartItem;
+ const itemCurrency = cartItemState.currency;
+
+ const totalLinePrice = displayCartPriceIncludingTax
+ ? parseInt( totals.line_subtotal, 10 ) +
+ parseInt( totals.line_subtotal_tax, 10 )
+ : parseInt( totals.line_subtotal, 10 );
+
+ const price = formatPriceWithCurrency(
+ totalLinePrice,
+ itemCurrency
+ );
+
+ // TODO: Add deprecation notice urging to replace with a
+ // `data-wp-text` directive or an alternative solution.
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
+ ) {
+ const priceText =
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
+ {
+ filterName: 'cartItemPrice',
+ defaultValue: '<price/>',
+ extensions: cartItemState.cartItem.extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ }
+ );
+
+ return priceText.replace( '<price/>', price );
+ }
+
+ return price;
+ },
+
+ get isProductHiddenFromCatalog(): boolean {
+ const context = getContext< { isImageHidden: boolean } >();
+ const { catalog_visibility: catalogVisibility } =
+ cartItemState.cartItem;
+ return (
+ ( catalogVisibility === 'hidden' ||
+ catalogVisibility === 'search' ) &&
+ ! context.isImageHidden
+ );
+ },
+
+ get itemShowRemoveItemLink(): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( window.wc as any ).blocksCheckout.applyCheckoutFilter( {
+ filterName: 'showRemoveItemLink',
+ defaultValue: true,
+ extensions: cartItemState.cartItem.extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ } )
+ : true;
+ },
+
+ get cartItemDataAttr(): CartItemDataAttr | null {
+ const rawName = getItemDataRaw( 'name' );
+ const rawValue = getItemDataRaw( 'value' );
+
+ if ( ! rawName && ! rawValue ) {
+ return null;
+ }
+
+ const nameTxt = document.createElement( 'textarea' );
+ nameTxt.innerHTML = rawName;
+ const valueTxt = document.createElement( 'textarea' );
+ valueTxt.innerHTML = rawValue;
+
+ const { itemData, dataProperty } = getContext< {
+ itemData: ItemData;
+ dataProperty: DataProperty;
+ } >();
+ const dataItemAttr =
+ itemData || cartItemState.cartItem[ dataProperty ]?.[ 0 ];
+ const hiddenValue = dataItemAttr?.hidden;
+
+ return {
+ name: nameTxt.value ? nameTxt.value + ':' : '',
+ value: valueTxt.value,
+ className: `wc-block-components-product-details__${ nameTxt.value
+ .replace( /([a-z])([A-Z])/g, '$1-$2' )
+ .replace( /<[^>]*>/g, '' )
+ .replace( /[\s_&]+/g, '-' )
+ .toLowerCase() }`,
+ hidden:
+ hiddenValue === true ||
+ hiddenValue === 'true' ||
+ hiddenValue === '1' ||
+ hiddenValue === 1,
+ };
+ },
+
+ get cartItemDataAttrHidden(): boolean {
+ return (
+ cartItemState.cartItemDataAttr === null ||
+ !! cartItemState.cartItemDataAttr?.hidden
+ );
+ },
+
+ // Used to index cart item data attributes for wp-each-key.
+ get cartItemDataKey(): string {
+ const { itemData, dataProperty } = getContext< {
+ itemData: ItemData;
+ dataProperty: DataProperty;
+ } >();
+
+ const dataItemAttr =
+ itemData || cartItemState.cartItem[ dataProperty ]?.[ 0 ];
+
+ if ( ! dataItemAttr ) {
+ return '';
+ }
+
+ let name = '';
+ let value = '';
+
+ if ( dataProperty === 'variation' ) {
+ // For variations use raw_attribute as name and value as value
+ name = dataItemAttr.raw_attribute || '';
+ value = dataItemAttr.value || '';
+ } else {
+ // For item_data, use key/name and display/value
+ name = dataItemAttr.key || dataItemAttr.name || '';
+ value = dataItemAttr.display || dataItemAttr.value || '';
+ }
+
+ return `${ name }:${ value }`;
+ },
+
+ get shouldHideProductDetails(): boolean {
+ const { dataProperty } = getContext< {
+ dataProperty: DataProperty;
+ } >();
+ return cartItemState.cartItem[ dataProperty ].length === 0;
+ },
+
+ get isLastCartItemDataAttr(): boolean {
+ const { itemData, dataProperty } = getContext< {
+ itemData: ItemData;
+ dataProperty: DataProperty;
+ } >();
+
+ const items = cartItemState.cartItem[ dataProperty ];
+ if ( ! items || items.length === 0 ) {
+ return true;
+ }
+
+ // Filter out hidden items
+ const visibleItems = items.filter(
+ ( item: ItemData ) =>
+ ! (
+ item.hidden === true ||
+ item.hidden === 'true' ||
+ item.hidden === '1' ||
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ( item.hidden as any ) === 1
+ )
+ );
+
+ if ( visibleItems.length === 0 ) {
+ return true;
+ }
+
+ const lastItem = visibleItems[ visibleItems.length - 1 ];
+ return itemData === lastItem;
+ },
+ },
+
+ actions: {
+ overrideInvalidQuantity( e: InputEvent ) {
+ const input = e.target as HTMLInputElement;
+ const qty = input.value;
+
+ const { minimum, maximum } =
+ cartItemState.cartItem.quantity_limits;
+
+ const quantity = parseInt( qty, 10 );
+
+ if ( Number.isNaN( quantity ) ) {
+ input.value = cartItemState.cartItem.quantity.toString();
+ return;
+ }
+
+ let finalQuantity = quantity;
+
+ if ( quantity < minimum ) {
+ finalQuantity = minimum;
+ } else if ( quantity > maximum ) {
+ finalQuantity = maximum;
+ }
+
+ cartItemState.cartItem.quantity = finalQuantity;
+ },
+
+ *changeQuantity(): Generator< unknown, void > {
+ const variation = cartItemState.cartItem.variation.map(
+ ( { raw_attribute: rawAttribute, ...rest } ) => ( {
+ ...rest,
+ attribute: rawAttribute,
+ } )
+ );
+ yield actions.addCartItem( {
+ id: cartItemState.cartItem.id,
+ key: cartItemState.cartItem.key,
+ quantity: cartItemState.cartItem.quantity,
+ variation,
+ type: cartItemState.cartItem.type,
+ } );
+ },
+
+ *removeItemFromCart(): Generator< unknown, void > {
+ yield actions.removeCartItem( cartItemState.cartItem.key );
+ },
+
+ *incrementQuantity(): Generator< unknown, void > {
+ const { multiple_of: multipleOf = 1 } =
+ cartItemState.cartItem.quantity_limits;
+ const variation = cartItemState.cartItem.variation.map(
+ ( { raw_attribute: rawAttribute, ...rest } ) => ( {
+ ...rest,
+ attribute: rawAttribute,
+ } )
+ );
+ yield actions.addCartItem( {
+ id: cartItemState.cartItem.id,
+ key: cartItemState.cartItem.key,
+ quantity: cartItemState.cartItem.quantity + multipleOf,
+ variation,
+ type: cartItemState.cartItem.type,
+ } );
+ },
+
+ *decrementQuantity(): Generator< unknown, void > {
+ const { multiple_of: multipleOf = 1 } =
+ cartItemState.cartItem.quantity_limits;
+ const variation = cartItemState.cartItem.variation.map(
+ ( { raw_attribute: rawAttribute, ...rest } ) => ( {
+ ...rest,
+ attribute: rawAttribute,
+ } )
+ );
+ yield actions.addCartItem( {
+ id: cartItemState.cartItem.id,
+ key: cartItemState.cartItem.key,
+ quantity: cartItemState.cartItem.quantity - multipleOf,
+ variation,
+ type: cartItemState.cartItem.type,
+ } );
+ },
+
+ hideImage() {
+ const context = getContext< { isImageHidden: boolean } >();
+ context.isImageHidden = true;
+ },
+ },
+
+ callbacks: {
+ itemShortDescription() {
+ const { ref } = getElement();
+
+ if ( ref ) {
+ const innerEl = ref.querySelector(
+ '.wc-block-components-product-metadata__description'
+ );
+ const { short_description: shortDescription, description } =
+ cartItemState.cartItem;
+
+ if ( innerEl && ( shortDescription || description ) ) {
+ innerEl.innerHTML = trimWords(
+ shortDescription || description
+ );
+ }
+ }
+ },
+
+ itemDataNameInnerHTML() {
+ const { ref } = getElement();
+ const raw = getItemDataRaw( 'name' );
+ if ( ref && raw ) {
+ ref.innerHTML = trimWords( raw + ':' );
+ }
+ },
+
+ itemDataValueInnerHTML() {
+ const { ref } = getElement();
+ const raw = getItemDataRaw( 'value' );
+ if ( ref && raw ) {
+ ref.innerHTML = trimWords( raw );
+ }
+ },
+
+ filterCartItemClass() {
+ // TODO: Add deprecation notice urging to replace with a `data-wp-class` directive.
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const applyCheckoutFilter = ( window.wc as any )?.blocksCheckout
+ ?.applyCheckoutFilter;
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ const previouslyAppliedClasses = useRef< string[] >( [] );
+
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore -- It must run on every render.
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ useLayoutEffect( () => {
+ if ( applyCheckoutFilter ) {
+ const { ref } = getElement();
+
+ // Remove previously applied classes.
+ if ( ref ) {
+ ref.classList.remove(
+ ...previouslyAppliedClasses.current
+ );
+ }
+
+ const newClassesString = applyCheckoutFilter( {
+ filterName: 'cartItemClass',
+ defaultValue: '',
+ extensions: cartItemState.cartItem.extensions,
+ arg: {
+ context: 'cart',
+ cartItem: cartItemState.cartItem,
+ cart: woocommerceState.cart,
+ },
+ } );
+
+ // Apply new classes.
+ previouslyAppliedClasses.current = newClassesString
+ .split( ' ' )
+ .filter( Boolean );
+ if ( ref ) {
+ ref.classList.add(
+ ...previouslyAppliedClasses.current
+ );
+ }
+ }
+ } );
+ },
+ },
+ },
+ { lock: true }
+);
+
+store(
+ 'woocommerce/mini-cart-title-items-counter-block',
+ {
+ state: {
+ get itemsInCartText() {
+ const cartItemsCount = miniCartState.totalItemsInCart;
+
+ return itemsInCartTextTemplate.replace(
+ '%d',
+ cartItemsCount.toString()
+ );
+ },
+ },
+ },
+ { lock: true }
+);
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/iapi-frontend.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/iapi-frontend.ts
deleted file mode 100644
index 6237aadc042..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/iapi-frontend.ts
+++ /dev/null
@@ -1,1094 +0,0 @@
-/**
- * External dependencies
- */
-import {
- store,
- getContext,
- getConfig,
- getElement,
- useLayoutEffect,
- useRef,
- withSyncEvent,
-} from '@wordpress/interactivity';
-import '@woocommerce/stores/woocommerce/cart';
-import '@woocommerce/stores/store-notices';
-import type {
- Store as WooCommerce,
- WooCommerceConfig,
-} from '@woocommerce/stores/woocommerce/cart';
-
-/**
- * Internal dependencies
- */
-import {
- formatPriceWithCurrency,
- normalizeCurrencyResponse,
-} from '../../../../packages/prices/utils/currency';
-import { CartItem, Currency } from '../../types';
-import { translateJQueryEventToNative } from '../../base/stores/woocommerce/legacy-events';
-
-const universalLock =
- 'I acknowledge that using a private store means my plugin will inevitably break on the next store release.';
-
-const {
- currency,
- placeholderImgSrc,
- nonOptimisticProperties = [],
-} = getConfig( 'woocommerce' ) as WooCommerceConfig;
-const {
- onCartClickBehaviour,
- checkoutUrl,
- displayCartPriceIncludingTax,
- buttonAriaLabelTemplate,
-} = getConfig( 'woocommerce/mini-cart' );
-const {
- reduceQuantityLabel,
- increaseQuantityLabel,
- quantityDescriptionLabel,
- removeFromCartLabel,
-} = getConfig( 'woocommerce/mini-cart-products-table-block' );
-const { itemsInCartTextTemplate } = getConfig(
- 'woocommerce/mini-cart-title-items-counter-block'
-);
-
-type ScalePriceArgs = {
- price: number;
- inputDecimals: number;
- outputDecimals?: number;
-};
-
-const scalePrice = ( {
- price,
- inputDecimals,
- outputDecimals = 0,
-}: ScalePriceArgs ) => {
- const scaledPrice = price * Math.pow( 10, outputDecimals - inputDecimals );
- // Remove extra decimals.
- return Math.round( scaledPrice );
-};
-
-/**
- * Recursively traverses the DOM hierarchy to find the closest non-transparent color.
- *
- * @param element The starting element to check.
- * @param colorType Either 'color' (text) or 'backgroundColor'.
- * @return The computed color as an RGB string, or null if not found.
- */
-function getClosestColor(
- element: Element | null,
- colorType: 'color' | 'backgroundColor'
-): string | null {
- if ( ! element ) {
- return null;
- }
- const color = window.getComputedStyle( element )[ colorType ];
- if ( color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent' ) {
- const matches = color.match( /\d+/g );
- if ( ! matches || matches.length < 3 ) {
- return null;
- }
- const [ r, g, b ] = matches.slice( 0, 3 );
- return `rgb(${ r }, ${ g }, ${ b })`;
- }
- return getClosestColor( element.parentElement, colorType );
-}
-
-type MiniCart = {
- state: {
- isHydrated: boolean;
- isOpen: boolean;
- totalItemsInCart: number;
- formattedSubtotal: string;
- drawerOverlayClass: string;
- badgeIsVisible: boolean;
- cartIsEmpty: boolean;
- drawerRole: string | null;
- drawerTabIndex: string | null;
- buttonAriaLabel: string;
- shouldShowTaxLabel: boolean;
- miniCartButtonRef: HTMLElement | null;
- contentsBackgroundColor: string;
- badgeBackgroundColor: string | undefined;
- badgeTextColor: string | undefined;
- productCountColor: string;
- };
- actions: {
- openDrawer: () => void;
- closeDrawer: () => void;
- overlayCloseDrawer: ( e: MouseEvent ) => void;
- handleOverlayKeydown: ( e: KeyboardEvent ) => void;
- };
- callbacks: {
- markAsHydrated: () => void;
- setupJQueryEventBridge: () => void;
- disableScrollingOnBody: () => void;
- focusFirstElement: () => void;
- };
-};
-
-type MiniCartContext = {
- productCountVisibility: 'never' | 'always' | 'greater_than_zero';
-};
-
-type CartItemContext = {
- cartItem: CartItem;
-};
-
-type ItemData = {
- raw_attribute?: string | undefined;
- value?: string | undefined;
- display?: string;
- attribute?: string;
- hidden?: boolean | string | number;
-} & ( { key: string; name?: never } | { key?: never; name: string } );
-
-type CartItemDataAttr = {
- value: string;
- name: string;
- className: string;
- hidden: boolean;
-};
-
-type DataProperty = 'item_data' | 'variation';
-
-const trimWords = ( html: string, maxWords = 15 ): string => {
- const words = html.trim().split( /\s+/ );
- if ( words.length <= maxWords ) {
- return html;
- }
- return words.slice( 0, maxWords ).join( ' ' ) + '…';
-};
-
-const focusableSelectors = `
- a[href],
- input:not([disabled]):not([type="hidden"]):not([aria-hidden]),
- select:not([disabled]):not([aria-hidden]),
- textarea:not([disabled]):not([aria-hidden]),
- button:not([disabled]):not([aria-hidden]),
- [contenteditable],
- [tabindex]:not([tabindex^="-"])
-`;
-
-const getFocusableElements = ( container: HTMLElement | null ) =>
- container
- ? Array.from(
- container.querySelectorAll< HTMLElement >( focusableSelectors )
- ).filter( ( el ) => el.offsetParent !== null )
- : [];
-
-const { state: woocommerceState, actions } = store< WooCommerce >(
- 'woocommerce',
- {},
- { lock: universalLock }
-);
-
-const { state: miniCartState, actions: miniCartActions } = store< MiniCart >(
- 'woocommerce/mini-cart',
- {},
- { lock: true }
-);
-
-// Getters cannot access `state` during hydration if it is not declared
-// beforehand. This will be removed once the iAPI allows this case.
-const { state } = store< MiniCart >(
- 'woocommerce/mini-cart',
- {},
- { lock: universalLock }
-);
-
-store< MiniCart >(
- 'woocommerce/mini-cart',
- {
- state: {
- isHydrated: false,
- get totalItemsInCart() {
- if ( nonOptimisticProperties.includes( 'cart.items_count' ) ) {
- return woocommerceState.cart.items_count as number;
- }
- return woocommerceState.cart.items.reduce< number >(
- ( total, { quantity } ) => total + quantity,
- 0
- );
- },
-
- get formattedSubtotal(): string {
- if ( ! currency ) {
- return '';
- }
-
- const subtotal = displayCartPriceIncludingTax
- ? parseInt( woocommerceState.cart.totals.total_items, 10 ) +
- parseInt(
- woocommerceState.cart.totals.total_items_tax,
- 10
- )
- : parseInt( woocommerceState.cart.totals.total_items, 10 );
-
- const normalizedCurrency = normalizeCurrencyResponse(
- woocommerceState.cart.totals,
- currency
- );
-
- return formatPriceWithCurrency( subtotal, normalizedCurrency );
- },
-
- get drawerRole() {
- return state.isOpen ? 'dialog' : null;
- },
-
- get drawerTabIndex() {
- return state.isOpen ? '-1' : null;
- },
-
- get drawerOverlayClass() {
- const baseClasses =
- 'wc-block-components-drawer__screen-overlay wc-block-components-drawer__screen-overlay--with-slide-out';
- return state.isOpen
- ? `${ baseClasses } wc-block-components-drawer__screen-overlay--with-slide-in`
- : `${ baseClasses } wc-block-components-drawer__screen-overlay--is-hidden`;
- },
-
- get badgeIsVisible(): boolean {
- const cartHasItems = miniCartState.totalItemsInCart > 0;
- const { productCountVisibility } =
- getContext< MiniCartContext >();
-
- return (
- productCountVisibility === 'always' ||
- ( productCountVisibility === 'greater_than_zero' &&
- cartHasItems )
- );
- },
-
- get cartIsEmpty(): boolean {
- return miniCartState.totalItemsInCart === 0;
- },
-
- get buttonAriaLabel(): string {
- return buttonAriaLabelTemplate
- .replace( '%d', state.totalItemsInCart )
- .replace( '%1$d', state.totalItemsInCart )
- .replace( '%2$s', state.formattedSubtotal );
- },
-
- get shouldShowTaxLabel(): boolean {
- return (
- parseInt(
- woocommerceState.cart.totals.total_items_tax,
- 10
- ) > 0
- );
- },
-
- get contentsBackgroundColor(): string {
- return (
- getComputedStyle( document.body ).backgroundColor || '#fff'
- );
- },
-
- get badgeBackgroundColor(): string | undefined {
- if ( state.isHydrated ) {
- if ( state.productCountColor ) {
- return state.productCountColor;
- }
- const { ref } = getElement();
- return getClosestColor( ref, 'color' ) || '#000';
- }
- },
-
- get badgeTextColor(): string | undefined {
- if ( state.isHydrated ) {
- const { ref } = getElement();
- return getClosestColor( ref, 'backgroundColor' ) || '#fff';
- }
- },
- },
-
- actions: {
- openDrawer() {
- if ( onCartClickBehaviour === 'navigate_to_checkout' ) {
- window.location.href = checkoutUrl;
- return;
- }
- const { ref } = getElement();
- state.miniCartButtonRef = ref;
- state.isOpen = true;
- },
-
- closeDrawer() {
- state.isOpen = false;
- state.miniCartButtonRef?.focus();
- },
-
- overlayCloseDrawer( e: MouseEvent ) {
- // Only close the drawer if the overlay itself was clicked.
- if ( e.target === e.currentTarget ) {
- miniCartActions.closeDrawer();
- }
- },
-
- handleOverlayKeydown: withSyncEvent( ( e: KeyboardEvent ) => {
- if ( state.isOpen ) {
- if ( e.key === 'Escape' ) {
- miniCartActions.closeDrawer();
- }
-
- // Trap focus if it is an overlay (main menu).
- if ( e.key === 'Tab' ) {
- const { ref } = getElement();
- const focusableElements = getFocusableElements( ref );
- const activeElement = ref.ownerDocument.activeElement;
- if (
- e.shiftKey &&
- activeElement === focusableElements?.[ 0 ]
- ) {
- // Focus last element when shift+tab in the first one.
- e.preventDefault();
- focusableElements[
- focusableElements.length - 1
- ]?.focus();
- } else if (
- ! e.shiftKey &&
- activeElement ===
- focusableElements?.[
- focusableElements.length - 1
- ]
- ) {
- // Focus first element when tab in the last one.
- e.preventDefault();
- focusableElements?.[ 0 ]?.focus();
- }
- }
- }
- } ),
- },
-
- callbacks: {
- *setupJQueryEventBridge() {
- if ( ! ( 'jQuery' in window ) ) {
- return;
- }
-
- // Make it so we can read jQuery events triggered by WC Core elements.
- const removeJQueryAddedToCartEvent =
- translateJQueryEventToNative(
- 'added_to_cart',
- 'wc-blocks_added_to_cart',
- true
- );
- const removeJQueryRemovedFromCartEvent =
- translateJQueryEventToNative(
- 'removed_from_cart',
- 'wc-blocks_removed_from_cart',
- true
- );
-
- return () => {
- removeJQueryAddedToCartEvent();
- removeJQueryRemovedFromCartEvent();
- };
- },
-
- disableScrollingOnBody() {
- if ( state.isOpen ) {
- Object.assign( document.body.style, {
- overflow: 'hidden',
- paddingRight:
- window.innerWidth -
- document.documentElement.clientWidth +
- 'px',
- } );
- } else {
- Object.assign( document.body.style, {
- overflow: '',
- paddingRight: 0,
- } );
- }
- },
-
- focusFirstElement() {
- if ( state.isOpen ) {
- const { ref } = getElement();
- // Focus first element when the minicart is opened.
- getFocusableElements( ref )[ 0 ]?.focus();
- }
- },
- markAsHydrated() {
- state.isHydrated = true;
- },
- },
- },
- { lock: universalLock }
-);
-
-/**
- * Returns the raw API value for an item_data field. Used by both innerHTML
- * callbacks and the cartItemDataAttr getter.
- */
-function getItemDataRaw( field: 'name' | 'value' ): string {
- const { itemData, dataProperty } = getContext< {
- itemData: ItemData;
- dataProperty: DataProperty;
- } >();
-
- const dataItemAttr =
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
- itemData || cartItemState.cartItem[ dataProperty ]?.[ 0 ];
-
- if ( ! dataItemAttr ) {
- return '';
- }
-
- if ( field === 'name' ) {
- return (
- dataItemAttr.key ||
- dataItemAttr.attribute ||
- dataItemAttr.name ||
- ''
- );
- }
-
- return dataItemAttr.display || dataItemAttr.value || '';
-}
-
-const { state: cartItemState } = store(
- 'woocommerce/mini-cart-products-table-block',
- {
- state: {
- // As a workaround for a bug in context of wp-each we use state to
- // find the cart item. Where we need reactivity for the wp-each, use
- // state.cartItem to get the cart item.
- get cartItem() {
- const {
- cartItem: { id, key, variation },
- } = getContext< CartItemContext >( 'woocommerce' );
-
- const cartItem = ( woocommerceState.findItemInCart( {
- id,
- key,
- variation,
- } ) || {} ) as CartItem;
-
- cartItem.variation = cartItem.variation || [];
- cartItem.item_data = cartItem.item_data || [];
-
- return cartItem;
- },
-
- get currency(): Currency {
- return normalizeCurrencyResponse(
- woocommerceState.cart.totals,
- currency as Currency
- );
- },
-
- get lineItemDiscount(): string {
- const { quantity, extensions } = cartItemState.cartItem;
-
- const totalLineItemDiscount =
- ( cartItemState.regularAmountSingle -
- cartItemState.purchaseAmountSingle ) *
- quantity;
-
- const price = formatPriceWithCurrency(
- totalLineItemDiscount,
- cartItemState.currency
- );
-
- // TODO: Add deprecation notice urging to replace with a
- // `data-wp-text` directive or an alternative solution.
- if (
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
- ) {
- const priceText =
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
- {
- filterName: 'saleBadgePriceFormat',
- defaultValue: '<price/>',
- extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- }
- );
-
- return priceText.replace( '<price/>', price );
- }
-
- return price;
- },
-
- get cartItemHasDiscount(): boolean {
- const { raw_prices: rawPrices } = cartItemState.cartItem.prices;
- return (
- parseInt( rawPrices.regular_price, 10 ) >
- parseInt( rawPrices.price, 10 )
- );
- },
-
- get minimumReached(): boolean {
- const {
- quantity,
- quantity_limits: { minimum, multiple_of: multipleOf = 1 },
- } = cartItemState.cartItem;
-
- return quantity - multipleOf < minimum;
- },
-
- get maximumReached(): boolean {
- const {
- quantity,
- quantity_limits: { maximum, multiple_of: multipleOf = 1 },
- } = cartItemState.cartItem;
- return quantity + multipleOf > maximum;
- },
-
- get reduceQuantityLabel(): string {
- return reduceQuantityLabel.replace(
- '%s',
- cartItemState.cartItemName
- );
- },
-
- get increaseQuantityLabel(): string {
- return increaseQuantityLabel.replace(
- '%s',
- cartItemState.cartItemName
- );
- },
-
- get quantityDescriptionLabel(): string {
- return quantityDescriptionLabel.replace(
- '%s',
- cartItemState.cartItemName
- );
- },
-
- get removeFromCartLabel(): string {
- return removeFromCartLabel.replace(
- '%s',
- cartItemState.cartItemName
- );
- },
-
- get cartItemName(): string {
- const txt = document.createElement( 'textarea' );
- let { name } = cartItemState.cartItem;
- if (
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
- ) {
- name =
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
- {
- filterName: 'itemName',
- defaultValue: name,
- extensions: cartItemState.cartItem.extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- }
- );
- }
- txt.innerHTML = name;
- return txt.value;
- },
-
- get itemThumbnail(): string {
- return (
- cartItemState.cartItem.images[ 0 ]?.thumbnail ||
- placeholderImgSrc ||
- ''
- );
- },
-
- get itemSrcset(): string {
- return (
- cartItemState.cartItem.images[ 0 ]?.thumbnail_srcset || ''
- );
- },
-
- get itemSizes(): string {
- return cartItemState.cartItem.images[ 0 ]?.thumbnail_srcset
- ? '64px'
- : '';
- },
-
- get priceWithoutDiscount(): string {
- const { raw_prices: rawPrices } = cartItemState.cartItem.prices;
- const priceWithoutDiscount = scalePrice( {
- price: parseInt( rawPrices.regular_price, 10 ),
- inputDecimals: rawPrices.precision,
- outputDecimals: cartItemState.currency.minorUnit,
- } );
-
- return formatPriceWithCurrency(
- priceWithoutDiscount,
- cartItemState.currency
- );
- },
-
- get regularAmountSingle(): number {
- const { prices } = cartItemState.cartItem;
-
- return scalePrice( {
- price: parseInt( prices.raw_prices.regular_price, 10 ),
- inputDecimals: prices.raw_prices.precision,
- outputDecimals: cartItemState.currency.minorUnit,
- } );
- },
-
- get purchaseAmountSingle(): number {
- const { prices } = cartItemState.cartItem;
-
- return scalePrice( {
- price: parseInt( prices.raw_prices.price, 10 ),
- inputDecimals: prices.raw_prices.precision,
- outputDecimals: cartItemState.currency.minorUnit,
- } );
- },
-
- get beforeItemPrice(): string | null {
- // TODO: Add deprecation notice urging to replace with a
- // `data-wp-text` directive or an alternative solution.
- if (
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
- ) {
- const priceText =
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
- {
- filterName: 'subtotalPriceFormat',
- defaultValue: '<price/>',
- extensions: cartItemState.cartItem.extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- }
- );
- return priceText.split( '<price/>' )[ 0 ];
- }
- return null;
- },
-
- get afterItemPrice(): string | null {
- // TODO: Add deprecation notice urging to replace with a
- // `data-wp-text` directive or an alternative solution.
- if (
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
- ) {
- const priceText =
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
- {
- filterName: 'subtotalPriceFormat',
- defaultValue: '<price/>',
- extensions: cartItemState.cartItem.extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- }
- );
- return priceText.split( '<price/>' )[ 1 ];
- }
- return null;
- },
-
- get itemPrice(): string {
- const { raw_prices: rawPrices } = cartItemState.cartItem.prices;
- const itemPrice = scalePrice( {
- price: parseInt( rawPrices.price, 10 ),
- inputDecimals: rawPrices.precision,
- outputDecimals: cartItemState.currency.minorUnit,
- } );
-
- return formatPriceWithCurrency(
- itemPrice,
- cartItemState.currency
- );
- },
-
- get lineItemTotal(): string {
- const { totals } = cartItemState.cartItem;
- const itemCurrency = cartItemState.currency;
-
- const totalLinePrice = displayCartPriceIncludingTax
- ? parseInt( totals.line_subtotal, 10 ) +
- parseInt( totals.line_subtotal_tax, 10 )
- : parseInt( totals.line_subtotal, 10 );
-
- const price = formatPriceWithCurrency(
- totalLinePrice,
- itemCurrency
- );
-
- // TODO: Add deprecation notice urging to replace with a
- // `data-wp-text` directive or an alternative solution.
- if (
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
- ) {
- const priceText =
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any ).blocksCheckout.applyCheckoutFilter(
- {
- filterName: 'cartItemPrice',
- defaultValue: '<price/>',
- extensions: cartItemState.cartItem.extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- }
- );
-
- return priceText.replace( '<price/>', price );
- }
-
- return price;
- },
-
- get isProductHiddenFromCatalog(): boolean {
- const context = getContext< { isImageHidden: boolean } >();
- const { catalog_visibility: catalogVisibility } =
- cartItemState.cartItem;
- return (
- ( catalogVisibility === 'hidden' ||
- catalogVisibility === 'search' ) &&
- ! context.isImageHidden
- );
- },
-
- get itemShowRemoveItemLink(): boolean {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return ( window.wc as any )?.blocksCheckout?.applyCheckoutFilter
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( window.wc as any ).blocksCheckout.applyCheckoutFilter( {
- filterName: 'showRemoveItemLink',
- defaultValue: true,
- extensions: cartItemState.cartItem.extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- } )
- : true;
- },
-
- get cartItemDataAttr(): CartItemDataAttr | null {
- const rawName = getItemDataRaw( 'name' );
- const rawValue = getItemDataRaw( 'value' );
-
- if ( ! rawName && ! rawValue ) {
- return null;
- }
-
- const nameTxt = document.createElement( 'textarea' );
- nameTxt.innerHTML = rawName;
- const valueTxt = document.createElement( 'textarea' );
- valueTxt.innerHTML = rawValue;
-
- const { itemData, dataProperty } = getContext< {
- itemData: ItemData;
- dataProperty: DataProperty;
- } >();
- const dataItemAttr =
- itemData || cartItemState.cartItem[ dataProperty ]?.[ 0 ];
- const hiddenValue = dataItemAttr?.hidden;
-
- return {
- name: nameTxt.value ? nameTxt.value + ':' : '',
- value: valueTxt.value,
- className: `wc-block-components-product-details__${ nameTxt.value
- .replace( /([a-z])([A-Z])/g, '$1-$2' )
- .replace( /<[^>]*>/g, '' )
- .replace( /[\s_&]+/g, '-' )
- .toLowerCase() }`,
- hidden:
- hiddenValue === true ||
- hiddenValue === 'true' ||
- hiddenValue === '1' ||
- hiddenValue === 1,
- };
- },
-
- get cartItemDataAttrHidden(): boolean {
- return (
- cartItemState.cartItemDataAttr === null ||
- !! cartItemState.cartItemDataAttr?.hidden
- );
- },
-
- // Used to index cart item data attributes for wp-each-key.
- get cartItemDataKey(): string {
- const { itemData, dataProperty } = getContext< {
- itemData: ItemData;
- dataProperty: DataProperty;
- } >();
-
- const dataItemAttr =
- itemData || cartItemState.cartItem[ dataProperty ]?.[ 0 ];
-
- if ( ! dataItemAttr ) {
- return '';
- }
-
- let name = '';
- let value = '';
-
- if ( dataProperty === 'variation' ) {
- // For variations use raw_attribute as name and value as value
- name = dataItemAttr.raw_attribute || '';
- value = dataItemAttr.value || '';
- } else {
- // For item_data, use key/name and display/value
- name = dataItemAttr.key || dataItemAttr.name || '';
- value = dataItemAttr.display || dataItemAttr.value || '';
- }
-
- return `${ name }:${ value }`;
- },
-
- get shouldHideProductDetails(): boolean {
- const { dataProperty } = getContext< {
- dataProperty: DataProperty;
- } >();
- return cartItemState.cartItem[ dataProperty ].length === 0;
- },
-
- get isLastCartItemDataAttr(): boolean {
- const { itemData, dataProperty } = getContext< {
- itemData: ItemData;
- dataProperty: DataProperty;
- } >();
-
- const items = cartItemState.cartItem[ dataProperty ];
- if ( ! items || items.length === 0 ) {
- return true;
- }
-
- // Filter out hidden items
- const visibleItems = items.filter(
- ( item: ItemData ) =>
- ! (
- item.hidden === true ||
- item.hidden === 'true' ||
- item.hidden === '1' ||
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ( item.hidden as any ) === 1
- )
- );
-
- if ( visibleItems.length === 0 ) {
- return true;
- }
-
- const lastItem = visibleItems[ visibleItems.length - 1 ];
- return itemData === lastItem;
- },
- },
-
- actions: {
- overrideInvalidQuantity( e: InputEvent ) {
- const input = e.target as HTMLInputElement;
- const qty = input.value;
-
- const { minimum, maximum } =
- cartItemState.cartItem.quantity_limits;
-
- const quantity = parseInt( qty, 10 );
-
- if ( Number.isNaN( quantity ) ) {
- input.value = cartItemState.cartItem.quantity.toString();
- return;
- }
-
- let finalQuantity = quantity;
-
- if ( quantity < minimum ) {
- finalQuantity = minimum;
- } else if ( quantity > maximum ) {
- finalQuantity = maximum;
- }
-
- cartItemState.cartItem.quantity = finalQuantity;
- },
-
- *changeQuantity(): Generator< unknown, void > {
- const variation = cartItemState.cartItem.variation.map(
- ( { raw_attribute: rawAttribute, ...rest } ) => ( {
- ...rest,
- attribute: rawAttribute,
- } )
- );
- yield actions.addCartItem( {
- id: cartItemState.cartItem.id,
- key: cartItemState.cartItem.key,
- quantity: cartItemState.cartItem.quantity,
- variation,
- type: cartItemState.cartItem.type,
- } );
- },
-
- *removeItemFromCart(): Generator< unknown, void > {
- yield actions.removeCartItem( cartItemState.cartItem.key );
- },
-
- *incrementQuantity(): Generator< unknown, void > {
- const { multiple_of: multipleOf = 1 } =
- cartItemState.cartItem.quantity_limits;
- const variation = cartItemState.cartItem.variation.map(
- ( { raw_attribute: rawAttribute, ...rest } ) => ( {
- ...rest,
- attribute: rawAttribute,
- } )
- );
- yield actions.addCartItem( {
- id: cartItemState.cartItem.id,
- key: cartItemState.cartItem.key,
- quantity: cartItemState.cartItem.quantity + multipleOf,
- variation,
- type: cartItemState.cartItem.type,
- } );
- },
-
- *decrementQuantity(): Generator< unknown, void > {
- const { multiple_of: multipleOf = 1 } =
- cartItemState.cartItem.quantity_limits;
- const variation = cartItemState.cartItem.variation.map(
- ( { raw_attribute: rawAttribute, ...rest } ) => ( {
- ...rest,
- attribute: rawAttribute,
- } )
- );
- yield actions.addCartItem( {
- id: cartItemState.cartItem.id,
- key: cartItemState.cartItem.key,
- quantity: cartItemState.cartItem.quantity - multipleOf,
- variation,
- type: cartItemState.cartItem.type,
- } );
- },
-
- hideImage() {
- const context = getContext< { isImageHidden: boolean } >();
- context.isImageHidden = true;
- },
- },
-
- callbacks: {
- itemShortDescription() {
- const { ref } = getElement();
-
- if ( ref ) {
- const innerEl = ref.querySelector(
- '.wc-block-components-product-metadata__description'
- );
- const { short_description: shortDescription, description } =
- cartItemState.cartItem;
-
- if ( innerEl && ( shortDescription || description ) ) {
- innerEl.innerHTML = trimWords(
- shortDescription || description
- );
- }
- }
- },
-
- itemDataNameInnerHTML() {
- const { ref } = getElement();
- const raw = getItemDataRaw( 'name' );
- if ( ref && raw ) {
- ref.innerHTML = trimWords( raw + ':' );
- }
- },
-
- itemDataValueInnerHTML() {
- const { ref } = getElement();
- const raw = getItemDataRaw( 'value' );
- if ( ref && raw ) {
- ref.innerHTML = trimWords( raw );
- }
- },
-
- filterCartItemClass() {
- // TODO: Add deprecation notice urging to replace with a `data-wp-class` directive.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const applyCheckoutFilter = ( window.wc as any )?.blocksCheckout
- ?.applyCheckoutFilter;
- // eslint-disable-next-line react-hooks/rules-of-hooks
- const previouslyAppliedClasses = useRef< string[] >( [] );
-
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore -- It must run on every render.
- // eslint-disable-next-line react-hooks/rules-of-hooks
- useLayoutEffect( () => {
- if ( applyCheckoutFilter ) {
- const { ref } = getElement();
-
- // Remove previously applied classes.
- if ( ref ) {
- ref.classList.remove(
- ...previouslyAppliedClasses.current
- );
- }
-
- const newClassesString = applyCheckoutFilter( {
- filterName: 'cartItemClass',
- defaultValue: '',
- extensions: cartItemState.cartItem.extensions,
- arg: {
- context: 'cart',
- cartItem: cartItemState.cartItem,
- cart: woocommerceState.cart,
- },
- } );
-
- // Apply new classes.
- previouslyAppliedClasses.current = newClassesString
- .split( ' ' )
- .filter( Boolean );
- if ( ref ) {
- ref.classList.add(
- ...previouslyAppliedClasses.current
- );
- }
- }
- } );
- },
- },
- },
- { lock: true }
-);
-
-store(
- 'woocommerce/mini-cart-title-items-counter-block',
- {
- state: {
- get itemsInCartText() {
- const cartItemsCount = miniCartState.totalItemsInCart;
-
- return itemsInCartTextTemplate.replace(
- '%d',
- cartItemsCount.toString()
- );
- },
- },
- },
- { lock: true }
-);
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/block.tsx
deleted file mode 100644
index 6e8fa6675fe..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/block.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * External dependencies
- */
-import { DrawerCloseButton } from '@woocommerce/base-components/drawer';
-import { CartEventsProvider } from '@woocommerce/base-context';
-
-/**
- * Internal dependencies
- */
-import './inner-blocks/register-components';
-
-type MiniCartContentsBlockProps = {
- attributes: Record< string, unknown >;
- children: JSX.Element | JSX.Element[];
-};
-
-export const MiniCartContentsBlock = (
- props: MiniCartContentsBlockProps
-): JSX.Element => {
- const { children } = props;
-
- return (
- <>
- <CartEventsProvider>
- <DrawerCloseButton />
- { children }
- </CartEventsProvider>
- </>
- );
-};
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/empty-mini-cart-contents-block/frontend.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/empty-mini-cart-contents-block/frontend.tsx
deleted file mode 100644
index 025747f7a2a..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/empty-mini-cart-contents-block/frontend.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * External dependencies
- */
-import { useStoreCart } from '@woocommerce/base-context/hooks';
-import { useEffect, useRef } from '@wordpress/element';
-
-/**
- * Internal dependencies
- */
-
-type EmptyMiniCartContentsBlockProps = {
- children: JSX.Element | JSX.Element[];
- className: string;
-};
-
-const EmptyMiniCartContentsBlock = ( {
- children,
- className,
-}: EmptyMiniCartContentsBlockProps ): JSX.Element | null => {
- const { cartItems, cartIsLoading } = useStoreCart();
-
- const elementRef = useRef< HTMLDivElement >( null );
-
- useEffect( () => {
- if ( cartItems.length === 0 && ! cartIsLoading ) {
- elementRef.current?.focus();
- }
- }, [ cartItems, cartIsLoading ] );
-
- if ( cartIsLoading || cartItems.length > 0 ) {
- return null;
- }
-
- return (
- <div tabIndex={ -1 } ref={ elementRef } className={ className }>
- <div className="wc-block-mini-cart__empty-cart-wrapper">
- { children }
- </div>
- </div>
- );
-};
-
-export default EmptyMiniCartContentsBlock;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/filled-mini-cart-contents-block/frontend.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/filled-mini-cart-contents-block/frontend.tsx
deleted file mode 100644
index 3662e9b354f..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/filled-mini-cart-contents-block/frontend.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * External dependencies
- */
-import { StoreNoticesContainer } from '@woocommerce/blocks-components';
-import { useStoreCart } from '@woocommerce/base-context/hooks';
-
-type FilledMiniCartContentsBlockProps = {
- children: JSX.Element;
- className: string;
-};
-
-const FilledMiniCartContentsBlock = ( {
- children,
- className,
-}: FilledMiniCartContentsBlockProps ): JSX.Element | null => {
- const { cartItems } = useStoreCart();
-
- if ( cartItems.length === 0 ) {
- return null;
- }
-
- return (
- <div className={ className }>
- <StoreNoticesContainer context="wc/cart" />
- { children }
- </div>
- );
-};
-
-export default FilledMiniCartContentsBlock;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-cart-button-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-cart-button-block/block.tsx
deleted file mode 100644
index 563d5cdca7d..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-cart-button-block/block.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * External dependencies
- */
-import { CART_URL } from '@woocommerce/block-settings';
-import Button from '@woocommerce/base-components/button';
-import clsx from 'clsx';
-import { useStyleProps } from '@woocommerce/base-hooks';
-
-/**
- * Internal dependencies
- */
-import { defaultCartButtonLabel } from './constants';
-import { getVariant } from '../utils';
-
-type MiniCartCartButtonBlockProps = {
- cartButtonLabel?: string;
- className?: string;
- style?: string;
-};
-
-const Block = ( {
- className,
- cartButtonLabel,
- style,
-}: MiniCartCartButtonBlockProps ): JSX.Element | null => {
- const styleProps = useStyleProps( { style } );
-
- if ( ! CART_URL ) {
- return null;
- }
-
- return (
- <Button
- className={ clsx(
- className,
- styleProps.className,
- 'wc-block-mini-cart__footer-cart'
- ) }
- style={ styleProps.style }
- href={ CART_URL }
- variant={ getVariant( className, 'outlined' ) }
- >
- { cartButtonLabel || defaultCartButtonLabel }
- </Button>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-checkout-button-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-checkout-button-block/block.tsx
deleted file mode 100644
index da2a28adfc0..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-checkout-button-block/block.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * External dependencies
- */
-import { CHECKOUT_URL } from '@woocommerce/block-settings';
-import Button from '@woocommerce/base-components/button';
-import clsx from 'clsx';
-import { useStyleProps } from '@woocommerce/base-hooks';
-import { useCartEventsContext } from '@woocommerce/base-context';
-import { isErrorResponse } from '@woocommerce/types';
-
-/**
- * Internal dependencies
- */
-import { defaultCheckoutButtonLabel } from './constants';
-import { getVariant } from '../utils';
-
-type MiniCartCheckoutButtonBlockProps = {
- checkoutButtonLabel?: string;
- className?: string;
- style?: string;
-};
-
-const Block = ( {
- className,
- checkoutButtonLabel,
- style,
-}: MiniCartCheckoutButtonBlockProps ): JSX.Element | null => {
- const styleProps = useStyleProps( { style } );
- const { dispatchOnProceedToCheckout } = useCartEventsContext();
-
- if ( ! CHECKOUT_URL ) {
- return null;
- }
-
- return (
- <Button
- className={ clsx(
- className,
- styleProps.className,
- 'wc-block-mini-cart__footer-checkout'
- ) }
- variant={ getVariant( className, 'contained' ) }
- style={ styleProps.style }
- href={ CHECKOUT_URL }
- onClick={ ( e ) => {
- dispatchOnProceedToCheckout().then( ( observerResponses ) => {
- if ( observerResponses.some( isErrorResponse ) ) {
- e.preventDefault();
- }
- } );
- } }
- >
- { checkoutButtonLabel || defaultCheckoutButtonLabel }
- </Button>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-checkout-button-block/test/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-checkout-button-block/test/block.tsx
deleted file mode 100644
index 6c0af48a58e..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-checkout-button-block/test/block.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * External dependencies
- */
-import {
- CartEventsProvider,
- useCartEventsContext,
-} from '@woocommerce/base-context';
-import { useEffect } from '@wordpress/element';
-import { render, screen, waitFor } from '@testing-library/react';
-
-/**
- * Internal dependencies
- */
-import Block from '../block';
-
-describe( 'Mini Cart Checkout Button Block', () => {
- it( 'dispatches the onProceedToCheckout event when the button is clicked', async () => {
- const mockObserver = jest.fn().mockReturnValue( { type: 'error' } );
- const MockObserverComponent = () => {
- const { onProceedToCheckout } = useCartEventsContext();
- useEffect( () => {
- return onProceedToCheckout( mockObserver );
- }, [ onProceedToCheckout ] );
- return <div>Mock observer</div>;
- };
-
- render(
- <CartEventsProvider>
- <div>
- <MockObserverComponent />
- <Block
- checkoutButtonLabel={ 'Proceed to Checkout' }
- className="test-block"
- />
- </div>
- </CartEventsProvider>
- );
- expect( screen.getByText( 'Mock observer' ) ).toBeInTheDocument();
- const button = screen.getByText( 'Proceed to Checkout' );
-
- // Forcibly set the button URL to # to prevent JSDOM error: `["Error: Not implemented: navigation (except hash changes)`
- button.closest( 'a' )?.removeAttribute( 'href' );
- button.click();
- await waitFor( () => {
- expect( mockObserver ).toHaveBeenCalled();
- } );
- } );
-} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-footer-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-footer-block/block.tsx
deleted file mode 100644
index cd640a3e67a..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-footer-block/block.tsx
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * External dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { TotalsItem } from '@woocommerce/blocks-components';
-import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
-import {
- usePaymentMethods,
- useStoreCart,
-} from '@woocommerce/base-context/hooks';
-import PaymentMethodIcons from '@woocommerce/base-components/cart-checkout/payment-method-icons';
-import { getIconsFromPaymentMethods } from '@woocommerce/base-utils';
-import { getSetting } from '@woocommerce/settings';
-import { PaymentEventsProvider } from '@woocommerce/base-context';
-import clsx from 'clsx';
-
-/**
- * Internal dependencies
- */
-import CartButton from '../mini-cart-cart-button-block/block';
-import CheckoutButton from '../mini-cart-checkout-button-block/block';
-import { hasChildren, getTotalsItemDescription } from '../utils';
-
-const PaymentMethodIconsElement = (): JSX.Element => {
- const { paymentMethods } = usePaymentMethods();
- return (
- <PaymentMethodIcons
- icons={ getIconsFromPaymentMethods( paymentMethods ) }
- />
- );
-};
-
-interface Props {
- children: JSX.Element[] | undefined;
- className?: string;
- cartButtonLabel: string;
- checkoutButtonLabel: string;
-}
-
-const Block = ( {
- children,
- className,
- cartButtonLabel,
- checkoutButtonLabel,
-}: Props ): JSX.Element | null => {
- const { cartTotals } = useStoreCart();
- const subTotal = getSetting( 'displayCartPricesIncludingTax', false )
- ? parseInt( cartTotals.total_items, 10 ) +
- parseInt( cartTotals.total_items_tax, 10 )
- : parseInt( cartTotals.total_items, 10 );
-
- // If the block is hidden, then the children will be undefined.
- // In this case, we return null to prevent the fallback for the legacy template
- if ( ! children ) {
- return null;
- }
-
- // The `Cart` and `Checkout` buttons were converted to inner blocks, but we still need to render the buttons
- // for themes that have the old `mini-cart.html` template. So we check if there are any inner blocks (buttons) and
- // if not, render the buttons.
- const hasButtons = hasChildren( children );
-
- return (
- <div className={ clsx( className, 'wc-block-mini-cart__footer' ) }>
- <TotalsItem
- className="wc-block-mini-cart__footer-subtotal"
- currency={ getCurrencyFromPriceResponse( cartTotals ) }
- label={ __( 'Subtotal', 'woocommerce' ) }
- value={ subTotal }
- description={ getTotalsItemDescription() }
- />
- <div className="wc-block-mini-cart__footer-actions">
- { hasButtons ? (
- children
- ) : (
- <>
- <CartButton cartButtonLabel={ cartButtonLabel } />
- <CheckoutButton
- checkoutButtonLabel={ checkoutButtonLabel }
- />
- </>
- ) }
- </div>
- <PaymentEventsProvider>
- <PaymentMethodIconsElement />
- </PaymentEventsProvider>
- </div>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-items-block/frontend.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-items-block/frontend.tsx
deleted file mode 100644
index 0fe3344c948..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-items-block/frontend.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * External dependencies
- */
-import clsx from 'clsx';
-
-type MiniCartItemsBlockProps = {
- children: JSX.Element;
- className: string;
-};
-
-const Block = ( {
- children,
- className,
-}: MiniCartItemsBlockProps ): JSX.Element => {
- return (
- <div
- className={ clsx( className, 'wc-block-mini-cart__items' ) }
- tabIndex={ -1 }
- >
- { children }
- </div>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/block.tsx
deleted file mode 100644
index c68ee952140..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-shopping-button-block/block.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * External dependencies
- */
-import { SHOP_URL } from '@woocommerce/block-settings';
-import Button from '@woocommerce/base-components/button';
-import { useStyleProps } from '@woocommerce/base-hooks';
-import clsx from 'clsx';
-
-/**
- * Internal dependencies
- */
-import { defaultStartShoppingButtonLabel } from './constants';
-import { getVariant } from '../utils';
-
-type MiniCartShoppingButtonBlockProps = {
- className: string;
- startShoppingButtonLabel: string;
- style?: string;
- textColor?: string;
- backgroundColor?: string;
-};
-
-const Block = ( {
- className,
- startShoppingButtonLabel,
- style,
- textColor,
- backgroundColor,
-}: MiniCartShoppingButtonBlockProps ): JSX.Element | null => {
- const styleProps = useStyleProps( {
- style,
- textColor,
- backgroundColor,
- } );
-
- if ( ! SHOP_URL ) {
- return null;
- }
-
- return (
- <div className="wp-block-button has-text-align-center">
- <Button
- className={ clsx(
- className,
- styleProps.className,
- 'wc-block-mini-cart__shopping-button'
- ) }
- style={ styleProps.style }
- variant={ getVariant( className, 'contained' ) }
- href={ SHOP_URL }
- >
- { startShoppingButtonLabel || defaultStartShoppingButtonLabel }
- </Button>
- </div>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-block/block.tsx
deleted file mode 100644
index 9544d3a8b3f..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-block/block.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * External dependencies
- */
-import { useStoreCart } from '@woocommerce/base-context/hooks';
-import clsx from 'clsx';
-
-/**
- * Internal dependencies
- */
-import TitleItemsCounter from '../mini-cart-title-items-counter-block/block';
-import TitleYourCart from '../mini-cart-title-label-block/block';
-import { hasChildren } from '../utils';
-
-type MiniCartTitleBlockProps = {
- className: string;
- children: JSX.Element;
-};
-
-const Block = ( {
- children,
- className,
-}: MiniCartTitleBlockProps ): JSX.Element | null => {
- const { cartIsLoading } = useStoreCart();
- if ( cartIsLoading ) {
- return null;
- }
-
- // The `Mini-Cart Title` was converted to two inner blocks, but we still need to render the old title for
- // themes that have the old `mini-cart.html` template. So we check if there are any inner blocks and if
- // not, render the title blocks.
- const hasTitleInnerBlocks = hasChildren( children );
-
- return (
- <h2 className={ clsx( className, 'wc-block-mini-cart__title' ) }>
- { hasTitleInnerBlocks ? (
- children
- ) : (
- <>
- <TitleYourCart />
- <TitleItemsCounter />
- </>
- ) }
- </h2>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-items-counter-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-items-counter-block/block.tsx
deleted file mode 100644
index ea24c07304a..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-items-counter-block/block.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * External dependencies
- */
-import { useStoreCart } from '@woocommerce/base-context';
-import clsx from 'clsx';
-import { _n, sprintf } from '@wordpress/i18n';
-import { useStyleProps } from '@woocommerce/base-hooks';
-
-type Props = {
- className?: string;
-};
-
-const Block = ( props: Props ): JSX.Element => {
- const { cartItemsCount } = useStoreCart();
- const styleProps = useStyleProps( props );
-
- return (
- <span
- className={ clsx( props.className, styleProps.className ) }
- style={ styleProps.style }
- >
- { sprintf(
- /* translators: %d is the count of items in the cart. */
- _n( '(%d item)', '(%d items)', cartItemsCount, 'woocommerce' ),
- cartItemsCount
- ) }
- </span>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-label-block/block.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-label-block/block.tsx
deleted file mode 100644
index 49b164ac340..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-title-label-block/block.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * External dependencies
- */
-import { useStyleProps } from '@woocommerce/base-hooks';
-import clsx from 'clsx';
-
-/**
- * Internal dependencies
- */
-import { defaultYourCartLabel } from './constants';
-
-type Props = {
- label?: string;
- className?: string;
-};
-
-const Block = ( props: Props ): JSX.Element => {
- const styleProps = useStyleProps( props );
-
- return (
- <span
- className={ clsx( props.className, styleProps.className ) }
- style={ styleProps.style }
- >
- { props.label || defaultYourCartLabel }
- </span>
- );
-};
-
-export default Block;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/register-components.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/register-components.ts
deleted file mode 100644
index 99aae07f44d..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/register-components.ts
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * External dependencies
- */
-import { WC_BLOCKS_BUILD_URL } from '@woocommerce/block-settings';
-import { registerCheckoutBlock } from '@woocommerce/blocks-checkout';
-import { lazy } from '@wordpress/element';
-/**
- * Internal dependencies
- */
-import emptyMiniCartContentsMetadata from './empty-mini-cart-contents-block/block.json';
-import filledMiniCartMetadata from './filled-mini-cart-contents-block/block.json';
-import miniCartTitleMetadata from './mini-cart-title-block/block.json';
-import miniCartTitleItemsCounterMetadata from './mini-cart-title-items-counter-block/block.json';
-import miniCartTitleLabelBlockMetadata from './mini-cart-title-label-block/block.json';
-import miniCartProductsTableMetadata from './mini-cart-products-table-block/block.json';
-import miniCartFooterMetadata from './mini-cart-footer-block/block.json';
-import miniCartItemsMetadata from './mini-cart-items-block/block.json';
-import miniCartShoppingButtonMetadata from './mini-cart-shopping-button-block/block.json';
-import miniCartCartButtonMetadata from './mini-cart-cart-button-block/block.json';
-import miniCartCheckoutButtonMetadata from './mini-cart-checkout-button-block/block.json';
-
-// Modify webpack publicPath at runtime based on location of WordPress Plugin.
-// eslint-disable-next-line no-undef,camelcase
-__webpack_public_path__ = WC_BLOCKS_BUILD_URL;
-
-registerCheckoutBlock( {
- metadata: filledMiniCartMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/filled-cart" */ './filled-mini-cart-contents-block/frontend'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: emptyMiniCartContentsMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/empty-cart" */ './empty-mini-cart-contents-block/frontend'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartTitleMetadata,
- force: false,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/title" */ './mini-cart-title-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartTitleItemsCounterMetadata,
- force: false,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/title-items-counter" */ './mini-cart-title-items-counter-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartTitleLabelBlockMetadata,
- force: false,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/title-label" */ './mini-cart-title-label-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartItemsMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/items" */ './mini-cart-items-block/frontend'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartProductsTableMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/products-table" */ './mini-cart-products-table-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartFooterMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/footer" */ './mini-cart-footer-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartShoppingButtonMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/shopping-button" */ './mini-cart-shopping-button-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartCartButtonMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/cart-button" */ './mini-cart-cart-button-block/block'
- )
- ),
-} );
-
-registerCheckoutBlock( {
- metadata: miniCartCheckoutButtonMetadata,
- component: lazy(
- () =>
- import(
- /* webpackChunkName: "mini-cart-contents-block/checkout-button" */ './mini-cart-checkout-button-block/block'
- )
- ),
-} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/utils.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/utils.ts
index ac376205668..8bddfe86254 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/utils.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/utils.ts
@@ -2,7 +2,6 @@
* External dependencies
*/
import { getSetting } from '@woocommerce/settings';
-import { isObject } from '@woocommerce/types';
type Variant = 'text' | 'contained' | 'outlined';
@@ -21,22 +20,6 @@ export const getVariant = (
return defaultVariant;
};
-/**
- * Checks if there are any children that are blocks.
- */
-export const hasChildren = ( children: JSX.Element[] | undefined ): boolean => {
- if ( ! children ) {
- return false;
- }
-
- return children.some( ( child ) => {
- if ( Array.isArray( child ) ) {
- return hasChildren( child );
- }
- return isObject( child ) && child.key !== null;
- } );
-};
-
/**
* Gets the totals item description text from PHP-computed setting.
*
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx
index 025c48f6745..51904f1d8e5 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx
@@ -7,7 +7,6 @@ import { Icon } from '@wordpress/icons';
/**
* Internal dependencies
*/
-import './style.scss';
import { IconType, ColorItem, productCountVisibilityType } from '.././types';
interface Props {
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/style.scss b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/style.scss
index aca7c8f4833..3df262d6ee8 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/style.scss
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/style.scss
@@ -1,3 +1,6 @@
+@import "../../base/components/drawer/style";
+@import "quantity-badge/style";
+
.wc-block-mini-cart {
display: inline-block;
}
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/test/block.js b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/test/block.js
deleted file mode 100644
index 1f8e9b3f9b6..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/test/block.js
+++ /dev/null
@@ -1,231 +0,0 @@
-/**
- * External dependencies
- */
-import {
- act,
- render,
- screen,
- queryByText,
- waitFor,
- waitForElementToBeRemoved,
-} from '@testing-library/react';
-import { previewCart } from '@woocommerce/resource-previews';
-import { dispatch } from '@wordpress/data';
-import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
-import { SlotFillProvider } from '@woocommerce/blocks-checkout';
-import { server, http, HttpResponse } from '@woocommerce/test-utils/msw';
-import userEvent from '@testing-library/user-event';
-
-/**
- * Internal dependencies
- */
-import Block from '../block';
-import { defaultCartState } from '../../../data/cart/default-state';
-
-const MiniCartBlock = ( props ) => (
- <SlotFillProvider>
- <Block
- contents='<div data-block-name="woocommerce/mini-cart-contents" class="wp-block-woocommerce-mini-cart-contents"><div data-block-name="woocommerce/filled-mini-cart-contents-block" class="wp-block-woocommerce-filled-mini-cart-contents-block"><div data-block-name="woocommerce/mini-cart-title-block" class="wp-block-woocommerce-mini-cart-title-block"><div data-block-name="woocommerce/mini-cart-title-label-block" class="wp-block-woocommerce-mini-cart-title-label-block"></div>
- <div data-block-name="woocommerce/mini-cart-title-items-counter-block" class="wp-block-woocommerce-mini-cart-title-items-counter-block"></div></div>
- <div data-block-name="woocommerce/mini-cart-items-block" class="wp-block-woocommerce-mini-cart-items-block"><div data-block-name="woocommerce/mini-cart-products-table-block" class="wp-block-woocommerce-mini-cart-products-table-block"></div></div>
- <div data-block-name="woocommerce/mini-cart-footer-block" class="wp-block-woocommerce-mini-cart-footer-block"><div data-block-name="woocommerce/mini-cart-cart-button-block" class="wp-block-woocommerce-mini-cart-cart-button-block"></div>
- <div data-block-name="woocommerce/mini-cart-checkout-button-block" class="wp-block-woocommerce-mini-cart-checkout-button-block"></div></div></div>
- <div data-block-name="woocommerce/empty-mini-cart-contents-block" class="wp-block-woocommerce-empty-mini-cart-contents-block">
- <p class="has-text-align-center"><strong>Your cart is currently empty!</strong></p>
- <div data-block-name="woocommerce/mini-cart-shopping-button-block" class="wp-block-woocommerce-mini-cart-shopping-button-block"></div></div></div>'
- { ...props }
- />
- </SlotFillProvider>
-);
-
-const mockEmptyCart = () => {
- server.use(
- http.get( '*/wc/store/v1/cart*', () => {
- return HttpResponse.json( defaultCartState.cartData );
- } )
- );
-};
-
-const mockFullCart = () => {
- server.use(
- http.get( '*/wc/store/v1/cart*', () => {
- return HttpResponse.json( previewCart );
- } )
- );
-};
-
-describe( 'Testing Mini-Cart', () => {
- beforeEach( () => {
- act( () => {
- mockFullCart();
- // need to clear the store resolution state between tests.
- dispatch( storeKey ).invalidateResolutionForStore();
- dispatch( storeKey ).receiveCart( defaultCartState.cartData );
- } );
- } );
-
- afterEach( () => {
- server.resetHandlers();
- } );
-
- it( 'shows Mini-Cart count badge when there are items in the cart', async () => {
- render( <MiniCartBlock /> );
-
- await waitFor( () =>
- expect( screen.getByText( '3' ) ).toBeInTheDocument()
- );
- } );
-
- it( "doesn't show Mini-Cart count badge when cart is empty", async () => {
- mockEmptyCart();
- render( <MiniCartBlock /> );
- await waitFor( () =>
- expect( screen.getByLabelText( /0 items in cart/i ) ).toBeVisible()
- );
- const badgeWith0Count = screen.queryByText( '0' );
-
- expect( badgeWith0Count ).toBeNull();
- } );
-
- it( 'opens Mini-Cart drawer when clicking on button', async () => {
- const user = userEvent.setup();
- render( <MiniCartBlock /> );
-
- await waitFor( () =>
- expect( screen.getByLabelText( /3 items in cart/i ) ).toBeVisible()
- );
- await act( async () => {
- await user.click( screen.getByLabelText( /items/i ) );
- } );
-
- await waitFor( () =>
- expect( screen.getByText( /your cart/i ) ).toBeInTheDocument()
- );
- } );
-
- it( 'closes the drawer when clicking on the close button', async () => {
- const user = userEvent.setup();
- render( <MiniCartBlock /> );
- await waitFor( () =>
- expect( screen.getByLabelText( /3 items in cart/i ) ).toBeVisible()
- );
-
- // Open drawer.
- await act( async () => {
- await user.click( screen.getByLabelText( /items/i ) );
- } );
-
- // Close drawer.
- let closeButton = null;
-
- await waitFor( () => {
- closeButton = screen.getByLabelText( /close/i );
- } );
-
- if ( closeButton ) {
- await act( async () => {
- await user.click( closeButton );
- } );
- }
-
- await waitFor( () => {
- expect(
- screen.queryByText( /your cart/i )
- ).not.toBeInTheDocument();
- } );
- } );
-
- it( 'renders empty cart if there are no items in the cart', async () => {
- const user = userEvent.setup();
- mockEmptyCart();
- render( <MiniCartBlock /> );
-
- await waitFor( () =>
- expect( screen.getByLabelText( /0 items in cart/i ) ).toBeVisible()
- );
-
- await act( async () => {
- await user.click( screen.getByLabelText( /items/i ) );
- } );
-
- // Should show empty cart message
- await waitFor( () =>
- expect(
- screen.getByText( /Your cart is currently empty!/i )
- ).toBeVisible()
- );
- } );
-
- it( 'updates contents when removed from cart event is triggered', async () => {
- render( <MiniCartBlock /> );
- await waitFor( () =>
- expect( screen.getByLabelText( /3 items in cart/i ) ).toBeVisible()
- );
-
- mockEmptyCart();
- // eslint-disable-next-line no-undef
- const removedFromCartEvent = new Event( 'wc-blocks_removed_from_cart' );
- act( () => {
- document.body.dispatchEvent( removedFromCartEvent );
- } );
-
- await waitForElementToBeRemoved( () =>
- screen.queryByLabelText( /3 items in cart/i )
- );
- await waitFor( () =>
- expect( screen.getByLabelText( /0 items in cart/i ) ).toBeVisible()
- );
- } );
-
- it( 'updates contents when added to cart event is triggered', async () => {
- mockEmptyCart();
- render( <MiniCartBlock /> );
- await waitFor( () =>
- expect( screen.getByLabelText( /0 items in cart/i ) ).toBeVisible()
- );
-
- mockFullCart();
- // eslint-disable-next-line no-undef
- const addedToCartEvent = new Event( 'wc-blocks_added_to_cart' );
- act( () => {
- document.body.dispatchEvent( addedToCartEvent );
- } );
-
- await waitForElementToBeRemoved( () =>
- screen.queryByLabelText( /0 items in cart/i )
- );
- await waitFor( () =>
- expect(
- screen.getByLabelText( /3 items in cart/i )
- ).toBeInTheDocument()
- );
- } );
-
- it( 'renders cart price if "Hide Cart Price" setting is not enabled', async () => {
- mockEmptyCart();
- render( <MiniCartBlock hasHiddenPrice={ false } /> );
- await waitFor( () =>
- expect(
- screen.getByLabelText( /0 items in cart/i )
- ).toBeInTheDocument()
- );
-
- await waitFor( () =>
- expect( screen.getByText( '$0.00' ) ).toBeInTheDocument()
- );
- } );
-
- it( 'does not render cart price if "Hide Cart Price" setting is enabled', async () => {
- mockEmptyCart();
- const { container } = render( <MiniCartBlock /> );
- await waitFor( () =>
- expect(
- screen.getByLabelText( /0 items in cart/i )
- ).toBeInTheDocument()
- );
-
- await waitFor( () =>
- expect( queryByText( container, '$0.00' ) ).not.toBeInTheDocument()
- );
- } );
-} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/types.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/types.ts
index 302bf307643..34d7bd9b865 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/types.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/types.ts
@@ -1,8 +1,3 @@
-/**
- * External dependencies
- */
-import { CartResponseTotals } from '@woocommerce/types';
-
export type IconType = 'cart' | 'bag' | 'bag-alt' | undefined;
export type productCountVisibilityType =
| 'always'
@@ -16,19 +11,3 @@ export interface ColorItem {
slug?: string;
class?: string;
}
-export interface BlockAttributes {
- initialCartItemsCount?: number;
- initialCartTotals?: CartResponseTotals;
- isInitiallyOpen?: boolean;
- colorClassNames?: string;
- style?: Record< string, Record< string, string > >;
- contents: string;
- miniCartIcon?: IconType;
- addToCartBehaviour: string;
- onCartClickBehaviour: string;
- hasHiddenPrice: boolean;
- priceColor: ColorItem;
- iconColor: ColorItem;
- productCountColor: ColorItem;
- productCountVisibility?: productCountVisibilityType;
-}
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/data.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/data.ts
index 125f1415ea1..5af747c671f 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/data.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/data.ts
@@ -1,109 +1,13 @@
/**
* External dependencies
*/
-import { _n, sprintf } from '@wordpress/i18n';
-import {
- getCurrencyFromPriceResponse,
- formatPrice,
-} from '@woocommerce/price-format';
-import { CartResponseTotals, isBoolean } from '@woocommerce/types';
-import { getSettingWithCoercion } from '@woocommerce/settings';
import type { ColorPaletteOption } from '@woocommerce/editor-components/color-panel/types';
-import type { Cart } from '@woocommerce/types';
/**
* Internal dependencies
*/
import { Attributes } from '../edit';
-const getPrice = ( totals: CartResponseTotals, showIncludingTax: boolean ) => {
- const currency = getCurrencyFromPriceResponse( totals );
-
- const subTotal = showIncludingTax
- ? parseInt( totals.total_items, 10 ) +
- parseInt( totals.total_items_tax, 10 )
- : parseInt( totals.total_items, 10 );
-
- return formatPrice( subTotal, currency );
-};
-
-export const updateTotals = ( cartData: Cart ) => {
- if ( ! cartData ) {
- return;
- }
- const { totals, itemsCount: quantity } = cartData;
- const showIncludingTax = getSettingWithCoercion(
- 'displayCartPricesIncludingTax',
- false,
- isBoolean
- );
- const amount = getPrice( totals, showIncludingTax );
- const miniCartBlocks = document.querySelectorAll( '.wc-block-mini-cart' );
- const miniCartQuantities = document.querySelectorAll(
- '.wc-block-mini-cart__badge'
- );
- const miniCartAmounts = document.querySelectorAll(
- '.wc-block-mini-cart__amount'
- );
-
- miniCartBlocks.forEach( ( miniCartBlock ) => {
- if ( ! ( miniCartBlock instanceof HTMLElement ) ) {
- return;
- }
-
- const miniCartButton = miniCartBlock.querySelector(
- '.wc-block-mini-cart__button'
- );
-
- miniCartButton?.setAttribute(
- 'aria-label',
- miniCartBlock.dataset.hasHiddenPrice
- ? sprintf(
- /* translators: %s number of products in cart. */
- _n(
- '%1$d item in cart',
- '%1$d items in cart',
- quantity,
- 'woocommerce'
- ),
- quantity
- )
- : sprintf(
- /* translators: %1$d is the number of products in the cart. %2$s is the cart total */
- _n(
- '%1$d item in cart, total price of %2$s',
- '%1$d items in cart, total price of %2$s',
- quantity,
- 'woocommerce'
- ),
- quantity,
- amount
- )
- );
-
- miniCartBlock.dataset.cartTotals = JSON.stringify( totals );
- miniCartBlock.dataset.cartItemsCount = quantity.toString();
- } );
- miniCartQuantities.forEach( ( miniCartQuantity ) => {
- if ( quantity > 0 || miniCartQuantity.textContent !== '' ) {
- miniCartQuantity.textContent = quantity.toString();
- }
- } );
- miniCartAmounts.forEach( ( miniCartAmount ) => {
- miniCartAmount.textContent = amount;
- } );
-
- // Show the tax label only if there are products in the cart.
- if ( quantity > 0 ) {
- const miniCartTaxLabels = document.querySelectorAll(
- '.wc-block-mini-cart__tax-label'
- );
- miniCartTaxLabels.forEach( ( miniCartTaxLabel ) => {
- miniCartTaxLabel.removeAttribute( 'hidden' );
- } );
- }
-};
-
interface MaybeInCompatibleAttributes
extends Omit<
Attributes,
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/set-styles.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/set-styles.ts
deleted file mode 100644
index 27323a4132e..00000000000
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/set-styles.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-function getClosestColor(
- element: Element | null,
- colorType: 'color' | 'backgroundColor'
-): string | null {
- if ( ! element ) {
- return null;
- }
- const color = window.getComputedStyle( element )[ colorType ];
- if ( color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent' ) {
- const matches = color.match( /\d+/g );
- if ( ! matches || matches.length < 3 ) {
- return null;
- }
- const [ r, g, b ] = matches.slice( 0, 3 );
- return `rgb(${ r }, ${ g }, ${ b })`;
- }
- return getClosestColor( element.parentElement, colorType );
-}
-
-function setStyles() {
- /**
- * Get the background color of the body then set it as the background color
- * of the Mini-Cart Contents block.
- *
- * We only set the background color, instead of the whole background. As
- * we only provide the option to customize the background color.
- */
- const backgroundColor = getComputedStyle( document.body ).backgroundColor;
- // For simplicity, we only consider the background color of the first Mini-Cart button.
- const firstMiniCartButton = document.querySelector(
- '.wc-block-mini-cart__button'
- );
- const badgeTextColor =
- getClosestColor( firstMiniCartButton, 'backgroundColor' ) || '#fff';
- const badgeBackgroundColor =
- getClosestColor( firstMiniCartButton, 'color' ) || '#000';
-
- // We use :where here to reduce specificity so customized colors and theme
- // CSS take priority.
- // We need to set `div` and `span` in the selector so it has more specificity than the CSS.
- const css = `div:where(.wp-block-woocommerce-mini-cart-contents) {
- background-color: ${ backgroundColor };
- }
- span:where(.wc-block-mini-cart__badge) {
- background-color: ${ badgeBackgroundColor };
- color: ${ badgeTextColor };
- }`;
-
- // Use adoptedStyleSheets so styles survive iAPI client-side navigations.
- // Fall back to a <style> element for environments that don't support it,
- // (specifically it would fail in tests).
- try {
- const sheet = new CSSStyleSheet();
- sheet.replaceSync( css );
- document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, sheet ];
- } catch {
- const style = document.createElement( 'style' );
- style.appendChild( document.createTextNode( css ) );
- document.head.appendChild( style );
- }
-}
-
-export default setStyles;
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/test/data.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/test/data.ts
index ae100551eb9..3e279815232 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/test/data.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/utils/test/data.ts
@@ -1,150 +1,7 @@
-// eslint-disable testing-library/no-dom-import
-/**
- * External dependencies
- */
-import { getByTestId, waitFor } from '@testing-library/dom';
-import { getSettingWithCoercion } from '@woocommerce/settings';
-import { cartStore } from '@woocommerce/block-data';
-import { dispatch, select } from '@wordpress/data';
-import apiFetch from '@wordpress/api-fetch';
-
/**
* Internal dependencies
*/
import { migrateAttributesToColorPanel } from '../data';
-import '../../frontend';
-
-jest.mock( '@wordpress/data-controls' );
-jest.mock( '@wordpress/api-fetch' );
-
-// This is a simplified version of the response of the Cart API endpoint.
-const responseMock = {
- totals: {
- total_price: '1800',
- total_items: '1400',
- total_items_tax: '200',
- currency_code: 'USD',
- currency_symbol: '$',
- currency_minor_unit: 2,
- currency_decimal_separator: '.',
- currency_thousand_separator: ',',
- currency_prefix: '$',
- currency_suffix: '',
- },
- items_count: 2,
-};
-
-// This is a simplified version of the Mini-Cart DOM generated by MiniCart.php.
-const getMiniCartDOM = () => {
- const div = document.createElement( 'div' );
- div.innerHTML = `
- <div class="wc-block-mini-cart">
- <div class="wc-block-mini-cart__amount" data-testid="amount"></div>
- <div class="wc-block-mini-cart__badge" data-testid="quantity"></div>
- </div>`;
- return div;
-};
-
-jest.mock( '@woocommerce/settings', () => {
- return {
- ...jest.requireActual( '@woocommerce/settings' ),
- getSettingWithCoercion: jest.fn(),
- };
-} );
-
-describe( 'Mini-Cart frontend script when "the display prices during cart and checkout" option is set to "Including Tax"', () => {
- beforeAll( () => {
- ( getSettingWithCoercion as jest.Mock ).mockReturnValue( true );
- } );
-
- afterAll( () => {
- jest.resetModules();
- } );
-
- it( 'updates the cart contents based on the cart data store', async () => {
- const container = getMiniCartDOM();
- document.body.appendChild( container );
-
- apiFetch.mockReturnValue(
- Promise.resolve( {
- status: 200,
- json: () => Promise.resolve( responseMock ),
- } )
- );
- dispatch( cartStore ).invalidateResolutionForStore();
- select( cartStore ).getCartData();
-
- // Assert that we are rendering the amount.
- await waitFor( () =>
- expect( getByTestId( container, 'amount' ).textContent ).toBe(
- '$16.00'
- )
- );
-
- // Assert that we are rendering the quantity.
- await waitFor( () =>
- expect( getByTestId( container, 'quantity' ).textContent ).toBe(
- '2'
- )
- );
-
- apiFetch.mockReturnValue(
- Promise.resolve( {
- status: 200,
- json: () =>
- Promise.resolve( {
- ...responseMock,
- items_count: 3,
- } ),
- } )
- );
-
- dispatch( cartStore ).invalidateResolutionForStoreSelector(
- 'getCartData'
- );
- select( cartStore ).getCartData();
-
- await waitFor( () =>
- expect( getByTestId( container, 'quantity' ).textContent ).toBe(
- '3'
- )
- );
- } );
-} );
-
-describe( 'Mini-Cart frontend script when "the display prices during cart and checkout" option is set to "Excluding Tax"', () => {
- beforeAll( () => {
- ( getSettingWithCoercion as jest.Mock ).mockReturnValue( false );
- } );
- it( 'updates the cart contents based on the API response', async () => {
- const container = getMiniCartDOM();
- document.body.appendChild( container );
-
- apiFetch.mockReturnValue(
- Promise.resolve( {
- status: 200,
- json: () => Promise.resolve( responseMock ),
- } )
- );
- dispatch( cartStore ).invalidateResolutionForStoreSelector(
- 'getCartData'
- );
- select( cartStore ).getCartData();
-
- // Assert that we are rendering the amount.
- await waitFor( () =>
- expect( getByTestId( container, 'amount' ).textContent ).toBe(
- '$14.00'
- )
- );
- // Assert that we are rendering the quantity.
- await waitFor( () =>
- expect( getByTestId( container, 'quantity' ).textContent ).toBe(
- '2'
- )
- );
- } );
-} );
const mockAttributes = {
miniCartIcon: 'cart',
diff --git a/plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js b/plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
index 1a8a908460d..c77c2330e62 100644
--- a/plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
+++ b/plugins/woocommerce/client/blocks/bin/webpack-config-interactive-blocks.js
@@ -35,10 +35,6 @@ const entries = {
...scriptModuleEntries,
...styleEntries,
...editorStyleEntries,
-
- // Experimental mini cart frontend modules, only enqueued when experimental-iapi-mini-cart feature flag is enabled.
- 'woocommerce/mini-cart': './assets/js/blocks/mini-cart/iapi-frontend.ts',
-
// Product elements frontend module. Share by several blocks.
'woocommerce/product-elements':
'./assets/js/atomic/blocks/product-elements/frontend.ts',
@@ -46,7 +42,6 @@ const entries = {
// Product Quantity block and the Grouped Product Selector block.
'woocommerce/add-to-cart-with-options-quantity-selector':
'./assets/js/blocks/add-to-cart-with-options/quantity-selector/frontend.ts',
-
// Other
'@woocommerce/stores/woocommerce/cart':
'./assets/js/base/stores/woocommerce/cart.ts',
diff --git a/plugins/woocommerce/client/blocks/bin/webpack-entries.js b/plugins/woocommerce/client/blocks/bin/webpack-entries.js
index 35bb14d5260..a1b3b48eb39 100644
--- a/plugins/woocommerce/client/blocks/bin/webpack-entries.js
+++ b/plugins/woocommerce/client/blocks/bin/webpack-entries.js
@@ -303,6 +303,16 @@ const frontendEntries = getBlockEntries( 'frontend.{t,j}s{,x}', {
),
} );
+const cartAndCheckoutFrontendEntries = getBlockEntries( 'frontend.{t,j}s{,x}', {
+ ...Object.fromEntries(
+ Object.entries( cartAndCheckoutBlocks ).filter( ( [ blockName ] ) => {
+ return ! frontendScriptModuleBlocksToSkip.includes(
+ `woocommerce/${ blockName }`
+ );
+ } )
+ ),
+} );
+
// Remove styles from style build,
// that are already included in interactivity
// script modules build.
@@ -387,11 +397,9 @@ const entries = {
'./assets/js/extensions/shipping-methods/pickup-location/index.js',
},
cartAndCheckoutFrontend: {
- ...getBlockEntries( 'frontend.{t,j}s{,x}', cartAndCheckoutBlocks ),
+ ...cartAndCheckoutFrontendEntries,
blocksCheckout: './packages/checkout/index.js',
blocksComponents: './packages/components/index.ts',
- 'mini-cart-component':
- './assets/js/blocks/mini-cart/component-frontend.tsx',
},
};
diff --git a/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-for-lazy-loaded-components.md b/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-for-lazy-loaded-components.md
index 18542c4139a..287a11ddc68 100644
--- a/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-for-lazy-loaded-components.md
+++ b/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-for-lazy-loaded-components.md
@@ -1,6 +1,6 @@
# Translations for lazy-loaded components
-The Mini-Cart block as well as inner blocks of the Cart and the Checkout blocks are lazy-loaded. To lazy-load them, the translation chunks needs to be registered. This takes place in `/src/BlockTypes/AbstractBlock.php`:
+The inner blocks of the Cart and Checkout blocks are lazy-loaded. To lazy-load them, the translation chunks need to be registered. This takes place in `src/Blocks/BlockTypes/AbstractBlock.php`:
```php
/**
@@ -26,7 +26,7 @@ protected function register_chunk_translations( $chunks ) {
## Lazy-loaded translations of the Cart block
-The translations of the inner blocks of the Cart block are loaded in this function in `src/BlockTypes/Cart.php`:
+The translations of the inner blocks of the Cart block are loaded in this function in `src/Blocks/BlockTypes/Cart.php`:
```php
/**
@@ -45,7 +45,7 @@ protected function register_block_type_assets() {
## Lazy-loaded translations of the Checkout block
-The translations of the inner blocks of the Cart block are loaded in this function in `src/BlockTypes/Checkout.php`:
+The translations of the inner blocks of the Checkout block are loaded in this function in `src/Blocks/BlockTypes/Checkout.php`:
```php
/**
@@ -62,35 +62,6 @@ protected function register_block_type_assets() {
}
```
-## Lazy-loaded translations of the Mini-Cart block
-
-The translations of the inner blocks of the Mini-Cart block are loaded in this function in `src/BlockTypes/MiniCart.php`:
-
-```php
-/**
- * Prepare translations for inner blocks and dependencies.
- */
-protected function get_inner_blocks_translations() {
- $wp_scripts = wp_scripts();
- $translations = array();
-
- $chunks = $this->get_chunks_paths( $this->chunks_folder );
- $vendor_chunks = $this->get_chunks_paths( 'vendors--mini-cart-contents-block' );
- $shared_chunks = [ 'cart-blocks/cart-line-items--mini-cart-contents-block/products-table-frontend' ];
-
- foreach ( array_merge( $chunks, $vendor_chunks, $shared_chunks ) as $chunk ) {
- $handle = 'wc-blocks-' . $chunk . '-chunk';
- $this->asset_api->register_script( $handle, $this->asset_api->get_block_asset_build_path( $chunk ), [], true );
- $translations[] = $wp_scripts->print_translations( $handle, false );
- wp_deregister_script( $handle );
- }
-
- $translations = array_filter( $translations );
-
- return implode( '', $translations );
-}
-```
-
## Register lazy-loading components
The functions above show how the chunks are lazy-loaded. These chunks are currently defined in `assets/js/blocks/checkout/inner-blocks/register-components.ts` and look like this:
diff --git a/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md b/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md
index 4b3e3962e27..669bc11a03a 100644
--- a/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md
+++ b/plugins/woocommerce/client/blocks/docs/internal-developers/translations/translations-in-FSE-templates.md
@@ -73,7 +73,7 @@ We then replace this code with the following code:
<!-- wp:pattern {"slug":"woocommerce/mini-cart-empty-cart-message"} /-->
```
-In the file, that holds the logic for this FSE-template, in this case `src/BlockTypes/MiniCart.php`, we then register this placeholder as a block pattern:
+In the file, that holds the logic for this FSE-template, in this case `src/Blocks/BlockTypes/MiniCart.php`, we then register this placeholder as a block pattern:
```php
/**
@@ -83,9 +83,9 @@ public function register_empty_cart_message_block_pattern() {
register_block_pattern(
'woocommerce/mini-cart-empty-cart-message',
array(
- 'title' => __( 'Empty Mini-Cart Message', 'woo-gutenberg-products-block' ),
+ 'title' => __( 'Empty Mini-Cart Message', 'woocommerce' ),
'inserter' => false,
- 'content' => '<!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center"><strong>' . __( 'Your cart is currently empty!', 'woo-gutenberg-products-block' ) . '</strong></p><!-- /wp:paragraph -->',
+ 'content' => '<!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center"><strong>' . __( 'Your cart is currently empty!', 'woocommerce' ) . '</strong></p><!-- /wp:paragraph -->',
)
);
}
diff --git a/plugins/woocommerce/client/blocks/package.json b/plugins/woocommerce/client/blocks/package.json
index 64c06452380..87be32ac489 100644
--- a/plugins/woocommerce/client/blocks/package.json
+++ b/plugins/woocommerce/client/blocks/package.json
@@ -28,8 +28,6 @@
"./assets/js/blocks/cart/inner-blocks/**/index.tsx",
"./assets/js/blocks/cart/inner-blocks/register-components.ts",
"./assets/js/base/components/**/*.{tsx,ts}",
- "./assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/**/index.tsx",
- "./assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/register-components.ts",
"./assets/js/blocks/cart-checkout-shared/sidebar-notices/index.tsx",
"./assets/js/blocks/cart-checkout-shared/view-switcher/index.tsx",
"./assets/js/blocks/filter-wrapper/register-components.ts",
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php
index feeda7901f4..4c520e71359 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard-setup.php
@@ -7,7 +7,6 @@
*/
use Automattic\Jetpack\Constants;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
@@ -249,11 +248,11 @@ if ( ! class_exists( 'WC_Admin_Dashboard_Setup', false ) ) :
* @return bool
*/
public function should_display_widget() {
- if ( ! class_exists( 'Automattic\WooCommerce\Admin\Features\Features' ) || ! class_exists( 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists' ) ) {
+ if ( ! class_exists( 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists' ) ) {
return false;
}
- if ( ! Features::is_enabled( 'onboarding' ) || ! WC()->is_wc_admin_active() ) {
+ if ( ! WC()->is_wc_admin_active() ) {
return false;
}
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
index 73ebe5cf967..6aaaf3a6a12 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-dashboard.php
@@ -7,13 +7,14 @@
*/
use Automattic\Jetpack\Constants;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Enums\OrderInternalStatus;
+use Automattic\WooCommerce\Utilities\FeaturesUtil;
use Automattic\WooCommerce\Utilities\OrderUtil;
if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly.
+ exit;
+ // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
@@ -165,7 +166,7 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
*/
public function status_widget_content() {
//phpcs:ignore
- $is_wc_admin_disabled = apply_filters( 'woocommerce_admin_disabled', false ) || ! Features::is_enabled( 'analytics' );
+ $is_wc_admin_disabled = apply_filters( 'woocommerce_admin_disabled', false ) || ! FeaturesUtil::feature_is_enabled( 'analytics' );
$status_widget_reports = array(
'net_sales_link' => 'admin.php?page=wc-admin&path=%2Fanalytics%2Frevenue&chart=net_revenue&orderby=net_revenue&period=month&compare=previous_period',
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-settings.php b/plugins/woocommerce/includes/admin/class-wc-admin-settings.php
index d6722ccab75..0cd4f06c8c2 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin-settings.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin-settings.php
@@ -57,9 +57,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
$settings[] = include_once __DIR__ . '/settings/class-wc-settings-accounts.php';
$settings[] = include_once __DIR__ . '/settings/class-wc-settings-emails.php';
$settings[] = include_once __DIR__ . '/settings/class-wc-settings-integrations.php';
- if ( \Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'launch-your-store' ) ) {
- $settings[] = include_once __DIR__ . '/settings/class-wc-settings-site-visibility.php';
- }
+ $settings[] = include_once __DIR__ . '/settings/class-wc-settings-site-visibility.php';
$settings[] = include_once __DIR__ . '/settings/class-wc-settings-point-of-sale.php';
$settings[] = include_once __DIR__ . '/settings/class-wc-settings-advanced.php';
diff --git a/plugins/woocommerce/includes/react-admin/connect-existing-pages.php b/plugins/woocommerce/includes/react-admin/connect-existing-pages.php
index ede5fbee569..e4666c14d09 100644
--- a/plugins/woocommerce/includes/react-admin/connect-existing-pages.php
+++ b/plugins/woocommerce/includes/react-admin/connect-existing-pages.php
@@ -6,7 +6,6 @@
*/
use Automattic\WooCommerce\Admin\PageController;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Utilities\OrderUtil;
/**
@@ -172,7 +171,7 @@ if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
wc_admin_connect_page(
array(
'id' => 'woocommerce-coupons',
- 'parent' => Features::is_enabled( 'coupons' ) ? 'woocommerce-marketing' : null,
+ 'parent' => 'woocommerce-marketing',
'screen_id' => 'edit-shop_coupon',
'title' => __( 'Coupons', 'woocommerce' ),
'path' => add_query_arg( 'post_type', 'shop_coupon', $posttype_list_base ),
diff --git a/plugins/woocommerce/package.json b/plugins/woocommerce/package.json
index 5eda4191427..6df6cb366af 100644
--- a/plugins/woocommerce/package.json
+++ b/plugins/woocommerce/package.json
@@ -87,11 +87,7 @@
"test:e2e:hpos-off": "pnpm test:e2e:with-env default-hpos-disabled --project=e2e-hpos-disabled",
"test:e2e:gb-stable": "pnpm test:e2e:with-env gutenberg-stable",
"test:e2e:gb-nightly": "pnpm test:e2e:with-env gutenberg-nightly",
- "ci:legacy-minicart-flag-off": "node ./bin/set-legacy-minicart-flag.js && php bin/generate-feature-config.php",
- "test:e2e:legacy-mini-cart": "pnpm ci:legacy-minicart-flag-off && pnpm test:e2e:default --project=legacy-mini-cart",
- "test:e2e:blocks:legacy-mini-cart": "pnpm ci:legacy-minicart-flag-off && pnpm playwright test --config=tests/e2e/playwright.config.ts --project=blocks-legacy-mini-cart",
"test:e2e:paypal-standard": "pnpm test:e2e:default --project=paypal-standard",
- "test:php:legacy-mini-cart": "pnpm ci:legacy-minicart-flag-off && pnpm test:php:env",
"test:env:start": "pnpm env:test",
"test:perf": "./tests/performance/bin/k6 run ./tests/performance/tests/main.js",
"test:perf:ci-setup": "pnpm test:perf:install-k6 && pnpm env:perf",
@@ -180,37 +176,6 @@
"php-unit-php-8.5-wp-latest"
]
},
- {
- "name": "PHP: 8.5 WP: latest - Legacy MiniCart",
- "testType": "unit:php",
- "command": "test:php:legacy-mini-cart",
- "shardingArguments": [
- "--testsuite=wc-phpunit-legacy",
- "--testsuite=wc-phpunit-main",
- "--testsuite=wc-phpunit-graphql-infra",
- "--testsuite=wc-phpunit-graphql-api"
- ],
- "onlyForDependencies": [],
- "changes": [
- "client/admin/config/*.json",
- "composer.json",
- "composer.lock",
- "**/*.php",
- ".wp-env.test.json",
- "phpunit.xml"
- ],
- "testEnv": {
- "start": "env:test --debug",
- "config": {
- "phpVersion": "8.5",
- "wpVersion": "latest"
- }
- },
- "events": [
- "pull_request",
- "push"
- ]
- },
{
"name": "PHP: 7.4 WP: latest - 1",
"testType": "unit:php",
@@ -357,38 +322,6 @@
"allure": true
}
},
- {
- "name": "Core e2e tests - Legacy MiniCart",
- "testType": "e2e",
- "command": "test:e2e:legacy-mini-cart",
- "shardingArguments": [],
- "changes": [
- "client/admin/config/*.json",
- "composer.json",
- "composer.lock",
- "i18n/**/*.php",
- "includes/**/*.php",
- "patterns/**/*.php",
- "src/**/*.php",
- "templates/**/*.php",
- "tests/e2e/**",
- ".wp-env.e2e.json",
- "woocommerce.php",
- "uninstall.php"
- ],
- "testEnv": {
- "start": "env:e2e --debug"
- },
- "events": [
- "pull_request",
- "push"
- ],
- "report": {
- "resultsBlobName": "legacy-core-e2e-report",
- "resultsPath": "tests/e2e/test-results",
- "allure": true
- }
- },
{
"name": "Core e2e tests - Gutenberg stable",
"testType": "e2e",
@@ -897,50 +830,6 @@
"allure": true
}
},
- {
- "name": "Blocks e2e tests - Legacy MiniCart",
- "testType": "e2e",
- "command": "test:e2e:blocks:legacy-mini-cart",
- "shardingArguments": [
- "--shard=1/3",
- "--shard=2/3",
- "--shard=3/3"
- ],
- "changes": [
- "patterns/**/*.php",
- "includes/**/*.php",
- "src/Blocks/**/*.php",
- "templates/**/*.php",
- "templates/**/*.html",
- "tests/e2e/bin/blocks/**",
- "tests/e2e/fixtures/blocks-setup.ts",
- "tests/e2e/playwright.config.ts",
- "tests/e2e/content-templates/blocks/**",
- "tests/e2e/test-data/blocks/**",
- "tests/e2e/test-plugins/blocks/**",
- "tests/e2e/tests/blocks/**",
- "tests/e2e/themes/blocks/**",
- "tests/e2e/utils/blocks/**"
- ],
- "onlyForDependencies": [
- "@woocommerce/block-library"
- ],
- "testEnv": {
- "start": "env:start:blocks",
- "config": {
- "phpVersion": "7.4"
- }
- },
- "events": [
- "pull_request",
- "push"
- ],
- "report": {
- "resultsBlobName": "legacy-blocks-e2e-report",
- "resultsPath": "tests/e2e/test-results",
- "allure": true
- }
- },
{
"name": "Blocks e2e tests - WP pre-release",
"optional": true,
diff --git a/plugins/woocommerce/patterns/coming-soon-entire-site.php b/plugins/woocommerce/patterns/coming-soon-entire-site.php
index 2b2f2fad3dc..7fe3a687cc2 100644
--- a/plugins/woocommerce/patterns/coming-soon-entire-site.php
+++ b/plugins/woocommerce/patterns/coming-soon-entire-site.php
@@ -9,7 +9,6 @@
* Slug: woocommerce/coming-soon-entire-site
* Categories: WooCommerce
* Inserter: false
- * Feature Flag: launch-your-store
*
* @package WooCommerce\Blocks
*/
diff --git a/plugins/woocommerce/patterns/coming-soon-store-only.php b/plugins/woocommerce/patterns/coming-soon-store-only.php
index ba2c49c2cde..290cec650f4 100644
--- a/plugins/woocommerce/patterns/coming-soon-store-only.php
+++ b/plugins/woocommerce/patterns/coming-soon-store-only.php
@@ -9,7 +9,6 @@
* Slug: woocommerce/coming-soon-store-only
* Categories: WooCommerce
* Inserter: false
- * Feature Flag: launch-your-store
*
* @package WooCommerce\Blocks
*/
diff --git a/plugins/woocommerce/patterns/coming-soon.php b/plugins/woocommerce/patterns/coming-soon.php
index 026aec11023..86a587ff3da 100644
--- a/plugins/woocommerce/patterns/coming-soon.php
+++ b/plugins/woocommerce/patterns/coming-soon.php
@@ -4,7 +4,6 @@
* Slug: woocommerce/coming-soon
* Categories: WooCommerce
* Inserter: false
- * Feature Flag: launch-your-store
*
* @package WooCommerce\Blocks
*/
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 2dc6f35ac63..aac84ee53f7 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -50823,24 +50823,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/CustomerAccount.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\EmptyMiniCartContentsBlock\:\:render_experimental_empty_mini_cart_contents\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\EmptyMiniCartContentsBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\EmptyMiniCartContentsBlock\:\:render_experimental_empty_mini_cart_contents\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\FeaturedCategory\:\:get_item_image\(\) should return string but returns string\|false\.$#'
identifier: return.type
@@ -50937,24 +50919,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/FeaturedProduct.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\FilledMiniCartContentsBlock\:\:render_experimental_filled_mini_cart_contents\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\FilledMiniCartContentsBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\FilledMiniCartContentsBlock\:\:render_experimental_filled_mini_cart_contents\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\HandpickedProducts\:\:set_block_query_args\(\) has no return type specified\.$#'
identifier: missingType.return
@@ -50979,30 +50943,12 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:append_script_and_deps_src\(\) has no return type specified\.$#'
- identifier: missingType.return
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:enable_interactivity_support\(\) has no return type specified\.$#'
- identifier: missingType.return
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:enqueue_data\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:get_block_type_script\(\) should return array\|string but empty return statement found\.$#'
- identifier: return.empty
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:get_cart_instance\(\) should return WC_Cart but returns null\.$#'
identifier: return.type
@@ -51015,12 +50961,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:get_inner_blocks_translations\(\) has no return type specified\.$#'
- identifier: missingType.return
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:get_tax_label\(\) has no return type specified\.$#'
identifier: missingType.return
@@ -51039,24 +50979,12 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:print_lazy_load_scripts\(\) has no return type specified\.$#'
- identifier: missingType.return
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:register_empty_cart_message_block_pattern\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:render_experimental_iapi_mini_cart\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Offset int\<0, max\>\|null might not exist on list\<bool\>\.$#'
identifier: offsetAccess.notFound
@@ -51075,12 +51003,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Parameter \#1 \$arr1 of function array_merge expects array, array\<string\>\|null given\.$#'
- identifier: argument.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Parameter \#1 \$content of function do_blocks expects string, string\|false given\.$#'
identifier: argument.type
@@ -51111,24 +51033,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Parameter \#1 \$str of function rawurlencode expects string, string\|false given\.$#'
- identifier: argument.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:render_experimental_iapi_mini_cart\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Parameter \$context of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:modify_hooked_block_attributes\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block_Template\.$#'
identifier: class.notFound
@@ -51153,18 +51057,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Property Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:\$scripts_to_lazy_load \(array\<string\>\) does not accept array\<array\<string, bool\|string\>\|string\>\.$#'
- identifier: assign.propertyType
- count: 1
- path: src/Blocks/BlockTypes/MiniCart.php
-
- -
- message: '#^Property Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCart\:\:\$scripts_to_lazy_load \(array\<string\>\) does not accept array\<array\<string, mixed\>\|string\>\.$#'
- identifier: assign.propertyType
- count: 2
- path: src/Blocks/BlockTypes/MiniCart.php
-
-
message: '#^Result of && is always false\.$#'
identifier: booleanAnd.alwaysFalse
@@ -51195,54 +51087,18 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCart.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartCartButtonBlock\:\:render_experimental_iapi_markup\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
-
-
message: '#^Parameter \#1 \$url of function esc_url expects string, string\|false given\.$#'
identifier: argument.type
count: 1
path: src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartCartButtonBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartCartButtonBlock\:\:render_experimental_iapi_markup\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
-
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartCheckoutButtonBlock\:\:render_experimental_iapi_markup\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
-
-
message: '#^Parameter \#1 \$url of function esc_url expects string, string\|false given\.$#'
identifier: argument.type
count: 1
path: src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartCheckoutButtonBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartCheckoutButtonBlock\:\:render_experimental_iapi_markup\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
-
-
message: '#^Call to function is_array\(\) with array\{''\.wc\-block\-mini\-cart…'', ''\.wc\-block\-mini\-cart…'', ''\.wc\-block\-mini\-cart…'', ''\.wc\-block\-mini\-cart…'', ''\.wc\-block\-mini\-cart…'', ''\.wc\-block\-mini\-cart…'', ''\.wc\-block\-mini\-cart…''\} will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
@@ -51261,12 +51117,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCartContents.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartContents\:\:render_experimental_iapi_mini_cart_contents\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartContents.php
-
-
message: '#^PHPDoc tag @return has invalid value \(array;\)\: Unexpected token ";", expected TOKEN_HORIZONTAL_WS at offset 91 on line 4$#'
identifier: phpDoc.parseError
@@ -51285,30 +51135,6 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCartContents.php
- -
- message: '#^Parameter \#3 \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\AbstractBlock\:\:enqueue_assets\(\) expects WP_Block, Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block given\.$#'
- identifier: argument.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartContents.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartContents\:\:enqueue_assets\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartContents.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartContents\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartContents.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartContents\:\:render_experimental_iapi_mini_cart_contents\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartContents.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartFooterBlock\:\:enqueue_data\(\) has no return type specified\.$#'
identifier: missingType.return
@@ -51321,48 +51147,12 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCartFooterBlock.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartFooterBlock\:\:render_experimental_iapi_mini_cart_footer\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartFooterBlock.php
-
-
message: '#^Parameter \#1 \$query of method WP_HTML_Tag_Processor\:\:next_tag\(\) expects array\{tag_name\?\: string\|null, match_offset\?\: int\|null, class_name\?\: string\|null, tag_closers\?\: string\|null\}\|null, ''bdi'' given\.$#'
identifier: argument.type
count: 1
path: src/Blocks/BlockTypes/MiniCartFooterBlock.php
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartFooterBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartFooterBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartFooterBlock\:\:render_experimental_iapi_mini_cart_footer\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartFooterBlock.php
-
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartItemsBlock\:\:render_experimental_iapi_markup\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartItemsBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartItemsBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartItemsBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartItemsBlock\:\:render_experimental_iapi_markup\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartItemsBlock.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartProductsTableBlock\:\:render\(\) should return string but returns string\|false\.$#'
identifier: return.type
@@ -51387,78 +51177,12 @@ parameters:
count: 1
path: src/Blocks/BlockTypes/MiniCartProductsTableBlock.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartShoppingButtonBlock\:\:render_experimental_iapi_markup\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartShoppingButtonBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartShoppingButtonBlock\:\:render_experimental_iapi_markup\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
-
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleBlock\:\:render_experimental_iapi_title_block\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleBlock\:\:render_experimental_iapi_title_block\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleBlock.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleItemsCounterBlock\:\:get_cart_instance\(\) should return WC_Cart but returns null\.$#'
identifier: return.type
count: 1
path: src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleItemsCounterBlock\:\:render_experimental_iapi_title_label_block\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleItemsCounterBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php
-
- -
- message: '#^Method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleLabelBlock\:\:render_experimental_iapi_title_label_block\(\) should return string but returns string\|false\.$#'
- identifier: return.type
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleLabelBlock\:\:render\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php
-
- -
- message: '#^Parameter \$block of method Automattic\\WooCommerce\\Blocks\\BlockTypes\\MiniCartTitleLabelBlock\:\:render_experimental_iapi_title_label_block\(\) has invalid type Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
- identifier: class.notFound
- count: 1
- path: src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php
-
-
message: '#^Access to property \$context on an unknown class Automattic\\WooCommerce\\Blocks\\BlockTypes\\WP_Block\.$#'
identifier: class.notFound
@@ -56517,12 +56241,6 @@ parameters:
count: 1
path: src/Internal/Admin/FeaturePlugin.php
- -
- message: '#^Method Automattic\\WooCommerce\\Internal\\Admin\\FeaturePlugin\:\:replace_supported_features\(\) has no return type specified\.$#'
- identifier: missingType.return
- count: 1
- path: src/Internal/Admin/FeaturePlugin.php
-
-
message: '#^PHPDoc tag @var does not specify variable name\.$#'
identifier: varTag.noVariable
diff --git a/plugins/woocommerce/src/Admin/API/Init.php b/plugins/woocommerce/src/Admin/API/Init.php
index ace60c4ae1c..1de3bd82324 100644
--- a/plugins/woocommerce/src/Admin/API/Init.php
+++ b/plugins/woocommerce/src/Admin/API/Init.php
@@ -7,6 +7,7 @@ namespace Automattic\WooCommerce\Admin\API;
use AllowDynamicProperties;
use Automattic\WooCommerce\Admin\Features\Features;
+use Automattic\WooCommerce\Utilities\FeaturesUtil;
defined( 'ABSPATH' ) || exit;
@@ -66,11 +67,9 @@ class Init {
$rest_api_util = wc_get_container()->get( RestApiUtil::class );
$rest_api_util->lazy_load_namespace( 'wc-analytics', array( $this, 'rest_api_init_wc_analytics' ) );
- if ( Features::is_enabled( 'launch-your-store' ) ) {
- $controller = 'Automattic\WooCommerce\Admin\API\LaunchYourStore';
- $this->$controller = new $controller();
- $this->$controller->register_routes();
- }
+ $controller = 'Automattic\WooCommerce\Admin\API\LaunchYourStore';
+ $this->$controller = new $controller();
+ $this->$controller->register_routes();
}
/**
@@ -159,7 +158,7 @@ class Init {
);
$analytics_controllers = array();
- if ( Features::is_enabled( 'analytics' ) ) {
+ if ( FeaturesUtil::feature_is_enabled( 'analytics' ) ) {
$analytics_controllers = array(
'Automattic\WooCommerce\Admin\API\Customers',
'Automattic\WooCommerce\Admin\API\Leaderboards',
diff --git a/plugins/woocommerce/src/Admin/API/OnboardingTasks.php b/plugins/woocommerce/src/Admin/API/OnboardingTasks.php
index 46170b968bf..71411fc0f61 100644
--- a/plugins/woocommerce/src/Admin/API/OnboardingTasks.php
+++ b/plugins/woocommerce/src/Admin/API/OnboardingTasks.php
@@ -193,7 +193,7 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
'duration' => array(
'description' => __( 'Time period to snooze the task.', 'woocommerce' ),
'type' => 'string',
- 'validate_callback' => function( $param, $request, $key ) {
+ 'validate_callback' => function ( $param ) {
return in_array( $param, array_keys( $this->duration_to_ms ), true );
},
),
@@ -346,8 +346,7 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_Error|WP_REST_Response
*/
public static function import_sample_products() {
- $sample_csv_file = Features::is_enabled( 'experimental-fashion-sample-products' ) ? WC_ABSPATH . 'sample-data/experimental_fashion_sample_9_products.csv' :
- WC_ABSPATH . 'sample-data/experimental_sample_9_products.csv';
+ $sample_csv_file = WC_ABSPATH . 'sample-data/experimental_fashion_sample_9_products.csv';
$import = self::import_sample_products_from_csv( $sample_csv_file );
return rest_ensure_response( $import );
@@ -661,7 +660,8 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
'post_title' => __( 'Homepage', 'woocommerce' ),
'post_type' => 'page',
'post_status' => 'publish',
- 'post_content' => '', // Template content is updated below, so images can be attached to the post.
+ 'post_content' => '',
+ // Template content is updated below, so images can be attached to the post.
)
);
@@ -715,7 +715,7 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
$params['extended_tasks'] = array(
'description' => __( 'List of extended deprecated tasks from the client side filter.', 'woocommerce' ),
'type' => 'array',
- 'validate_callback' => function( $param, $request, $key ) {
+ 'validate_callback' => function ( $param ) {
$has_valid_keys = true;
foreach ( $param as $task ) {
if ( $has_valid_keys ) {
@@ -743,7 +743,7 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
$lists = is_array( $task_list_ids ) && count( $task_list_ids ) > 0 ? TaskLists::get_lists_by_ids( $task_list_ids ) : TaskLists::get_lists();
$json = array_map(
- function( $list ) {
+ function ( $list ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.listFound
return $list->sort_tasks()->get_json();
},
$lists
@@ -987,5 +987,4 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
$task->mark_actioned();
return rest_ensure_response( $task->get_json() );
}
-
}
diff --git a/plugins/woocommerce/src/Admin/Features/Features.php b/plugins/woocommerce/src/Admin/Features/Features.php
index 1f5ecf72fdb..ae534c8ae8e 100644
--- a/plugins/woocommerce/src/Admin/Features/Features.php
+++ b/plugins/woocommerce/src/Admin/Features/Features.php
@@ -6,7 +6,9 @@
namespace Automattic\WooCommerce\Admin\Features;
use Automattic\WooCommerce\Admin\PageController;
+use Automattic\WooCommerce\Internal\Admin\Analytics;
use Automattic\WooCommerce\Internal\Admin\Loader;
+use Automattic\WooCommerce\Internal\Admin\RemoteInboxNotifications;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;
use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -22,13 +24,134 @@ class Features {
protected static $instance = null;
/**
- * Optional features
+ * Version metadata for WC Admin feature flags kept for backward compatibility.
*
- * @var array
+ * Keep this dictionary in sync with RETIRED_FEATURE_FLAGS in
+ * plugins/woocommerce/client/admin/client/utils/features/retired-feature-flags.ts.
+ *
+ * @var array<string, array{deprecated_since: string, removed_in: ?string}>
*/
- protected static $optional_features = array(
- 'analytics' => array( 'default' => 'yes' ),
- 'remote-inbox-notifications' => array( 'default' => 'yes' ),
+ private static $retired_feature_compatibility_versions = array(
+ 'activity-panels' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'analytics' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'analytics-scheduled-import' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'experimental-iapi-mini-cart' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'coupons' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'core-profiler' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'customize-store' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'customer-effort-score-tracks' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'import-products-task' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'experimental-fashion-sample-products' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'shipping-smart-defaults' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'shipping-setting-tour' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'homescreen' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'marketing' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'mobile-app-banner' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'onboarding' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'onboarding-tasks' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'pattern-toolkit-full-composability' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'payment-gateway-suggestions' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'product-custom-fields' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'printful' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'remote-inbox-notifications' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'remote-free-extensions' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'shipping-label-banner' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'subscriptions' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'transient-notices' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'wc-pay-promotion' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'wc-pay-welcome-page' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'woo-mobile-welcome' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
+ 'launch-your-store' => array(
+ 'deprecated_since' => '11.1.0',
+ 'removed_in' => null,
+ ),
);
/**
@@ -70,19 +193,17 @@ class Features {
/**
* Gets the optional feature options as an associative array that can be toggled on or off.
*
+ * @deprecated 11.1.0 Use FeaturesUtil::feature_is_enabled() to check if a feature is enabled.
+ *
* @return array
*/
public static function get_optional_feature_options() {
- $features = array();
+ wc_deprecated_function( __METHOD__, '11.1.0', 'FeaturesUtil::feature_is_enabled()' );
- foreach ( array_keys( self::$optional_features ) as $optional_feature_key ) {
- $feature_class = self::get_feature_class( $optional_feature_key );
-
- if ( $feature_class ) {
- $features[ $optional_feature_key ] = $feature_class::TOGGLE_OPTION_NAME;
- }
- }
- return $features;
+ return array(
+ 'analytics' => Analytics::TOGGLE_OPTION_NAME,
+ 'remote-inbox-notifications' => RemoteInboxNotifications::TOGGLE_OPTION_NAME,
+ );
}
/**
@@ -92,7 +213,15 @@ class Features {
* @return bool Returns true if the feature exists.
*/
public static function exists( $feature ) {
- $features = self::get_features();
+ $is_legacy_compatibility_feature = self::is_legacy_compatibility_feature( $feature );
+
+ if ( $is_legacy_compatibility_feature ) {
+ self::warn_legacy_feature_compatibility_usage( __METHOD__, $feature );
+ }
+
+ $features = $is_legacy_compatibility_feature
+ ? self::get_features_with_legacy_compatibility_defaults()
+ : self::get_features();
return in_array( $feature, $features, true );
}
@@ -128,13 +257,45 @@ class Features {
return;
}
+ $always_loaded_feature_classes = array(
+ \Automattic\WooCommerce\Internal\Admin\ActivityPanels::class,
+ \Automattic\WooCommerce\Internal\Admin\Analytics::class,
+ \Automattic\WooCommerce\Internal\Admin\Coupons::class,
+ \Automattic\WooCommerce\Internal\Admin\CustomerEffortScoreTracks::class,
+ \Automattic\WooCommerce\Internal\Admin\Homescreen::class,
+ \Automattic\WooCommerce\Internal\Admin\Marketing::class,
+ \Automattic\WooCommerce\Internal\Admin\MobileAppBanner::class,
+ \Automattic\WooCommerce\Admin\Features\OnboardingTasks\Init::class,
+ \Automattic\WooCommerce\Internal\Admin\RemoteInboxNotifications::class,
+ \Automattic\WooCommerce\Internal\Admin\RemoteFreeExtensions\Init::class,
+ \Automattic\WooCommerce\Internal\Admin\ShippingLabelBanner::class,
+ \Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\Init::class,
+ \Automattic\WooCommerce\Admin\Features\TransientNotices::class,
+ \Automattic\WooCommerce\Internal\Admin\WCPayPromotion\Init::class,
+ \Automattic\WooCommerce\Internal\Admin\WcPayWelcomePage::class,
+ \Automattic\WooCommerce\Admin\Features\LaunchYourStore::class,
+ );
+
+ foreach ( $always_loaded_feature_classes as $feature_class ) {
+ new $feature_class();
+ }
+
$features = self::get_features();
foreach ( $features as $feature ) {
$feature_class = self::get_feature_class( $feature );
- if ( $feature_class ) {
- new $feature_class();
+ if ( ! $feature_class ) {
+ continue;
+ }
+
+ foreach ( $always_loaded_feature_classes as $loaded_feature_class ) {
+ if ( is_a( $feature_class, $loaded_feature_class, true ) ) {
+ // Skip the outer features loop because this feature was already loaded.
+ continue 2;
+ }
}
+
+ new $feature_class();
}
if ( FeaturesUtil::feature_is_enabled( 'blueprint' ) ) {
@@ -152,9 +313,13 @@ class Features {
* @return array Enabled Woocommerce Admin features/sections.
*/
public static function get_available_features() {
- $features = self::get_features();
- $optional_feature_keys = array_keys( self::$optional_features );
- $optional_features_unavailable = array();
+ $features = self::get_features_with_legacy_compatibility_defaults();
+ $optional_feature_keys = array( 'analytics', 'remote-inbox-notifications' );
+ $legacy_compatibility_values = self::get_legacy_feature_compatibility_values();
+ $unavailable_features = array();
+ $available_compatibility_keys = array_keys( array_filter( $legacy_compatibility_values ) );
+
+ $features = array_values( array_unique( array_merge( $features, $available_compatibility_keys ) ) );
/**
* Filter allowing WooCommerce Admin optional features to be disabled.
@@ -165,28 +330,21 @@ class Features {
return array_values( array_diff( $features, $optional_feature_keys ) );
}
- foreach ( $optional_feature_keys as $optional_feature_key ) {
- $feature_class = self::get_feature_class( $optional_feature_key );
-
- if ( $feature_class ) {
- $default = isset( self::$optional_features[ $optional_feature_key ]['default'] ) ?
- self::$optional_features[ $optional_feature_key ]['default'] :
- 'no';
-
- // Check if the feature is currently being enabled, if it is continue.
- /* phpcs:disable WordPress.Security.NonceVerification */
- $feature_option = $feature_class::TOGGLE_OPTION_NAME;
- if ( isset( $_POST[ $feature_option ] ) && '1' === $_POST[ $feature_option ] ) {
- continue;
- }
+ if (
+ in_array( 'analytics', $features, true ) &&
+ ! FeaturesUtil::feature_is_enabled( 'analytics' )
+ ) {
+ $unavailable_features[] = 'analytics';
+ }
- if ( 'yes' !== get_option( $feature_class::TOGGLE_OPTION_NAME, $default ) ) {
- $optional_features_unavailable[] = $optional_feature_key;
- }
- }
+ if (
+ in_array( 'remote-inbox-notifications', $features, true ) &&
+ 'yes' !== get_option( RemoteInboxNotifications::TOGGLE_OPTION_NAME, 'yes' )
+ ) {
+ $unavailable_features[] = 'remote-inbox-notifications';
}
- return array_values( array_diff( $features, $optional_features_unavailable ) );
+ return array_values( array_diff( $features, $unavailable_features ) );
}
/**
@@ -196,6 +354,10 @@ class Features {
* @return bool
*/
public static function is_enabled( $feature ) {
+ if ( self::is_legacy_compatibility_feature( $feature ) ) {
+ self::warn_legacy_feature_compatibility_usage( __METHOD__, $feature );
+ }
+
$available_features = self::get_available_features();
return in_array( $feature, $available_features, true );
}
@@ -203,14 +365,21 @@ class Features {
/**
* Enable a toggleable optional feature.
*
+ * @deprecated 11.1.0 Use FeaturesUtil::feature_is_enabled() to check if a feature is enabled.
+ *
* @param string $feature Feature name.
* @return bool
*/
public static function enable( $feature ) {
- $features = self::get_optional_feature_options();
+ wc_deprecated_function( __METHOD__, '11.1.0', 'FeaturesUtil::feature_is_enabled()' );
- if ( isset( $features[ $feature ] ) ) {
- update_option( $features[ $feature ], 'yes' );
+ if ( 'analytics' === $feature ) {
+ update_option( Analytics::TOGGLE_OPTION_NAME, 'yes' );
+ return true;
+ }
+
+ if ( 'remote-inbox-notifications' === $feature ) {
+ update_option( RemoteInboxNotifications::TOGGLE_OPTION_NAME, 'yes' );
return true;
}
@@ -220,14 +389,21 @@ class Features {
/**
* Disable a toggleable optional feature.
*
+ * @deprecated 11.1.0 Use FeaturesUtil::feature_is_enabled() to check if a feature is enabled.
+ *
* @param string $feature Feature name.
* @return bool
*/
public static function disable( $feature ) {
- $features = self::get_optional_feature_options();
+ wc_deprecated_function( __METHOD__, '11.1.0', 'FeaturesUtil::feature_is_enabled()' );
- if ( isset( $features[ $feature ] ) ) {
- update_option( $features[ $feature ], 'no' );
+ if ( 'analytics' === $feature ) {
+ update_option( Analytics::TOGGLE_OPTION_NAME, 'no' );
+ return true;
+ }
+
+ if ( 'remote-inbox-notifications' === $feature ) {
+ update_option( RemoteInboxNotifications::TOGGLE_OPTION_NAME, 'no' );
return true;
}
@@ -267,11 +443,14 @@ class Features {
return;
}
- $features = self::get_features();
- $enabled_features = array();
- foreach ( $features as $key ) {
- $enabled_features[ $key ] = self::is_enabled( $key );
+ $available_features = self::get_available_features();
+ $enabled_features = array();
+ foreach ( self::get_features() as $key ) {
+ $enabled_features[ $key ] = in_array( $key, $available_features, true );
}
+
+ $enabled_features = array_merge( $enabled_features, self::get_legacy_feature_compatibility_values() );
+
wp_add_inline_script( WC_ADMIN_APP, 'window.wcAdminFeatures = ' . wp_json_encode( $enabled_features, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), 'before' );
}
@@ -288,8 +467,7 @@ class Features {
$classes = explode( ' ', trim( $admin_body_class ) );
- $features = self::get_features();
- foreach ( $features as $feature_key ) {
+ foreach ( self::get_available_features() as $feature_key ) {
$classes[] = sanitize_html_class( 'woocommerce-feature-enabled-' . $feature_key );
}
@@ -297,6 +475,129 @@ class Features {
return " $admin_body_class ";
}
+ /**
+ * Gets legacy feature flag compatibility values.
+ *
+ * This method is intended for passive compatibility paths, such as script globals
+ * and filtering shared settings, where emitting deprecation notices would warn on
+ * every admin page load.
+ *
+ * @since 11.1.0
+ * @return array<string, bool>
+ */
+ public static function get_legacy_feature_compatibility_values() {
+ $compatibility_values = array_merge(
+ array_fill_keys( array_keys( self::$retired_feature_compatibility_versions ), true ),
+ array(
+ 'analytics' => FeaturesUtil::feature_is_enabled( 'analytics' ),
+ 'remote-inbox-notifications' => 'yes' === get_option( RemoteInboxNotifications::TOGGLE_OPTION_NAME, 'yes' ),
+ )
+ );
+
+ return array_intersect_key(
+ $compatibility_values,
+ array_flip( self::get_features_with_legacy_compatibility_defaults() )
+ );
+ }
+
+ /**
+ * Gets default legacy feature flag compatibility values before public filtering.
+ *
+ * @return array<string, bool>
+ */
+ private static function get_legacy_feature_compatibility_defaults() {
+ return array_merge(
+ array_fill_keys( array_keys( self::$retired_feature_compatibility_versions ), true ),
+ array(
+ 'analytics' => true,
+ 'remote-inbox-notifications' => true,
+ )
+ );
+ }
+
+ /**
+ * Gets WooCommerce Admin features with legacy compatibility defaults before public filtering.
+ *
+ * @return array Enabled Woocommerce Admin features/sections.
+ */
+ private static function get_features_with_legacy_compatibility_defaults() {
+ /**
+ * Filter allowing WooCommerce Admin features to be changed after legacy compatibility defaults are seeded.
+ *
+ * @since 11.1.0
+ *
+ * @param array $features Array of feature slugs.
+ */
+ return apply_filters( 'woocommerce_admin_features', array_keys( self::get_legacy_feature_compatibility_defaults() ) );
+ }
+
+ /**
+ * Checks if a feature slug is supported only by the legacy compatibility shim.
+ *
+ * @param string $feature Feature slug.
+ * @return bool
+ */
+ private static function is_legacy_compatibility_feature( $feature ) {
+ return array_key_exists( $feature, self::get_legacy_feature_compatibility_defaults() );
+ }
+
+ /**
+ * Gets version metadata for a legacy feature flag shim.
+ *
+ * @param string $feature Feature slug.
+ * @return array{deprecated_since: string, removed_in: ?string}|null
+ */
+ private static function get_legacy_feature_compatibility_versions( $feature ) {
+ return self::$retired_feature_compatibility_versions[ $feature ] ?? null;
+ }
+
+ /**
+ * Gets the WooCommerce version where a legacy feature flag shim was deprecated.
+ *
+ * @param string $feature Feature slug.
+ * @return string|null
+ */
+ private static function get_legacy_feature_compatibility_deprecation_version( $feature ) {
+ $versions = self::get_legacy_feature_compatibility_versions( $feature );
+ return $versions['deprecated_since'] ?? null;
+ }
+
+ /**
+ * Gets the WooCommerce version where a legacy feature flag shim will be removed.
+ *
+ * @param string $feature Feature slug.
+ * @return string|null
+ */
+ private static function get_legacy_feature_compatibility_removal_version( $feature ) {
+ $versions = self::get_legacy_feature_compatibility_versions( $feature );
+ return $versions['removed_in'] ?? null;
+ }
+
+ /**
+ * Emits a deprecation notice for a direct legacy feature flag shim lookup.
+ *
+ * @param string $method Method name.
+ * @param string $feature Feature slug.
+ */
+ private static function warn_legacy_feature_compatibility_usage( $method, $feature ): void {
+ $deprecation_version = self::get_legacy_feature_compatibility_deprecation_version( $feature );
+ $removal_version = self::get_legacy_feature_compatibility_removal_version( $feature );
+
+ if ( ! $deprecation_version ) {
+ return;
+ }
+
+ wc_deprecated_function(
+ sprintf( "%s( '%s' )", $method, $feature ),
+ $deprecation_version,
+ sprintf(
+ 'direct feature behavior checks. The %1$s WC Admin feature flag shim will be removed in %2$s.',
+ $feature,
+ $removal_version ? 'WooCommerce ' . $removal_version : 'a future version of WooCommerce'
+ )
+ );
+ }
+
/**
* Alias internal features classes to make them backward compatible.
* We've moved our feature classes to src-internal as part of merging this
diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/TaskLists.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/TaskLists.php
index 46bf94d5d59..20c044f4cb4 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/TaskLists.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/TaskLists.php
@@ -5,7 +5,6 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\ReviewShippingOptions;
use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -117,11 +116,9 @@ class TaskLists {
'LaunchYourStore',
);
- if ( Features::is_enabled( 'core-profiler' ) ) {
- $key = array_search( 'StoreDetails', $tasks, true );
- if ( false !== $key ) {
- unset( $tasks[ $key ] );
- }
+ $key = array_search( 'StoreDetails', $tasks, true );
+ if ( false !== $key ) {
+ unset( $tasks[ $key ] );
}
self::add_list(
@@ -161,28 +158,26 @@ class TaskLists {
)
);
- if ( Features::is_enabled( 'shipping-smart-defaults' ) ) {
- self::add_task(
- 'extended',
- new ReviewShippingOptions(
- self::get_list( 'extended' )
- )
- );
+ self::add_task(
+ 'extended',
+ new ReviewShippingOptions(
+ self::get_list( 'extended' )
+ )
+ );
- // Tasklist that will never be shown in homescreen,
- // used for having tasks that are accessed by other means.
- self::add_list(
- array(
- 'id' => 'secret_tasklist',
- 'hidden_id' => 'setup',
- 'tasks' => array(
- 'ExperimentalShippingRecommendation',
- ),
- 'event_prefix' => 'secret_tasklist_',
- 'visible' => false,
- )
- );
- }
+ // Tasklist that will never be shown in homescreen,
+ // used for having tasks that are accessed by other means.
+ self::add_list(
+ array(
+ 'id' => 'secret_tasklist',
+ 'hidden_id' => 'setup',
+ 'tasks' => array(
+ 'ExperimentalShippingRecommendation',
+ ),
+ 'event_prefix' => 'secret_tasklist_',
+ 'visible' => false,
+ )
+ );
if ( has_filter( 'woocommerce_admin_experimental_onboarding_tasklists' ) ) {
/**
diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendation.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendation.php
index d609fef0091..b1a841b947b 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendation.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendation.php
@@ -3,7 +3,6 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\Jetpack\Connection\Manager;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Internal\Jetpack\JetpackConnection;
@@ -63,7 +62,7 @@ class ExperimentalShippingRecommendation extends Task {
* @return bool
*/
public function can_view() {
- return Features::is_enabled( 'shipping-smart-defaults' );
+ return true;
}
/**
diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/LaunchYourStore.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/LaunchYourStore.php
index cbbcb38b4f0..3b3bad0a278 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/LaunchYourStore.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/LaunchYourStore.php
@@ -2,7 +2,6 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
@@ -83,7 +82,7 @@ class LaunchYourStore extends Task {
* @return bool
*/
public function can_view() {
- return Features::is_enabled( 'launch-your-store' );
+ return true;
}
/**
diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Marketing.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Marketing.php
index 11be6d22716..bfd4117e4a2 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Marketing.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Marketing.php
@@ -2,7 +2,6 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
@@ -92,7 +91,7 @@ class Marketing extends Task {
* @return bool
*/
public function can_view() {
- return Features::is_enabled( 'remote-free-extensions' );
+ return true;
}
/**
diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Shipping.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Shipping.php
index de27eaebab2..e38585e76ea 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Shipping.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Shipping.php
@@ -2,7 +2,6 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use WC_Data_Store;
@@ -84,42 +83,38 @@ class Shipping extends Task {
* @return bool
*/
public function can_view() {
- if ( Features::is_enabled( 'shipping-smart-defaults' ) ) {
- if ( 'yes' === get_option( 'woocommerce_admin_created_default_shipping_zones' ) ) {
- // If the user has already created a default shipping zone, we don't need to show the task.
- return false;
- }
-
- /**
- * Do not display the task when:
- * - The store sells digital products only
- * Display the task when:
- * - We don't know where the store's located
- * - The store is located in the UK, Australia or Canada
- */
-
- if ( self::is_selling_digital_type_only() ) {
- return false;
- }
-
- $default_store_country = wc_format_country_state_string( get_option( 'woocommerce_default_country', '' ) )['country'];
-
- // Check if a store address is set so that we don't default to WooCommerce's default country US.
- // Similar logic: https://github.com/woocommerce/woocommerce/blob/059d542394b48468587f252dcb6941c6425cd8d3/plugins/woocommerce-admin/client/profile-wizard/steps/store-details/index.js#L511-L516.
- $store_country = '';
- if ( ! empty( get_option( 'woocommerce_store_address', '' ) ) || 'US' !== $default_store_country ) {
- $store_country = $default_store_country;
- }
-
- // Unknown country.
- if ( empty( $store_country ) ) {
- return true;
- }
-
- return in_array( $store_country, array( 'US', 'CA', 'AU', 'NZ', 'SG', 'HK', 'GB', 'ES', 'IT', 'DE', 'FR', 'MX', 'CO', 'CL', 'AR', 'PE', 'BR', 'UY', 'GT', 'NL', 'AT', 'BE', 'IE', 'PT' ), true );
+ if ( 'yes' === get_option( 'woocommerce_admin_created_default_shipping_zones' ) ) {
+ // If the user has already created a default shipping zone, we don't need to show the task.
+ return false;
}
- return self::has_physical_products();
+ /**
+ * Do not display the task when:
+ * - The store sells digital products only
+ * Display the task when:
+ * - We don't know where the store's located
+ * - The store is located in the UK, Australia or Canada
+ */
+
+ if ( self::is_selling_digital_type_only() ) {
+ return false;
+ }
+
+ $default_store_country = wc_format_country_state_string( get_option( 'woocommerce_default_country', '' ) )['country'];
+
+ // Check if a store address is set so that we don't default to WooCommerce's default country US.
+ // Similar logic: https://github.com/woocommerce/woocommerce/blob/059d542394b48468587f252dcb6941c6425cd8d3/plugins/woocommerce-admin/client/profile-wizard/steps/store-details/index.js#L511-L516.
+ $store_country = '';
+ if ( ! empty( get_option( 'woocommerce_store_address', '' ) ) || 'US' !== $default_store_country ) {
+ $store_country = $default_store_country;
+ }
+
+ // Unknown country.
+ if ( empty( $store_country ) ) {
+ return true;
+ }
+
+ return in_array( $store_country, array( 'US', 'CA', 'AU', 'NZ', 'SG', 'HK', 'GB', 'ES', 'IT', 'DE', 'FR', 'MX', 'CO', 'CL', 'AR', 'PE', 'BR', 'UY', 'GT', 'NL', 'AT', 'BE', 'IE', 'PT' ), true );
}
/**
diff --git a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngine.php b/plugins/woocommerce/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngine.php
index d128d316dde..8b724c1140e 100644
--- a/plugins/woocommerce/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngine.php
+++ b/plugins/woocommerce/src/Admin/RemoteInboxNotifications/RemoteInboxNotificationsEngine.php
@@ -7,7 +7,6 @@ namespace Automattic\WooCommerce\Admin\RemoteInboxNotifications;
defined( 'ABSPATH' ) || exit;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Notes\Notes;
use Automattic\WooCommerce\Admin\PluginsProvider\PluginsProvider;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
@@ -256,11 +255,6 @@ class RemoteInboxNotificationsEngine extends RemoteSpecsEngine {
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
*/
public static function add_debug_tools( $tools ) {
- // Check if the feature flag is disabled.
- if ( ! Features::is_enabled( 'remote-inbox-notifications' ) ) {
- return false;
- }
-
// Check if the site has opted out of marketplace suggestions.
if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) !== 'yes' ) {
return false;
diff --git a/plugins/woocommerce/src/Blocks/BlockPatterns.php b/plugins/woocommerce/src/Blocks/BlockPatterns.php
index 1a3c939fc44..a68b561a5f5 100644
--- a/plugins/woocommerce/src/Blocks/BlockPatterns.php
+++ b/plugins/woocommerce/src/Blocks/BlockPatterns.php
@@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Automattic\WooCommerce\Blocks;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Blocks\Domain\Package;
use Automattic\WooCommerce\Blocks\Patterns\PatternRegistry;
use Automattic\WooCommerce\Blocks\Patterns\PTKPatternsStore;
@@ -74,10 +73,7 @@ class BlockPatterns {
$this->ptk_patterns_store = $ptk_patterns_store;
add_action( 'init', array( $this, 'register_block_patterns' ) );
-
- if ( Features::is_enabled( 'pattern-toolkit-full-composability' ) ) {
- add_action( 'init', array( $this, 'register_ptk_patterns' ) );
- }
+ add_action( 'init', array( $this, 'register_ptk_patterns' ) );
}
/**
@@ -144,7 +140,6 @@ class BlockPatterns {
'keywords' => 'Keywords',
'blockTypes' => 'Block Types',
'inserter' => 'Inserter',
- 'featureFlag' => 'Feature Flag',
'templateTypes' => 'Template Types',
);
diff --git a/plugins/woocommerce/src/Blocks/BlockTemplatesRegistry.php b/plugins/woocommerce/src/Blocks/BlockTemplatesRegistry.php
index ce83120aef8..34116825a98 100644
--- a/plugins/woocommerce/src/Blocks/BlockTemplatesRegistry.php
+++ b/plugins/woocommerce/src/Blocks/BlockTemplatesRegistry.php
@@ -2,7 +2,6 @@
declare( strict_types=1 );
namespace Automattic\WooCommerce\Blocks;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
use Automattic\WooCommerce\Blocks\Templates\AbstractTemplate;
use Automattic\WooCommerce\Blocks\Templates\AbstractTemplatePart;
@@ -59,9 +58,7 @@ class BlockTemplatesRegistry {
} else {
$templates = array();
}
- if ( Features::is_enabled( 'launch-your-store' ) ) {
- $templates[ ComingSoonTemplate::SLUG ] = new ComingSoonTemplate();
- }
+ $templates[ ComingSoonTemplate::SLUG ] = new ComingSoonTemplate();
if ( BlockTemplateUtils::supports_block_templates( 'wp_template_part' ) ) {
$template_parts = array(
MiniCartTemplate::SLUG => new MiniCartTemplate(),
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php
index f32605682d7..1d6924ea770 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/EmptyMiniCartContentsBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* EmptyMiniCartContentsBlock class.
*/
@@ -15,30 +13,14 @@ class EmptyMiniCartContentsBlock extends AbstractInnerBlock {
protected $block_name = 'empty-mini-cart-contents-block';
/**
- * Render the markup for the Filled Mini-Cart Contents block.
+ * Render the markup for the Empty Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_empty_mini_cart_contents( $attributes, $content, $block );
- }
-
- return $content;
- }
-
- /**
- * Render the experimental interactivity API powered Filled Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_empty_mini_cart_contents( $attributes, $content, $block ) {
$wrapper_attributes = get_block_wrapper_attributes(
array(
'data-wp-bind--aria-hidden' => '!state.cartIsEmpty',
@@ -58,6 +40,6 @@ class EmptyMiniCartContentsBlock extends AbstractInnerBlock {
</div>
</div>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php
index dbc122d47d3..66c62f87bf5 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/FilledMiniCartContentsBlock.php
@@ -1,7 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Blocks\Utils\BlocksSharedState;
/**
@@ -18,28 +17,12 @@ class FilledMiniCartContentsBlock extends AbstractInnerBlock {
/**
* Render the markup for the Filled Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_filled_mini_cart_contents( $attributes, $content, $block );
- }
-
- return $content;
- }
-
- /**
- * Render the experimental interactivity API powered Filled Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_filled_mini_cart_contents( $attributes, $content, $block ) {
$consent = 'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WooCommerce';
$notices = BlocksSharedState::get_cart_error_notices( $consent );
@@ -105,6 +88,6 @@ class FilledMiniCartContentsBlock extends AbstractInnerBlock {
?>
</div>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
index 3628e5fa1c6..98e9bb03e52 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Automattic\WooCommerce\Blocks\BlockTypes;
use Automattic\WooCommerce\Blocks\Package;
-use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi;
use Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry;
@@ -26,6 +25,7 @@ use Automattic\Block_Delimiter;
*/
class MiniCart extends AbstractBlock {
use BlockHooksTrait;
+ use EnableBlockJsonAssetsTrait;
/**
* Block name.
@@ -34,20 +34,6 @@ class MiniCart extends AbstractBlock {
*/
protected $block_name = 'mini-cart';
- /**
- * Chunks build folder.
- *
- * @var string
- */
- protected $chunks_folder = 'mini-cart-contents-block';
-
- /**
- * Array of scripts that will be lazy loaded when interacting with the block.
- *
- * @var string[]
- */
- protected $scripts_to_lazy_load = array();
-
/**
* Inc Tax label.
*
@@ -116,28 +102,8 @@ class MiniCart extends AbstractBlock {
protected function initialize() {
parent::initialize();
add_action( 'wp_loaded', array( $this, 'register_empty_cart_message_block_pattern' ) );
- add_action( 'wp_print_footer_scripts', array( $this, 'print_lazy_load_scripts' ), 2 );
add_filter( 'hooked_block_woocommerce/mini-cart', array( $this, 'modify_hooked_block_attributes' ), 10, 5 );
add_filter( 'hooked_block_types', array( $this, 'register_hooked_block' ), 9, 4 );
-
- // Priority 20 ensures this runs after WooCommerce block registration (priority 10)
- // allowing us to modify the block supports in the registry after registration is complete.
- add_action( 'init', array( $this, 'enable_interactivity_support' ), 20 );
- }
-
- /**
- * Enable interactivity through Block Supports API. We're using WP_Block_Type_Registry instead
- * of get_block_type_supports method available in AbstractBlock as the latter works only for
- * blocks without static block.json metadata.
- */
- public function enable_interactivity_support() {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- $block_type = \WP_Block_Type_Registry::get_instance()->get_registered( 'woocommerce/mini-cart' );
-
- if ( $block_type ) {
- $block_type->supports['interactivity'] = true;
- }
- }
}
/**
@@ -185,28 +151,10 @@ class MiniCart extends AbstractBlock {
*
* @see $this->register_block_type()
* @param string $key Data to get, or default to everything.
- * @return array|string
+ * @return null
*/
protected function get_block_type_script( $key = null ) {
- if ( is_cart() || is_checkout() || Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return;
- }
-
- $script = array(
- 'handle' => 'wc-' . $this->block_name . '-block-frontend',
- 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name . '-frontend' ),
- 'dependencies' => array(),
- );
- return $key ? $script[ $key ] : $script;
- }
-
- /**
- * Get the frontend style handle for this block type.
- *
- * @return string[]
- */
- protected function get_block_type_style() {
- return array_merge( parent::get_block_type_style(), array( 'wc-blocks-packages-style' ) );
+ return null;
}
/**
@@ -288,148 +236,6 @@ class MiniCart extends AbstractBlock {
do_action( 'woocommerce_blocks_cart_enqueue_data' );
}
- /**
- * Prints the variable containing information about the scripts to lazy load.
- */
- public function print_lazy_load_scripts() {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return;
- }
-
- $script_data = $this->asset_api->get_script_data( 'assets/client/blocks/mini-cart-component-frontend.js' );
-
- $num_dependencies = is_countable( $script_data['dependencies'] ) ? count( $script_data['dependencies'] ) : 0;
- $wp_scripts = wp_scripts();
-
- for ( $i = 0; $i < $num_dependencies; $i++ ) {
- $dependency = $script_data['dependencies'][ $i ];
-
- foreach ( $wp_scripts->registered as $script ) {
- if ( $script->handle === $dependency ) {
- $this->append_script_and_deps_src( $script );
- break;
- }
- }
- }
-
- $payment_method_registry = Package::container()->get( PaymentMethodRegistry::class );
- $payment_methods = $payment_method_registry->get_all_active_payment_method_script_dependencies();
-
- foreach ( $payment_methods as $payment_method ) {
- $payment_method_script = $this->get_script_from_handle( $payment_method );
-
- if ( ! is_null( $payment_method_script ) ) {
- $this->append_script_and_deps_src( $payment_method_script );
- }
- }
-
- $this->scripts_to_lazy_load['wc-block-mini-cart-component-frontend'] = array(
- 'src' => $script_data['src'],
- 'version' => $script_data['version'],
- 'translations' => $this->get_inner_blocks_translations(),
- );
-
- $inner_blocks_frontend_scripts = array();
- $cart = $this->get_cart_instance();
- if ( $cart ) {
- // Preload inner blocks frontend scripts.
- $inner_blocks_frontend_scripts = $cart->is_empty() ? array(
- 'empty-cart-frontend',
- 'filled-cart-frontend',
- 'shopping-button-frontend',
- ) : array(
- 'empty-cart-frontend',
- 'filled-cart-frontend',
- 'title-frontend',
- 'items-frontend',
- 'footer-frontend',
- 'products-table-frontend',
- 'cart-button-frontend',
- 'checkout-button-frontend',
- 'title-label-frontend',
- 'title-items-counter-frontend',
- );
- }
- foreach ( $inner_blocks_frontend_scripts as $inner_block_frontend_script ) {
- $script_data = $this->asset_api->get_script_data( 'assets/client/blocks/mini-cart-contents-block/' . $inner_block_frontend_script . '.js' );
- $this->scripts_to_lazy_load[ 'wc-block-' . $inner_block_frontend_script ] = array(
- 'src' => $script_data['src'],
- 'version' => $script_data['version'],
- );
- }
-
- $data = rawurlencode( wp_json_encode( $this->scripts_to_lazy_load ) );
- $mini_cart_dependencies_script = "var wcBlocksMiniCartFrontendDependencies = JSON.parse( decodeURIComponent( '" . esc_js( $data ) . "' ) );";
-
- wp_add_inline_script(
- 'wc-mini-cart-block-frontend',
- $mini_cart_dependencies_script,
- 'before'
- );
- }
-
- /**
- * Returns the script data given its handle.
- *
- * @param string $handle Handle of the script.
- *
- * @return \_WP_Dependency|null Object containing the script data if found, or null.
- */
- protected function get_script_from_handle( $handle ) {
- $wp_scripts = wp_scripts();
- foreach ( $wp_scripts->registered as $script ) {
- if ( $script->handle === $handle ) {
- return $script;
- }
- }
- return null;
- }
-
- /**
- * Recursively appends a scripts and its dependencies into the scripts_to_lazy_load array.
- *
- * @param \_WP_Dependency $script Object containing script data.
- */
- protected function append_script_and_deps_src( $script ) {
- $wp_scripts = wp_scripts();
-
- // This script and its dependencies have already been appended.
- if ( ! $script || array_key_exists( $script->handle, $this->scripts_to_lazy_load ) || wp_script_is( $script->handle, 'enqueued' ) ) {
- return;
- }
-
- if ( is_countable( $script->deps ) && count( $script->deps ) ) {
- foreach ( $script->deps as $dep ) {
- if ( ! array_key_exists( $dep, $this->scripts_to_lazy_load ) ) {
- $dep_script = $this->get_script_from_handle( $dep );
-
- if ( ! is_null( $dep_script ) ) {
- $this->append_script_and_deps_src( $dep_script );
- }
- }
- }
- }
- if ( ! $script->src ) {
- return;
- }
-
- if ( Utils::wp_version_compare( '6.3', '>=' ) ) {
- $script_before = $wp_scripts->get_inline_script_data( $script->handle, 'before' );
- $script_after = $wp_scripts->get_inline_script_data( $script->handle, 'after' );
- } else {
- $script_before = $wp_scripts->print_inline_script( $script->handle, 'before', false );
- $script_after = $wp_scripts->print_inline_script( $script->handle, 'after', false );
- }
-
- $this->scripts_to_lazy_load[ $script->handle ] = array(
- 'src' => Utils::get_absolute_script_url( $script->src ),
- 'version' => $script->ver,
- 'before' => $script_before,
- 'after' => $script_after,
- 'translations' => $wp_scripts->print_translations( $script->handle, false ),
- );
- }
-
/**
* Returns the markup for the cart price.
*
@@ -465,9 +271,9 @@ class MiniCart extends AbstractBlock {
/**
* Render the Mini-Cart block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
@@ -483,23 +289,10 @@ class MiniCart extends AbstractBlock {
* In the cart and checkout pages, the block is either rendered hidden or removed.
* It is not interactive, so it can fall back to the existing implementation.
*/
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) && ! is_cart() && ! is_checkout() ) {
- return $this->render_experimental_iapi_mini_cart( $attributes, $content, $block );
+ if ( is_cart() || is_checkout() ) {
+ return $content . $this->get_markup( MiniCartUtils::migrate_attributes_to_color_panel( $attributes ) );
}
- return $content . $this->get_markup( MiniCartUtils::migrate_attributes_to_color_panel( $attributes ) );
- }
-
-
- /**
- * Render an experimental interactivity API powered Mini-Cart block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_iapi_mini_cart( $attributes, $content, $block ) {
wp_enqueue_script_module( $this->get_full_block_name() );
// Enqueue all integration scripts registered for this block.
@@ -516,14 +309,15 @@ class MiniCart extends AbstractBlock {
$cart = $this->get_cart_instance();
if ( $cart ) {
- $classes_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
- $icon_color = isset( $attributes['iconColor']['color'] ) ? esc_attr( $attributes['iconColor']['color'] ) : 'currentColor';
- $product_count_color = isset( $attributes['productCountColor']['color'] ) ? $attributes['productCountColor']['color'] : '';
- $styles = $product_count_color ? 'background:' . esc_attr( $product_count_color ) : '';
- $icon = MiniCartUtils::get_svg_icon( $attributes['miniCartIcon'] ?? '', $icon_color );
- $product_count_visibility = isset( $attributes['productCountVisibility'] ) ? $attributes['productCountVisibility'] : 'greater_than_zero';
- $wrapper_classes = sprintf( 'wc-block-mini-cart wp-block-woocommerce-mini-cart %s', $classes_styles['classes'] );
- $wrapper_styles = $classes_styles['styles'];
+ $classes_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
+ $icon_color = isset( $attributes['iconColor']['color'] ) ? esc_attr( $attributes['iconColor']['color'] ) : 'currentColor';
+ $product_count_color = isset( $attributes['productCountColor']['color'] ) ? $attributes['productCountColor']['color'] : '';
+ $styles = $product_count_color ? 'background:' . esc_attr( $product_count_color ) : '';
+ $icon = MiniCartUtils::get_svg_icon( $attributes['miniCartIcon'] ?? '', $icon_color );
+ $product_count_visibility = isset( $attributes['productCountVisibility'] ) ? $attributes['productCountVisibility'] : 'greater_than_zero';
+ $wrapper_classes = sprintf( 'wc-block-mini-cart wp-block-woocommerce-mini-cart %s', $classes_styles['classes'] );
+ $wrapper_styles = $classes_styles['styles'];
+ // Pre-render the template part so nested blocks enqueue their assets before the overlay is printed in wp_footer.
$template_part_contents = $this->get_template_part_contents( false );
$template_part_contents = do_blocks( $this->process_template_contents( $template_part_contents ) );
$cart_item_count = $cart ? $cart->get_cart_contents_count() : 0;
@@ -592,12 +386,12 @@ class MiniCart extends AbstractBlock {
: '';
// Render the minicart overlay in the body, outside of the block itself.
- if ( ! has_action( 'wp_footer', array( $this, 'render_experimental_iapi_mini_cart_overlay' ) ) ) {
- add_action( 'wp_footer', array( $this, 'render_experimental_iapi_mini_cart_overlay' ) );
+ if ( ! has_action( 'wp_footer', array( $this, 'render_mini_cart_overlay' ) ) ) {
+ add_action( 'wp_footer', array( $this, 'render_mini_cart_overlay' ) );
}
ob_start();
?>
-
+
<div
data-wp-interactive="woocommerce/mini-cart"
data-wp-init="callbacks.setupJQueryEventBridge"
@@ -652,7 +446,7 @@ class MiniCart extends AbstractBlock {
</button>
</div>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
return '';
@@ -661,9 +455,10 @@ class MiniCart extends AbstractBlock {
/**
* Echoes the Interactivity API Mini Cart overlay markup.
*
+ * @since 11.1.0
* @return void
*/
- public function render_experimental_iapi_mini_cart_overlay() {
+ public function render_mini_cart_overlay() {
$template_part_contents = $this->get_template_part_contents( false );
$template_part_contents = do_blocks( $this->process_template_contents( $template_part_contents ) );
ob_start();
@@ -693,7 +488,7 @@ class MiniCart extends AbstractBlock {
</div>
</div>
</div>
- </div>
+ </div>
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo wp_interactivity_process_directives( ob_get_clean() );
@@ -913,29 +708,6 @@ class MiniCart extends AbstractBlock {
);
}
- /**
- * Prepare translations for inner blocks and dependencies.
- */
- protected function get_inner_blocks_translations() {
- $wp_scripts = wp_scripts();
- $translations = array();
-
- $chunks = $this->get_chunks_paths( $this->chunks_folder );
- $vendor_chunks = $this->get_chunks_paths( 'vendors--mini-cart-contents-block' );
- $shared_chunks = array( 'cart-blocks/cart-line-items--mini-cart-contents-block/products-table-frontend' );
-
- foreach ( array_merge( $chunks, $vendor_chunks, $shared_chunks ) as $chunk ) {
- $handle = 'wc-blocks-' . $chunk . '-chunk';
- $this->asset_api->register_script( $handle, $this->asset_api->get_block_asset_build_path( $chunk ), array(), true );
- $translations[] = $wp_scripts->print_translations( $handle, false );
- wp_deregister_script( $handle );
- }
-
- $translations = array_filter( $translations );
-
- return implode( "\n", $translations );
- }
-
/**
* Register block pattern for Empty Cart Message to make it translatable.
*/
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCartButtonBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
index 62d7ea1922f..486b79d6b79 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCartButtonBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartCartButtonBlock class.
*/
@@ -15,14 +13,14 @@ class MiniCartCartButtonBlock extends AbstractInnerBlock {
protected $block_name = 'mini-cart-cart-button-block';
/**
- * Render experimental iAPI block markup.
+ * Render the markup for the Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
- protected function render_experimental_iapi_markup( $attributes, $content, $block ) {
+ protected function render( $attributes, $content, $block ) {
$default_view_cart_text = __( 'View my cart', 'woocommerce' );
$view_cart_text = $attributes['cartButtonLabel'] ? $attributes['cartButtonLabel'] : $default_view_cart_text;
$cart_page_id = wc_get_page_id( 'cart' );
@@ -54,22 +52,6 @@ class MiniCartCartButtonBlock extends AbstractInnerBlock {
</div>
</a>
<?php
- return ob_get_clean();
- }
-
- /**
- * Render the markup for the Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_markup( $attributes, $content, $block );
- }
-
- return $content;
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
index b2861c9be61..f64d3fa7950 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartCheckoutButtonBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartCheckoutButtonBlock class.
*/
@@ -15,14 +13,14 @@ class MiniCartCheckoutButtonBlock extends AbstractInnerBlock {
protected $block_name = 'mini-cart-checkout-button-block';
/**
- * Render experimental iAPI block markup.
+ * Render the markup for the Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
- protected function render_experimental_iapi_markup( $attributes, $content, $block ) {
+ protected function render( $attributes, $content, $block ) {
$default_go_to_checkout_text = __( 'Go to checkout', 'woocommerce' );
$go_to_checkout_text = $attributes['checkoutButtonLabel'] ? $attributes['checkoutButtonLabel'] : $default_go_to_checkout_text;
$checkout_page_id = wc_get_page_id( 'checkout' );
@@ -42,22 +40,6 @@ class MiniCartCheckoutButtonBlock extends AbstractInnerBlock {
</div>
</a>
<?php
- return ob_get_clean();
- }
-
- /**
- * Render the markup for the Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_markup( $attributes, $content, $block );
- }
-
- return $content;
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartContents.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartContents.php
index 7d1fb90db99..5fef6015faf 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartContents.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartContents.php
@@ -1,7 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
/**
@@ -56,14 +55,20 @@ class MiniCartContents extends AbstractBlock {
}
/**
- * Render experimental iAPI powered Mini-Cart Contents block.
+ * Render the markup for the Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
- protected function render_experimental_iapi_mini_cart_contents( $attributes, $content, $block ) {
+ protected function render( $attributes, $content, $block ) {
+ if ( is_admin() || WC()->is_rest_api_request() ) {
+ // In the editor we will display the placeholder, so no need to
+ // print the markup.
+ return '';
+ }
+
$wrapper_attributes = get_block_wrapper_attributes(
array(
'data-wp-interactive' => 'woocommerce/mini-cart-contents',
@@ -87,37 +92,15 @@ class MiniCartContents extends AbstractBlock {
?>
</div>
<?php
- return ob_get_clean();
- }
-
- /**
- * Render the markup for the Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render( $attributes, $content, $block ) {
- if ( is_admin() || WC()->is_rest_api_request() ) {
- // In the editor we will display the placeholder, so no need to
- // print the markup.
- return '';
- }
-
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_mini_cart_contents( $attributes, $content, $block );
- }
-
- return $content;
+ return (string) ob_get_clean();
}
/**
* Enqueue frontend assets for this block, just in time for rendering.
*
- * @param array $attributes Any attributes that currently are available from the block.
- * @param string $content The block content.
- * @param WP_Block $block The block object.
+ * @param array $attributes Any attributes that currently are available from the block.
+ * @param string $content The block content.
+ * @param \WP_Block $block The block object.
*/
protected function enqueue_assets( array $attributes, $content, $block ) {
parent::enqueue_assets( $attributes, $content, $block );
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartFooterBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartFooterBlock.php
index ecf14b2cd3a..95d1b68586a 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartFooterBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartFooterBlock.php
@@ -1,9 +1,9 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Enums\TaxDisplayMode;
+
/**
* MiniCartFooterBlock class.
*/
@@ -31,14 +31,14 @@ class MiniCartFooterBlock extends AbstractInnerBlock {
}
/**
- * Render experimental iAPI powered Mini-Cart Footer block.
+ * Render the markup for the Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
- protected function render_experimental_iapi_mini_cart_footer( $attributes, $content, $block ) {
+ protected function render( $attributes, $content, $block ) {
ob_start();
$cart = $this->get_cart_instance();
@@ -95,7 +95,7 @@ class MiniCartFooterBlock extends AbstractInnerBlock {
</div>
</div>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
/**
@@ -173,20 +173,4 @@ class MiniCartFooterBlock extends AbstractInnerBlock {
// None enabled.
return '';
}
-
- /**
- * Render the markup for the Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_mini_cart_footer( $attributes, $content, $block );
- }
-
- return $content;
- }
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartItemsBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartItemsBlock.php
index 9dcdaf3aec5..c0f910e7dc6 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartItemsBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartItemsBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartItemsBlock class.
*/
@@ -17,28 +15,12 @@ class MiniCartItemsBlock extends AbstractInnerBlock {
/**
* Render the markup for the Mini-Cart Contents block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_markup( $attributes, $content, $block );
- }
-
- return $content;
- }
-
- /**
- * Render experimental iAPI block markup.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_iapi_markup( $attributes, $content, $block ) {
$wrapper_attributes = get_block_wrapper_attributes(
array(
'class' => 'wc-block-mini-cart__items',
@@ -52,6 +34,6 @@ class MiniCartItemsBlock extends AbstractInnerBlock {
<?php echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
index eb25cf2a568..53610e11a05 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartShoppingButtonBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartShoppingButtonBlock class.
*/
@@ -17,28 +15,12 @@ class MiniCartShoppingButtonBlock extends AbstractInnerBlock {
/**
* Render the markup for the Mini-Cart Shopping Button block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_markup( $attributes, $content, $block );
- }
-
- return $content;
- }
-
- /**
- * Render experimental iAPI powered markup for the Mini-Cart Contents block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_iapi_markup( $attributes, $content, $block ) {
ob_start();
$shop_url = wc_get_page_permalink( 'shop' );
$default_start_shopping_label = __( 'Start shopping', 'woocommerce' );
@@ -56,6 +38,6 @@ class MiniCartShoppingButtonBlock extends AbstractInnerBlock {
</a>
</div>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleBlock.php
index 7b0172eeee9..77104dfba87 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartTitleBlock class.
*/
@@ -17,27 +15,12 @@ class MiniCartTitleBlock extends AbstractInnerBlock {
/**
* Render the block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_title_block( $attributes, $content, $block );
- }
- return $content;
- }
-
- /**
- * Render the interactivity API powered experimental title block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_iapi_title_block( $attributes, $content, $block ) {
$wrapper_attributes = get_block_wrapper_attributes(
array(
'class' => 'wc-block-mini-cart__title',
@@ -52,6 +35,6 @@ class MiniCartTitleBlock extends AbstractInnerBlock {
?>
</h2>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php
index 3126b49da98..9ea61881aa4 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleItemsCounterBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartTitleItemsCounterBlock class.
*/
@@ -17,24 +15,12 @@ class MiniCartTitleItemsCounterBlock extends AbstractInnerBlock {
/**
* Render the block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_title_label_block();
- }
- return $content;
- }
-
- /**
- * Render the interactivity API powered experimental title block.
- *
- * @return string Rendered block type output.
- */
- protected function render_experimental_iapi_title_label_block() {
$cart = $this->get_cart_instance();
$cart_item_count = $cart ? $cart->get_cart_contents_count() : 0;
@@ -71,7 +57,7 @@ class MiniCartTitleItemsCounterBlock extends AbstractInnerBlock {
<span <?php echo $wrapper_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
</span>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
/**
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php
index e7d13257ff8..b536f5709ae 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCartTitleLabelBlock.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* MiniCartTitleLabelBlock class.
*/
@@ -17,27 +15,12 @@ class MiniCartTitleLabelBlock extends AbstractInnerBlock {
/**
* Render the block.
*
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
+ * @param array $attributes Block attributes.
+ * @param string $content Block content.
+ * @param \WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
- if ( Features::is_enabled( 'experimental-iapi-mini-cart' ) ) {
- return $this->render_experimental_iapi_title_label_block( $attributes, $content, $block );
- }
- return $content;
- }
-
- /**
- * Render the interactivity API powered experimental title block.
- *
- * @param array $attributes Block attributes.
- * @param string $content Block content.
- * @param WP_Block $block Block instance.
- * @return string Rendered block type output.
- */
- protected function render_experimental_iapi_title_label_block( $attributes, $content, $block ) {
$default_cart_label = __( 'Your cart', 'woocommerce' );
$cart_label = $attributes['label'] ? $attributes['label'] : $default_cart_label;
$wrapper_attributes = get_block_wrapper_attributes();
@@ -48,6 +31,6 @@ class MiniCartTitleLabelBlock extends AbstractInnerBlock {
<?php echo esc_html( $cart_label ); ?>
</span>
<?php
- return ob_get_clean();
+ return (string) ob_get_clean();
}
}
diff --git a/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php b/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php
index 2179f390501..c76283cee9c 100644
--- a/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php
+++ b/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php
@@ -2,7 +2,6 @@
namespace Automattic\WooCommerce\Blocks\Patterns;
-use Automattic\WooCommerce\Admin\Features\Features;
use WP_Upgrader;
/**
@@ -37,25 +36,22 @@ class PTKPatternsStore {
public function __construct( PTKClient $ptk_client ) {
$this->ptk_client = $ptk_client;
- if ( Features::is_enabled( 'pattern-toolkit-full-composability' ) ) {
- // We want to flush the cached patterns when:
- // - The WooCommerce plugin is deactivated.
- // - The `woocommerce_allow_tracking` option is disabled.
- //
- // We also want to re-fetch the patterns and update the cache when:
- // - The `woocommerce_allow_tracking` option changes to enabled.
- // - The WooCommerce plugin is activated (if `woocommerce_allow_tracking` is enabled).
- // - The WooCommerce plugin is updated.
-
- add_action( 'woocommerce_activated_plugin', array( $this, 'flush_or_fetch_patterns' ), 10, 2 );
- add_action( 'update_option_woocommerce_allow_tracking', array( $this, 'flush_or_fetch_patterns' ), 10, 2 );
- add_action( 'deactivated_plugin', array( $this, 'flush_cached_patterns' ), 10, 2 );
- add_action( 'upgrader_process_complete', array( $this, 'fetch_patterns_on_plugin_update' ), 10, 2 );
- add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'ensure_recurring_fetch_patterns_if_enabled' ) );
-
- // This is the scheduled action that takes care of flushing and re-fetching the patterns from the PTK API.
- add_action( self::FETCH_PATTERNS_ACTION, array( $this, 'fetch_patterns' ) );
- }
+ // We want to flush the cached patterns when:
+ // - The WooCommerce plugin is deactivated.
+ // - The `woocommerce_allow_tracking` option is disabled.
+ //
+ // We also want to re-fetch the patterns and update the cache when:
+ // - The `woocommerce_allow_tracking` option changes to enabled.
+ // - The WooCommerce plugin is activated (if `woocommerce_allow_tracking` is enabled).
+ // - The WooCommerce plugin is updated.
+ add_action( 'woocommerce_activated_plugin', array( $this, 'flush_or_fetch_patterns' ), 10, 2 );
+ add_action( 'update_option_woocommerce_allow_tracking', array( $this, 'flush_or_fetch_patterns' ), 10, 2 );
+ add_action( 'deactivated_plugin', array( $this, 'flush_cached_patterns' ), 10, 2 );
+ add_action( 'upgrader_process_complete', array( $this, 'fetch_patterns_on_plugin_update' ), 10, 2 );
+ add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'ensure_recurring_fetch_patterns_if_enabled' ) );
+
+ // This is the scheduled action that takes care of flushing and re-fetching the patterns from the PTK API.
+ add_action( self::FETCH_PATTERNS_ACTION, array( $this, 'fetch_patterns' ) );
}
/**
diff --git a/plugins/woocommerce/src/Blocks/Patterns/PatternRegistry.php b/plugins/woocommerce/src/Blocks/Patterns/PatternRegistry.php
index 04a5453614c..d57d5698b07 100644
--- a/plugins/woocommerce/src/Blocks/Patterns/PatternRegistry.php
+++ b/plugins/woocommerce/src/Blocks/Patterns/PatternRegistry.php
@@ -1,8 +1,6 @@
<?php
namespace Automattic\WooCommerce\Blocks\Patterns;
-use Automattic\WooCommerce\Admin\Features\Features;
-
/**
* PatternRegistry class.
*
@@ -75,10 +73,6 @@ class PatternRegistry {
return;
}
- if ( isset( $pattern_data['featureFlag'] ) && '' !== $pattern_data['featureFlag'] && ! Features::is_enabled( $pattern_data['featureFlag'] ) ) {
- return;
- }
-
// Title is a required property.
if ( ! isset( $pattern_data['title'] ) || ! $pattern_data['title'] ) {
_doing_it_wrong(
diff --git a/plugins/woocommerce/src/Blocks/Utils/BlockTemplateUtils.php b/plugins/woocommerce/src/Blocks/Utils/BlockTemplateUtils.php
index d920c95ef23..5e1c1059151 100644
--- a/plugins/woocommerce/src/Blocks/Utils/BlockTemplateUtils.php
+++ b/plugins/woocommerce/src/Blocks/Utils/BlockTemplateUtils.php
@@ -4,7 +4,6 @@ declare( strict_types=1 );
namespace Automattic\WooCommerce\Blocks\Utils;
use WP_Block_Patterns_Registry;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Blocks\Options;
use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\BlockTemplatesRegistry;
@@ -310,9 +309,7 @@ class BlockTemplateUtils {
'taxonomy-product_attribute.html',
);
- if ( Features::is_enabled( 'launch-your-store' ) ) {
- $wp_template_filenames[] = 'coming-soon.html';
- }
+ $wp_template_filenames[] = 'coming-soon.html';
$wp_template_part_filenames = array(
'checkout-header.html',
diff --git a/plugins/woocommerce/src/Internal/Admin/Analytics.php b/plugins/woocommerce/src/Internal/Admin/Analytics.php
index edf3096abe0..63bcc8934b3 100644
--- a/plugins/woocommerce/src/Internal/Admin/Analytics.php
+++ b/plugins/woocommerce/src/Internal/Admin/Analytics.php
@@ -7,7 +7,7 @@ namespace Automattic\WooCommerce\Internal\Admin;
use Automattic\WooCommerce\Admin\API\Reports\Cache;
use Automattic\WooCommerce\Utilities\OrderUtil;
-use Automattic\WooCommerce\Admin\Features\Features;
+use Automattic\WooCommerce\Utilities\FeaturesUtil;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore as OrderStatsDataStore;
use Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler;
@@ -63,7 +63,7 @@ class Analytics {
add_action( 'update_option_' . self::TOGGLE_OPTION_NAME, array( $this, 'reload_page_on_toggle' ), 10, 2 );
add_action( 'woocommerce_settings_saved', array( $this, 'maybe_reload_page' ) );
- if ( ! Features::is_enabled( 'analytics' ) ) {
+ if ( ! FeaturesUtil::feature_is_enabled( 'analytics' ) ) {
return;
}
@@ -643,7 +643,8 @@ class Analytics {
'title' => __( 'Analytics', 'woocommerce' ),
'path' => '/analytics/overview',
'icon' => 'dashicons-chart-bar',
- 'position' => 57, // After WooCommerce & Product menu items.
+ 'position' => 57,
+ // After WooCommerce & Product menu items.
);
$report_pages = array(
diff --git a/plugins/woocommerce/src/Internal/Admin/Coupons.php b/plugins/woocommerce/src/Internal/Admin/Coupons.php
index b6236a1c41f..46b0f0ee0c1 100644
--- a/plugins/woocommerce/src/Internal/Admin/Coupons.php
+++ b/plugins/woocommerce/src/Internal/Admin/Coupons.php
@@ -5,7 +5,6 @@
namespace Automattic\WooCommerce\Internal\Admin;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\PageController;
/**
@@ -40,11 +39,6 @@ class Coupons {
return;
}
- // If the main marketing feature is disabled, don't modify coupon behavior.
- if ( ! Features::is_enabled( 'marketing' ) ) {
- return;
- }
-
// Only support coupon modifications if coupons are enabled.
if ( ! wc_coupons_enabled() ) {
return;
diff --git a/plugins/woocommerce/src/Internal/Admin/Events.php b/plugins/woocommerce/src/Internal/Admin/Events.php
index 7b0f1ee6831..5ba281f0571 100644
--- a/plugins/woocommerce/src/Internal/Admin/Events.php
+++ b/plugins/woocommerce/src/Internal/Admin/Events.php
@@ -7,7 +7,6 @@ namespace Automattic\WooCommerce\Internal\Admin;
defined( 'ABSPATH' ) || exit;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
use Automattic\WooCommerce\Internal\Admin\Notes\CustomizeStoreWithBlocks;
use Automattic\WooCommerce\Internal\Admin\Notes\CustomizingProductCatalog;
@@ -145,9 +144,7 @@ class Events {
RemoteInboxNotificationsEngine::run();
}
- if ( Features::is_enabled( 'core-profiler' ) ) {
- ( new MailchimpScheduler() )->run();
- }
+ ( new MailchimpScheduler() )->run();
}
/**
@@ -221,11 +218,6 @@ class Events {
* @return bool Whether remote inbox notifications are enabled.
*/
protected function is_remote_inbox_notifications_enabled() {
- // Check if the feature flag is disabled.
- if ( ! Features::is_enabled( 'remote-inbox-notifications' ) ) {
- return false;
- }
-
// Check if the site has opted out of marketplace suggestions.
if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) !== 'yes' ) {
return false;
diff --git a/plugins/woocommerce/src/Internal/Admin/FeaturePlugin.php b/plugins/woocommerce/src/Internal/Admin/FeaturePlugin.php
index 2a7ed72e435..c48f4839d2d 100644
--- a/plugins/woocommerce/src/Internal/Admin/FeaturePlugin.php
+++ b/plugins/woocommerce/src/Internal/Admin/FeaturePlugin.php
@@ -22,6 +22,7 @@ use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\PluginsInstaller;
use Automattic\WooCommerce\Admin\ReportExporter;
use Automattic\WooCommerce\Admin\ReportsSync;
+use Automattic\WooCommerce\Utilities\FeaturesUtil;
use Automattic\WooCommerce\Internal\Admin\CategoryLookup;
use Automattic\WooCommerce\Internal\Admin\Events;
use Automattic\WooCommerce\Internal\Admin\Onboarding\Onboarding;
@@ -171,15 +172,12 @@ class FeaturePlugin {
// Initialize API.
API\Init::instance();
- if ( Features::is_enabled( 'onboarding' ) ) {
- Onboarding::init();
- }
+ Onboarding::init();
- if ( Features::is_enabled( 'analytics' ) ) {
+ if ( FeaturesUtil::feature_is_enabled( 'analytics' ) ) {
// Initialize Reports syncing.
ReportsSync::init();
CategoryLookup::instance()->init();
-
// Initialize Reports exporter.
ReportExporter::init();
}
@@ -206,11 +204,11 @@ class FeaturePlugin {
WCAdminAssets::get_instance();
}
-
/**
- * Overwrites the allowed features array using a local `feature-config.php` file.
+ * Adds the allowed features from a local `feature-config.php` file.
*
* @param array $features Array of feature slugs.
+ * @return array
*/
public function replace_supported_features( $features ) {
/**
@@ -219,8 +217,9 @@ class FeaturePlugin {
* @since 6.5.0
*/
$feature_config = apply_filters( 'woocommerce_admin_get_feature_config', wc_admin_get_feature_config() );
- $features = array_keys( array_filter( $feature_config ) );
- return $features;
+ $features = array_merge( $features, array_keys( array_filter( $feature_config ) ) );
+
+ return array_values( array_unique( $features ) );
}
/**
diff --git a/plugins/woocommerce/src/Internal/Admin/Homescreen.php b/plugins/woocommerce/src/Internal/Admin/Homescreen.php
index 48c86404e33..cd88c2833d1 100644
--- a/plugins/woocommerce/src/Internal/Admin/Homescreen.php
+++ b/plugins/woocommerce/src/Internal/Admin/Homescreen.php
@@ -7,7 +7,6 @@ declare( strict_types=1 );
namespace Automattic\WooCommerce\Internal\Admin;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Shipping;
/**
@@ -54,13 +53,11 @@ class Homescreen {
add_filter( 'woocommerce_admin_preload_options', array( $this, 'preload_options' ) );
- if ( Features::is_enabled( 'shipping-smart-defaults' ) ) {
- add_filter(
- 'woocommerce_admin_shared_settings',
- array( $this, 'maybe_set_default_shipping_options_on_home' ),
- 9999
- );
- }
+ add_filter(
+ 'woocommerce_admin_shared_settings',
+ array( $this, 'maybe_set_default_shipping_options_on_home' ),
+ 9999
+ );
}
/**
diff --git a/plugins/woocommerce/src/Internal/Admin/Notes/ScheduledUpdatesPromotion.php b/plugins/woocommerce/src/Internal/Admin/Notes/ScheduledUpdatesPromotion.php
index e4b17230b9e..b867efff932 100644
--- a/plugins/woocommerce/src/Internal/Admin/Notes/ScheduledUpdatesPromotion.php
+++ b/plugins/woocommerce/src/Internal/Admin/Notes/ScheduledUpdatesPromotion.php
@@ -11,7 +11,6 @@ namespace Automattic\WooCommerce\Internal\Admin\Notes;
defined( 'ABSPATH' ) || exit;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Notes\Note;
use Automattic\WooCommerce\Admin\Notes\NoteTraits;
@@ -49,10 +48,6 @@ class ScheduledUpdatesPromotion {
* @return bool
*/
public static function is_applicable() {
- if ( ! Features::is_enabled( 'analytics-scheduled-import' ) ) {
- return false;
- }
-
// Get the current option value.
// Note: get_option() returns false when option doesn't exist.
$immediate_import = get_option( self::OPTION_NAME, false );
diff --git a/plugins/woocommerce/src/Internal/Admin/Onboarding/OnboardingProducts.php b/plugins/woocommerce/src/Internal/Admin/Onboarding/OnboardingProducts.php
index ffa5dcde7ab..5d6a2cd5e90 100644
--- a/plugins/woocommerce/src/Internal/Admin/Onboarding/OnboardingProducts.php
+++ b/plugins/woocommerce/src/Internal/Admin/Onboarding/OnboardingProducts.php
@@ -5,7 +5,6 @@
namespace Automattic\WooCommerce\Internal\Admin\Onboarding;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Loader;
use Automattic\WooCommerce\Admin\PluginsHelper;
@@ -64,7 +63,7 @@ class OnboardingProducts {
$has_cbd_industry = in_array( 'cbd-other-hemp-derived-products', array_column( $profile['industry'], 'slug' ), true );
}
}
- if ( ! Features::is_enabled( 'subscriptions' ) || 'US' !== $base_location['country'] || $has_cbd_industry ) {
+ if ( 'US' !== $base_location['country'] || $has_cbd_industry ) {
$products['subscriptions']['product'] = 27147;
}
diff --git a/plugins/woocommerce/src/Internal/Admin/RemoteInboxNotifications.php b/plugins/woocommerce/src/Internal/Admin/RemoteInboxNotifications.php
index 402da6b7311..d817b813ee8 100644
--- a/plugins/woocommerce/src/Internal/Admin/RemoteInboxNotifications.php
+++ b/plugins/woocommerce/src/Internal/Admin/RemoteInboxNotifications.php
@@ -5,7 +5,6 @@
namespace Automattic\WooCommerce\Internal\Admin;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
/**
@@ -38,7 +37,7 @@ class RemoteInboxNotifications {
* Hook into WooCommerce.
*/
public function __construct() {
- if ( Features::is_enabled( 'remote-inbox-notifications' ) ) {
+ if ( 'yes' === get_option( self::TOGGLE_OPTION_NAME, 'yes' ) ) {
RemoteInboxNotificationsEngine::init();
}
}
diff --git a/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php b/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
index 35cb8c249eb..129281d9b64 100644
--- a/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
+++ b/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
@@ -16,7 +16,6 @@ use Automattic\WooCommerce\Admin\API\Reports\Products\DataStore as ProductsDataS
use Automattic\WooCommerce\Admin\API\Reports\Taxes\DataStore as TaxesDataStore;
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Utilities\OrderUtil;
-use Automattic\WooCommerce\Admin\Features\Features;
/**
* OrdersScheduler Class.
@@ -134,12 +133,10 @@ class OrdersScheduler extends ImportScheduler {
add_action( 'woocommerce_schedule_import', array( __CLASS__, 'possibly_schedule_import' ) );
}
- if ( Features::is_enabled( 'analytics-scheduled-import' ) ) {
- // Watch for changes to the scheduled import option.
- add_action( 'add_option_' . self::SCHEDULED_IMPORT_OPTION, array( __CLASS__, 'handle_scheduled_import_option_added' ), 10, 2 );
- add_action( 'update_option_' . self::SCHEDULED_IMPORT_OPTION, array( __CLASS__, 'handle_scheduled_import_option_change' ), 10, 2 );
- add_action( 'delete_option', array( __CLASS__, 'handle_scheduled_import_option_before_delete' ), 10, 1 );
- }
+ // Watch for changes to the scheduled import option.
+ add_action( 'add_option_' . self::SCHEDULED_IMPORT_OPTION, array( __CLASS__, 'handle_scheduled_import_option_added' ), 10, 2 );
+ add_action( 'update_option_' . self::SCHEDULED_IMPORT_OPTION, array( __CLASS__, 'handle_scheduled_import_option_change' ), 10, 2 );
+ add_action( 'delete_option', array( __CLASS__, 'handle_scheduled_import_option_before_delete' ), 10, 1 );
OrdersStatsDataStore::init();
CouponsDataStore::init();
@@ -918,8 +915,7 @@ AND status NOT IN ( 'wc-auto-draft', 'trash', 'auto-draft' )
/**
* Check whether scheduled import is enabled.
*
- * When the "analytics-scheduled-import" feature is disabled, only immediate
- * import is supported (returns false). When enabled, checks the option value.
+ * Checks the scheduled import option value.
*
* @internal
* @since 10.5.0 Introduced as a private method.
@@ -927,11 +923,6 @@ AND status NOT IN ( 'wc-auto-draft', 'trash', 'auto-draft' )
* @return bool
*/
public static function is_scheduled_import_enabled(): bool {
- if ( ! Features::is_enabled( 'analytics-scheduled-import' ) ) {
- // If the feature is disabled, only immediate import is supported.
- return false;
- }
-
$value = get_option( self::SCHEDULED_IMPORT_OPTION, false );
if ( false !== $value ) {
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings.php b/plugins/woocommerce/src/Internal/Admin/Settings.php
index 5099942d857..26ab01b4207 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings.php
@@ -211,7 +211,7 @@ class Settings {
// 'WooCommerce' to wcSettings.
$settings['woocommerceTranslation'] = __( 'WooCommerce', 'woocommerce' );
- if ( PageController::is_admin_page() && Features::is_enabled( 'analytics' ) ) {
+ if ( PageController::is_admin_page() && FeaturesUtil::feature_is_enabled( 'analytics' ) ) {
// We may have synced orders with a now-unregistered status.
// E.g. an extension that added statuses is now inactive or removed.
$settings['unregisteredOrderStatuses'] = $this->get_unregistered_order_statuses();
@@ -360,32 +360,31 @@ class Settings {
),
);
- if ( Features::is_enabled( 'analytics-scheduled-import' ) ) {
- $settings[] = array(
- 'id' => 'woocommerce_analytics_scheduled_import',
- 'option_key' => 'woocommerce_analytics_scheduled_import',
- 'label' => __( 'Updates', 'woocommerce' ),
- 'description' => __( 'Controls how analytics data is imported from orders.', 'woocommerce' ),
- 'type' => 'radio',
- 'default' => null, // Default to null so we can know if it's a new site or an existing site. New sites will have the option set.
- 'options' => array(
- 'yes' => __( 'Scheduled (recommended)', 'woocommerce' ),
- 'no' => __( 'Immediately', 'woocommerce' ),
- ),
- );
+ $settings[] = array(
+ 'id' => 'woocommerce_analytics_scheduled_import',
+ 'option_key' => 'woocommerce_analytics_scheduled_import',
+ 'label' => __( 'Updates', 'woocommerce' ),
+ 'description' => __( 'Controls how analytics data is imported from orders.', 'woocommerce' ),
+ 'type' => 'radio',
+ // Default to null so we can know if it's a new site or an existing site. New sites will have the option set.
+ 'default' => null,
+ 'options' => array(
+ 'yes' => __( 'Scheduled (recommended)', 'woocommerce' ),
+ 'no' => __( 'Immediately', 'woocommerce' ),
+ ),
+ );
- // Add hidden setting for the import interval to display in the client side.
- $import_interval = \Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler::get_import_interval();
- $import_interval = absint( $import_interval );
- // Format the import interval to a human-readable string.
- $import_interval_string = human_time_diff( 0, $import_interval );
- $settings[] = array(
- 'id' => 'woocommerce_analytics_import_interval',
- 'option_key' => 'woocommerce_analytics_import_interval',
- 'type' => 'hidden',
- 'default' => $import_interval_string,
- );
- }
+ // Add hidden setting for the import interval to display in the client side.
+ $import_interval = \Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler::get_import_interval();
+ $import_interval = absint( $import_interval );
+ // Format the import interval to a human-readable string.
+ $import_interval_string = human_time_diff( 0, $import_interval );
+ $settings[] = array(
+ 'id' => 'woocommerce_analytics_import_interval',
+ 'option_key' => 'woocommerce_analytics_import_interval',
+ 'type' => 'hidden',
+ 'default' => $import_interval_string,
+ );
return $settings;
}
diff --git a/plugins/woocommerce/src/Internal/ComingSoon/ComingSoonRequestHandler.php b/plugins/woocommerce/src/Internal/ComingSoon/ComingSoonRequestHandler.php
index 98d906c03ba..dd28f686106 100644
--- a/plugins/woocommerce/src/Internal/ComingSoon/ComingSoonRequestHandler.php
+++ b/plugins/woocommerce/src/Internal/ComingSoon/ComingSoonRequestHandler.php
@@ -1,7 +1,6 @@
<?php
namespace Automattic\WooCommerce\Internal\ComingSoon;
-use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Blocks\BlockTemplatesController;
use Automattic\WooCommerce\Blocks\BlockTemplatesRegistry;
use Automattic\WooCommerce\Blocks\Package as BlocksPackage;
@@ -134,11 +133,6 @@ class ComingSoonRequestHandler {
return true;
}
- // Early exit if LYS feature is disabled.
- if ( ! Features::is_enabled( 'launch-your-store' ) ) {
- return false;
- }
-
// Early exit if the user is logged in as administrator / shop manager.
if ( current_user_can( 'manage_woocommerce' ) ) {
return false;
@@ -190,10 +184,6 @@ class ComingSoonRequestHandler {
* @return WP_Theme_JSON_Data The filtered theme json data.
*/
public function experimental_filter_theme_json_theme( $theme_json ) {
- if ( ! Features::is_enabled( 'launch-your-store' ) ) {
- return $theme_json;
- }
-
$theme_data = $theme_json->get_data();
$font_data = $theme_data['settings']['typography']['fontFamilies']['theme'] ?? array();
@@ -295,11 +285,6 @@ class ComingSoonRequestHandler {
return;
}
- // Early exit if LYS feature is disabled.
- if ( ! Features::is_enabled( 'launch-your-store' ) ) {
- return;
- }
-
if ( $this->coming_soon_helper->is_site_live() ) {
return;
}
diff --git a/plugins/woocommerce/tests/e2e/playwright.config.ts b/plugins/woocommerce/tests/e2e/playwright.config.ts
index 70f35dce557..ca30e656ab4 100644
--- a/plugins/woocommerce/tests/e2e/playwright.config.ts
+++ b/plugins/woocommerce/tests/e2e/playwright.config.ts
@@ -243,13 +243,6 @@ export default defineConfig( {
dependencies: [ 'site setup' ],
workers: 4,
},
- {
- name: 'legacy-mini-cart',
- testMatch: [ '**/tests/cart/**', '**/tests/checkout/**' ],
- testIgnore: [ '**/tests/blocks/**' ],
- dependencies: [ 'site setup' ],
- workers: 1,
- },
{
name: 'paypal-standard',
testMatch: [ '**/tests/paypal/**' ],
@@ -266,21 +259,5 @@ export default defineConfig( {
storageState: BLOCKS_ADMIN_STATE,
},
},
- {
- name: 'blocks-legacy-mini-cart',
- testDir: `${ TESTS_ROOT_PATH }/tests/blocks`,
- testMatch: [
- '**/mini-cart/**/*.spec.ts',
- '**/add-to-cart-with-options/**/*.spec.ts',
- '**/product-button/**/*.spec.ts',
- '**/product-collection/**/*.spec.ts',
- ],
- dependencies: [ 'blocks setup' ],
- workers: 1,
- use: {
- ...devices[ 'Desktop Chrome' ],
- storageState: BLOCKS_ADMIN_STATE,
- },
- },
],
} );
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.block_theme.spec.ts
index db82f623786..097221ff6e3 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.block_theme.spec.ts
@@ -8,7 +8,6 @@ import { test as base, expect, wpCLI } from '@woocommerce/e2e-utils';
*/
import AddToCartWithOptionsPage from './add-to-cart-with-options.page';
import { ProductGalleryPage } from '../product-gallery/product-gallery.page';
-import config from '../../../../../client/admin/config/core.json';
const test = base.extend< {
pageObject: AddToCartWithOptionsPage;
@@ -126,59 +125,53 @@ test.describe( 'Add to Cart + Options Block', () => {
await expect( addToCartButton ).toHaveText( '4 in cart' );
} );
- // This test only applies to the iAPI cart which uses batch requests.
- // The legacy cart sends individual requests, not batched ones.
- if ( config.features[ 'experimental-iapi-mini-cart' ] ) {
- test( 'handles rapid add-to-cart clicks correctly', async ( {
- page,
- frontendUtils,
- miniCartUtils,
- } ) => {
- // Go to shop page where iAPI Product Button is used in product listings.
- await frontendUtils.goToShop();
-
- // Get the first Add to cart button on the page (Album product).
- const addToCartButton = page.locator( 'text=Add to cart' ).first();
- await expect( addToCartButton ).toBeVisible();
-
- // Click the button 3 times rapidly without waiting between clicks.
- // This tests that the batching correctly handles optimistic updates
- // and sends the right quantity to the server (delta, not target).
- // Without the fix, this would result in 1+2+3=6 items.
- //
- // Set up waitForResponse BEFORE the clicks to avoid a race condition.
- // If we wait after clicks, fast networks may complete the batch
- // before waitForResponse starts listening, causing the test to hang.
- const batchPromise = page.waitForResponse(
- '**/wc/store/v1/batch**'
- );
- await addToCartButton.click();
- await addToCartButton.click();
- await addToCartButton.click();
+ test( 'handles rapid add-to-cart clicks correctly', async ( {
+ page,
+ frontendUtils,
+ miniCartUtils,
+ } ) => {
+ // Go to shop page where iAPI Product Button is used in product listings.
+ await frontendUtils.goToShop();
+
+ // Get the first Add to cart button on the page (Album product).
+ const addToCartButton = page.locator( 'text=Add to cart' ).first();
+ await expect( addToCartButton ).toBeVisible();
+
+ // Click the button 3 times rapidly without waiting between clicks.
+ // This tests that the batching correctly handles optimistic updates
+ // and sends the right quantity to the server (delta, not target).
+ // Without the fix, this would result in 1+2+3=6 items.
+ //
+ // Set up waitForResponse BEFORE the clicks to avoid a race condition.
+ // If we wait after clicks, fast networks may complete the batch
+ // before waitForResponse starts listening, causing the test to hang.
+ const batchPromise = page.waitForResponse( '**/wc/store/v1/batch**' );
+ await addToCartButton.click();
+ await addToCartButton.click();
+ await addToCartButton.click();
- // Wait for all batch requests to complete.
- await batchPromise;
+ // Wait for all batch requests to complete.
+ await batchPromise;
- // Open mini cart and verify the count.
- await miniCartUtils.openMiniCart();
+ // Open mini cart and verify the count.
+ await miniCartUtils.openMiniCart();
- // Check the mini cart shows exactly 3 items.
- // If the bug were present, it would show 6 (1+2+3).
- const quantityInput = page.getByLabel(
- 'Quantity of Album in your cart.'
- );
- const quantity = await quantityInput.inputValue();
- const quantityNum = parseInt( quantity, 10 );
+ // Check the mini cart shows exactly 3 items.
+ // If the bug were present, it would show 6 (1+2+3).
+ const quantityInput = page.getByLabel(
+ 'Quantity of Album in your cart.'
+ );
+ const quantity = await quantityInput.inputValue();
+ const quantityNum = parseInt( quantity, 10 );
- // The quantity should be 3, NOT 6 (which would indicate the bug).
- // We use a soft assertion to account for any timing edge cases.
- expect( quantityNum ).toBeLessThanOrEqual( 3 );
- expect( quantityNum ).toBeGreaterThanOrEqual( 2 );
+ // The quantity should be 3, NOT 6 (which would indicate the bug).
+ // We use a soft assertion to account for any timing edge cases.
+ expect( quantityNum ).toBeLessThanOrEqual( 3 );
+ expect( quantityNum ).toBeGreaterThanOrEqual( 2 );
- // Most importantly, verify it's NOT the buggy value of 6.
- expect( quantityNum ).not.toBe( 6 );
- } );
- }
+ // Most importantly, verify it's NOT the buggy value of 6.
+ expect( quantityNum ).not.toBe( 6 );
+ } );
test( 'allows adding variable products to cart', async ( {
page,
@@ -620,11 +613,7 @@ test.describe( 'Add to Cart + Options Block', () => {
).toBeVisible();
await expect(
- page.getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 2'
- : '2 items in cart'
- )
+ page.getByLabel( 'Number of items in the cart: 2' )
).toBeVisible();
} );
@@ -692,11 +681,7 @@ test.describe( 'Add to Cart + Options Block', () => {
await batchPromise;
await expect(
- page.getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 3'
- : '3 items in cart'
- )
+ page.getByLabel( 'Number of items in the cart: 3' )
).toBeVisible();
} );
@@ -737,11 +722,7 @@ test.describe( 'Add to Cart + Options Block', () => {
// Verify optimistic updates were applied, so the product that was
// successfully added to cart is counted.
await expect(
- page.getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 4'
- : '4 items in cart'
- )
+ page.getByLabel( 'Number of items in the cart: 4' )
).toBeVisible();
} );
} );
@@ -789,11 +770,7 @@ test.describe( 'Add to Cart + Options Block', () => {
).toBeVisible();
await expect(
- page.getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 2'
- : '2 items in cart'
- )
+ page.getByLabel( 'Number of items in the cart: 2' )
).toBeVisible();
} );
@@ -812,11 +789,7 @@ test.describe( 'Add to Cart + Options Block', () => {
await addedToCartButton.click();
await expect(
- page.getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 4'
- : '4 items in cart'
- )
+ page.getByLabel( 'Number of items in the cart: 4' )
).toBeVisible();
} );
@@ -824,11 +797,7 @@ test.describe( 'Add to Cart + Options Block', () => {
await page.reload();
await expect(
- page.getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 4'
- : '4 items in cart'
- )
+ page.getByLabel( 'Number of items in the cart: 4' )
).toBeVisible();
} );
} );
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart-block.shopper.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart-block.shopper.block_theme.spec.ts
index 935284b7fb0..c16d2346d55 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart-block.shopper.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart-block.shopper.block_theme.spec.ts
@@ -10,10 +10,7 @@ import {
REGULAR_PRICED_PRODUCT_NAME,
SIMPLE_PHYSICAL_PRODUCT_NAME,
} from '../checkout/constants';
-import { getTestTranslation } from '../../../utils/blocks/get-test-translation';
-import { translations } from '../../../test-data/blocks/data/data';
import ProductCollectionPage from '../product-collection/product-collection.page';
-import config from '../../../../../client/admin/config/core.json';
const test = base.extend< { productCollectionPage: ProductCollectionPage } >( {
productCollectionPage: async ( { page, admin, editor }, use ) => {
@@ -27,66 +24,62 @@ const test = base.extend< { productCollectionPage: ProductCollectionPage } >( {
} );
test.describe( 'Shopper → Notices', () => {
- // This test only applies to the iAPI mini cart which supports SSR.
- // The legacy React mini cart is entirely client-side rendered.
- if ( config.features[ 'experimental-iapi-mini-cart' ] ) {
- test( 'Shopper sees SSR error notice in mini cart when product goes out of stock', async ( {
- page,
- browser,
- frontendUtils,
- } ) => {
- const productName = 'Limited Stock Product';
+ test( 'Shopper sees SSR error notice in mini cart when product goes out of stock', async ( {
+ page,
+ browser,
+ frontendUtils,
+ } ) => {
+ const productName = 'Limited Stock Product';
- // Create a product with only 1 in stock.
- const result = await wpCLI(
- `wc product create --name="${ productName }" --regular_price=10 --manage_stock=true --stock_quantity=1 --user=admin --porcelain`
+ // Create a product with only 1 in stock.
+ const result = await wpCLI(
+ `wc product create --name="${ productName }" --regular_price=10 --manage_stock=true --stock_quantity=1 --user=admin --porcelain`
+ );
+ // Extract just the numeric ID from output (npm adds prefix lines to stdout).
+ const productId = result.stdout.match( /^\d+$/m )?.[ 0 ];
+ if ( ! productId ) {
+ throw new Error(
+ `Failed to extract product ID from wpCLI output: ${ result.stdout }`
);
- // Extract just the numeric ID from output (npm adds prefix lines to stdout).
- const productId = result.stdout.match( /^\d+$/m )?.[ 0 ];
- if ( ! productId ) {
- throw new Error(
- `Failed to extract product ID from wpCLI output: ${ result.stdout }`
- );
- }
+ }
- await frontendUtils.emptyCart();
- await frontendUtils.goToShop();
- await frontendUtils.addToCart( productName );
+ await frontendUtils.emptyCart();
+ await frontendUtils.goToShop();
+ await frontendUtils.addToCart( productName );
- // Set product to out of stock while it's in cart.
- await wpCLI(
- `wc product update ${ productId } --stock_quantity=0 --in_stock=false --user=admin`
- );
+ // Set product to out of stock while it's in cart.
+ await wpCLI(
+ `wc product update ${ productId } --stock_quantity=0 --in_stock=false --user=admin`
+ );
- // Get the current URL to revisit with JS disabled.
- const currentUrl = page.url();
+ // Get the current URL to revisit with JS disabled.
+ const currentUrl = page.url();
- // Create a new context with JavaScript disabled to verify SSR output.
- const noJsContext = await browser.newContext( {
- javaScriptEnabled: false,
- } );
+ // Create a new context with JavaScript disabled to verify SSR output.
+ const noJsContext = await browser.newContext( {
+ javaScriptEnabled: false,
+ } );
- try {
- const noJsPage = await noJsContext.newPage();
+ try {
+ const noJsPage = await noJsContext.newPage();
- // Copy cookies to maintain cart session.
- const cookies = await page.context().cookies();
- await noJsContext.addCookies( cookies );
+ // Copy cookies to maintain cart session.
+ const cookies = await page.context().cookies();
+ await noJsContext.addCookies( cookies );
- await noJsPage.goto( currentUrl );
+ await noJsPage.goto( currentUrl );
- // Verify error notice banner is rendered in SSR output (not client-side JS).
- // Note: The notice text content contains HTML and is rendered client-side via
- // data-wp-init callback, so we only verify the banner structure exists in SSR.
- const miniCartNotice = noJsPage.locator(
- '.wp-block-woocommerce-filled-mini-cart-contents-block .wc-block-components-notice-banner'
- );
- await expect( miniCartNotice ).toBeVisible();
- } finally {
- await noJsContext.close();
- }
- } );
- }
+ // Verify error notice banner is rendered in SSR output (not client-side JS).
+ // Note: The notice text content contains HTML and is rendered client-side via
+ // data-wp-init callback, so we only verify the banner structure exists in SSR.
+ const miniCartNotice = noJsPage.locator(
+ '.wp-block-woocommerce-filled-mini-cart-contents-block .wc-block-components-notice-banner'
+ );
+ await expect( miniCartNotice ).toBeVisible();
+ } finally {
+ await noJsContext.close();
+ }
+ } );
test( 'Shopper can add item to cart, and will not see a notice in the mini cart', async ( {
page,
@@ -168,60 +161,6 @@ test.describe( 'Shopper → Notices', () => {
} );
} );
-// Skip the rest of the translation tests if the iAPI mini cart is enabled.
-if ( ! config.features[ 'experimental-iapi-mini-cart' ] ) {
- test.describe( 'Shopper → Translations', () => {
- test.beforeEach( async () => {
- await wpCLI( `site switch-language ${ translations.locale }` );
- } );
-
- test( 'User can see translation in empty Mini-Cart', async ( {
- page,
- frontendUtils,
- miniCartUtils,
- } ) => {
- await frontendUtils.emptyCart();
- await frontendUtils.goToShop();
- await miniCartUtils.openMiniCart();
-
- await expect(
- page.getByRole( 'link', {
- name: getTestTranslation( 'Start shopping' ),
- } )
- ).toBeVisible();
- } );
-
- test( 'User can see translation in filled Mini-Cart', async ( {
- page,
- frontendUtils,
- miniCartUtils,
- } ) => {
- await frontendUtils.emptyCart();
- await frontendUtils.goToShop();
- await frontendUtils.addToCart( SIMPLE_PHYSICAL_PRODUCT_NAME );
- await miniCartUtils.openMiniCart();
-
- await expect(
- page.getByRole( 'heading', {
- name: getTestTranslation( 'Your cart' ),
- } )
- ).toBeVisible();
-
- await expect(
- page.getByRole( 'link', {
- name: getTestTranslation( 'View my cart' ),
- } )
- ).toBeVisible();
-
- await expect(
- page.getByRole( 'link', {
- name: getTestTranslation( 'Go to checkout' ),
- } )
- ).toBeVisible();
- } );
- } );
-}
-
test.describe( 'Shopper → Tax', () => {
test.beforeEach( async () => {
await wpCLI( 'option set woocommerce_prices_include_tax no' );
@@ -239,11 +178,7 @@ test.describe( 'Shopper → Tax', () => {
const miniCartLocator = page
.getByTestId( 'mini-cart' )
- .getByLabel(
- config.features[ 'experimental-iapi-mini-cart' ]
- ? 'Number of items in the cart: 1'
- : '1 item in cart'
- );
+ .getByLabel( 'Number of items in the cart: 1' );
await expect( miniCartLocator ).toContainText( '(incl. tax)' );
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts
index 5bbddb6add4..6e278500b1b 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts
@@ -7,7 +7,6 @@ import { test, expect, BlockData, wpCLI } from '@woocommerce/e2e-utils';
* Internal dependencies
*/
import { REGULAR_PRICED_PRODUCT_NAME } from '../checkout/constants';
-import config from '../../../../../client/admin/config/core.json';
const blockData: BlockData = {
name: 'Mini-Cart',
@@ -219,34 +218,26 @@ test.describe( `${ blockData.name } Block`, () => {
page.getByLabel( 'Quantity of Polo in your cart.' )
).toHaveValue( '1' );
- // iAPI cart uses batch requests, legacy cart uses individual endpoints.
// Set up waitForResponse BEFORE the click to avoid race condition.
- const useBatch = config.features[ 'experimental-iapi-mini-cart' ];
- let batchPromise = useBatch
- ? page.waitForResponse( '**/wp-json/wc/store/v1/batch**' )
- : null;
+ let batchPromise = page.waitForResponse(
+ '**/wp-json/wc/store/v1/batch**'
+ );
await page
.getByRole( 'button', { name: 'Increase quantity of Polo' } )
.click();
- if ( batchPromise ) {
- await batchPromise;
- }
+ await batchPromise;
await expect(
page.getByLabel( 'Quantity of Polo in your cart.' )
).toHaveValue( '2' );
- batchPromise = useBatch
- ? page.waitForResponse( '**/wp-json/wc/store/v1/batch**' )
- : null;
+ batchPromise = page.waitForResponse( '**/wp-json/wc/store/v1/batch**' );
await page
.getByRole( 'button', { name: 'Reduce quantity of Polo' } )
.click();
- if ( batchPromise ) {
- await batchPromise;
- }
+ await batchPromise;
await expect(
page.getByLabel( 'Quantity of Polo in your cart.' )
diff --git a/plugins/woocommerce/tests/php/src/Admin/API/AnalyticsImportsTest.php b/plugins/woocommerce/tests/php/src/Admin/API/AnalyticsImportsTest.php
index 72fdfac3719..c9605f046a5 100644
--- a/plugins/woocommerce/tests/php/src/Admin/API/AnalyticsImportsTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/API/AnalyticsImportsTest.php
@@ -49,10 +49,6 @@ class AnalyticsImportsTest extends WC_REST_Unit_Test_Case {
public function setUp(): void {
parent::setUp();
- // Enable the analytics-scheduled-import feature so is_scheduled_import_enabled()
- // delegates correctly (matches OrdersScheduler's own behaviour).
- Features::enable( 'analytics-scheduled-import' );
-
// Create test users.
$this->admin_user = $this->factory->user->create(
array(
@@ -84,7 +80,6 @@ class AnalyticsImportsTest extends WC_REST_Unit_Test_Case {
delete_option( OrdersScheduler::SCHEDULED_IMPORT_OPTION );
delete_option( OrdersScheduler::LAST_PROCESSED_ORDER_DATE_OPTION );
delete_option( OrdersScheduler::FAILED_ORDER_IMPORTS_OPTION );
- Features::disable( 'analytics-scheduled-import' );
parent::tearDown();
}
diff --git a/plugins/woocommerce/tests/php/src/Admin/Features/Analytics/FeatureEnabledTest.php b/plugins/woocommerce/tests/php/src/Admin/Features/Analytics/FeatureEnabledTest.php
index e8742141be7..8ea53266947 100644
--- a/plugins/woocommerce/tests/php/src/Admin/Features/Analytics/FeatureEnabledTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/Features/Analytics/FeatureEnabledTest.php
@@ -1,10 +1,11 @@
<?php
-
-declare(strict_types=1);
+declare( strict_types = 1 );
namespace Automattic\WooCommerce\Tests\Admin\Features\Analytics;
use Automattic\WooCommerce\Admin\Features\Features;
+use Automattic\WooCommerce\Internal\Admin\RemoteInboxNotifications;
+use Automattic\WooCommerce\Utilities\FeaturesUtil;
use WC_Unit_Test_Case;
/**
@@ -12,15 +13,163 @@ use WC_Unit_Test_Case;
*/
class FeatureEnabledTest extends WC_Unit_Test_Case {
/**
- * Test that the analytics feature should be disabled when not in admin and the option value is disabled.
+ * Tear down test fixtures.
*/
- public function test_should_be_disabled_when_not_in_admin_and_the_option_value_is_disabled() {
- // Simulate a non-admin environment by disabling feature loading.
- add_filter( 'woocommerce_admin_should_load_features', '__return_false' );
+ public function tearDown(): void {
+ delete_option( 'woocommerce_analytics_enabled' );
+ delete_option( RemoteInboxNotifications::TOGGLE_OPTION_NAME );
+ remove_filter( 'woocommerce_admin_features', array( $this, 'enable_analytics_feature' ) );
+ remove_filter( 'woocommerce_admin_features', array( $this, 'disable_launch_your_store_feature' ) );
+ remove_filter( 'woocommerce_admin_features', array( $this, 'disable_customize_store_feature' ) );
+
+ parent::tearDown();
+ }
+
+ /**
+ * @testdox Should disable the analytics feature when the option value is disabled.
+ */
+ public function test_should_be_disabled_when_the_option_value_is_disabled(): void {
+ update_option( 'woocommerce_analytics_enabled', 'no' );
- // Set the analytics feature option to no.
+ $this->assertFalse(
+ FeaturesUtil::feature_is_enabled( 'analytics' ),
+ 'Analytics should be disabled when the feature option is disabled.'
+ );
+ }
+
+ /**
+ * @testdox Should remove analytics from legacy admin features when the option value is disabled.
+ */
+ public function test_should_remove_analytics_from_legacy_admin_features_when_the_option_value_is_disabled(): void {
+ add_filter( 'woocommerce_admin_features', array( $this, 'enable_analytics_feature' ) );
update_option( 'woocommerce_analytics_enabled', 'no' );
+ $this->setExpectedDeprecated( "Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'analytics' )" );
+
+ try {
+ $this->assertFalse(
+ Features::is_enabled( 'analytics' ),
+ 'Analytics should be unavailable in legacy admin features when the feature option is disabled.'
+ );
+ } finally {
+ remove_filter( 'woocommerce_admin_features', array( $this, 'enable_analytics_feature' ) );
+ }
+ }
+
+ /**
+ * @testdox Should keep retired feature flags enabled through the legacy is_enabled shim.
+ */
+ public function test_should_keep_retired_feature_flags_enabled_through_legacy_is_enabled_shim(): void {
+ $this->setExpectedDeprecated( "Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'launch-your-store' )" );
+
+ $this->assertTrue(
+ Features::is_enabled( 'launch-your-store' ),
+ 'Retired feature flags should remain enabled through the compatibility shim.'
+ );
+ }
+
+ /**
+ * @testdox Should keep retired feature flags available through the legacy exists shim.
+ */
+ public function test_should_keep_retired_feature_flags_available_through_legacy_exists_shim(): void {
+ $this->setExpectedDeprecated( "Automattic\WooCommerce\Admin\Features\Features::exists( 'customize-store' )" );
+
+ $this->assertTrue(
+ Features::exists( 'customize-store' ),
+ 'Retired feature flags should remain available through the compatibility shim.'
+ );
+ }
+
+ /**
+ * @testdox Should respect filtered retired feature flags through the legacy is_enabled shim.
+ */
+ public function test_should_respect_filtered_retired_feature_flags_through_legacy_is_enabled_shim(): void {
+ add_filter( 'woocommerce_admin_features', array( $this, 'disable_launch_your_store_feature' ) );
+ $this->setExpectedDeprecated( "Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'launch-your-store' )" );
+
+ try {
+ $this->assertFalse(
+ Features::is_enabled( 'launch-your-store' ),
+ 'Retired feature flags should respect the filtered feature list through the compatibility shim.'
+ );
+ } finally {
+ remove_filter( 'woocommerce_admin_features', array( $this, 'disable_launch_your_store_feature' ) );
+ }
+ }
+
+ /**
+ * @testdox Should respect filtered retired feature flags through the legacy exists shim.
+ */
+ public function test_should_respect_filtered_retired_feature_flags_through_legacy_exists_shim(): void {
+ add_filter( 'woocommerce_admin_features', array( $this, 'disable_customize_store_feature' ) );
+ $this->setExpectedDeprecated( "Automattic\WooCommerce\Admin\Features\Features::exists( 'customize-store' )" );
+
+ try {
+ $this->assertFalse(
+ Features::exists( 'customize-store' ),
+ 'Retired feature flags should respect the filtered feature list through the compatibility shim.'
+ );
+ } finally {
+ remove_filter( 'woocommerce_admin_features', array( $this, 'disable_customize_store_feature' ) );
+ }
+ }
+
+ /**
+ * @testdox Should return false for unknown feature flags.
+ */
+ public function test_should_return_false_for_unknown_feature_flags(): void {
+ $this->assertFalse(
+ Features::is_enabled( 'unknown-feature-flag' ),
+ 'Unknown feature flags should not be enabled by the compatibility shim.'
+ );
+
+ $this->assertFalse(
+ Features::exists( 'unknown-feature-flag' ),
+ 'Unknown feature flags should not exist through the compatibility shim.'
+ );
+ }
+
+ /**
+ * @testdox Should keep remote inbox notifications option-aware through the legacy shim.
+ */
+ public function test_should_keep_remote_inbox_notifications_option_aware_through_legacy_shim(): void {
+ update_option( RemoteInboxNotifications::TOGGLE_OPTION_NAME, 'no' );
+ $this->setExpectedDeprecated( "Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'remote-inbox-notifications' )" );
- $this->assertFalse( Features::is_enabled( 'analytics' ) );
+ $this->assertFalse(
+ Features::is_enabled( 'remote-inbox-notifications' ),
+ 'Remote inbox notifications should remain option-aware through the compatibility shim.'
+ );
+ }
+
+ /**
+ * Enable the analytics feature in the legacy admin feature list.
+ *
+ * @param array $features Feature slugs.
+ * @return array
+ */
+ public function enable_analytics_feature( array $features ): array {
+ $features[] = 'analytics';
+
+ return array_unique( $features );
+ }
+
+ /**
+ * Disable the launch your store feature in the legacy admin feature list.
+ *
+ * @param array $features Feature slugs.
+ * @return array
+ */
+ public function disable_launch_your_store_feature( array $features ): array {
+ return array_values( array_diff( $features, array( 'launch-your-store' ) ) );
+ }
+
+ /**
+ * Disable the customize store feature in the legacy admin feature list.
+ *
+ * @param array $features Feature slugs.
+ * @return array
+ */
+ public function disable_customize_store_feature( array $features ): array {
+ return array_values( array_diff( $features, array( 'customize-store' ) ) );
}
}
diff --git a/plugins/woocommerce/tests/php/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendationTest.php b/plugins/woocommerce/tests/php/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendationTest.php
index 266bdd5d5e4..ef535a10261 100644
--- a/plugins/woocommerce/tests/php/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendationTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/Features/OnboardingTasks/Tasks/ExperimentalShippingRecommendationTest.php
@@ -22,11 +22,6 @@ class ExperimentalShippingRecommendationTest extends WC_Unit_Test_Case {
*/
const HOOK_PRIORITY = 9999;
- /**
- * @var string[]
- */
- private $enabled_admin_features_mock;
-
/**
* @var string[]
*/
@@ -40,9 +35,7 @@ class ExperimentalShippingRecommendationTest extends WC_Unit_Test_Case {
public function setUp(): void {
parent::setUp();
- add_filter( 'woocommerce_admin_features', array( $this, 'get_mocked_admin_features' ), self::HOOK_PRIORITY );
add_filter( 'pre_option_active_plugins', array( $this, 'get_mocked_active_plugins' ), self::HOOK_PRIORITY );
- $this->enabled_admin_features_mock = array();
$this->active_plugin_basenames_mock = array();
}
@@ -54,7 +47,6 @@ class ExperimentalShippingRecommendationTest extends WC_Unit_Test_Case {
public function tearDown(): void {
parent::tearDown();
- remove_filter( 'woocommerce_admin_features', array( $this, 'get_mocked_admin_features' ), self::HOOK_PRIORITY );
remove_filter( 'pre_option_active_plugins', array( $this, 'get_mocked_active_plugins' ), self::HOOK_PRIORITY );
wp_cache_delete( 'plugins', 'plugins' );
}
@@ -65,24 +57,11 @@ class ExperimentalShippingRecommendationTest extends WC_Unit_Test_Case {
* @return void
*/
public function test_can_view_returns_true() {
- $this->enabled_admin_features_mock = array( 'shipping-smart-defaults' );
$this->mock_active_plugin_basenames( array() );
$this->assertTrue( ( new ExperimentalShippingRecommendation() )->can_view() );
}
- /**
- * Tests that the task is unavailable if smart shipping defaults are disabled.
- *
- * @return void
- */
- public function test_can_view_returns_false_if_smart_defaults_are_disabled() {
- $this->enabled_admin_features_mock = array();
- $this->mock_active_plugin_basenames( array() );
-
- $this->assertFalse( ( new ExperimentalShippingRecommendation() )->can_view() );
- }
-
/**
* Mocks the list of basenames of active plugins.
*
@@ -100,17 +79,6 @@ class ExperimentalShippingRecommendationTest extends WC_Unit_Test_Case {
wp_cache_set( 'plugins', array( '' => array_flip( $plugin_basenames ) ), 'plugins' );
}
- /**
- * Returns a mocked list of enabled WC Admin features.
- *
- * @see \wc_admin_get_feature_config
- *
- * @return string[]
- */
- public function get_mocked_admin_features() {
- return $this->enabled_admin_features_mock;
- }
-
/**
* Returns a mocked list of active plugin basenames.
*
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockPatterns/BlockPatterns.php b/plugins/woocommerce/tests/php/src/Blocks/BlockPatterns/BlockPatterns.php
index e2b77199d4e..b52d54c7238 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockPatterns/BlockPatterns.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockPatterns/BlockPatterns.php
@@ -76,7 +76,6 @@ class BlockPatterns extends \WP_UnitTestCase {
'keywords' => '',
'blockTypes' => 'core/template-part/footer',
'inserter' => '',
- 'featureFlag' => '',
'templateTypes' => '',
'source' => __DIR__ . '/patterns/mock-footer.php',
'filePath' => __DIR__ . '/patterns/mock-footer.php',
@@ -93,7 +92,6 @@ class BlockPatterns extends \WP_UnitTestCase {
'keywords' => '',
'blockTypes' => 'core/template-part/header',
'inserter' => '',
- 'featureFlag' => '',
'templateTypes' => '',
'source' => __DIR__ . '/patterns/mock-header.php',
'filePath' => __DIR__ . '/patterns/mock-header.php',
@@ -229,7 +227,6 @@ class BlockPatterns extends \WP_UnitTestCase {
'keywords' => '',
'blockTypes' => 'core/template-part/footer',
'inserter' => '',
- 'featureFlag' => '',
'templateTypes' => '',
'source' => __DIR__ . '/patterns/mock-footer.php',
'filePath' => __DIR__ . '/patterns/mock-footer.php',
@@ -246,7 +243,6 @@ class BlockPatterns extends \WP_UnitTestCase {
'keywords' => '',
'blockTypes' => 'core/template-part/header',
'inserter' => '',
- 'featureFlag' => '',
'templateTypes' => '',
'source' => __DIR__ . '/patterns/mock-header.php',
'filePath' => __DIR__ . '/patterns/mock-header.php',
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Patterns/PatternRegistryTest.php b/plugins/woocommerce/tests/php/src/Blocks/Patterns/PatternRegistryTest.php
index 35f0ee30931..b546abefbe0 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Patterns/PatternRegistryTest.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Patterns/PatternRegistryTest.php
@@ -58,46 +58,6 @@ class PatternRegistryTest extends \WP_UnitTestCase {
$this->pattern_registry->register_block_pattern( 'source', $pattern, [] );
}
-
- /**
- * Test that a pattern should not be registered with a disabled feature flag.
- */
- public function test_should_not_register_a_pattern_with_a_disabled_feature_flag() {
- $pattern = [
- 'title' => 'My Pattern',
- 'slug' => 'my-pattern',
- 'featureFlag' => 'disabled-feature-flag',
- ];
-
- $this->pattern_registry->register_block_pattern( 'source', $pattern, [] );
-
- $this->assertFalse(
- \WP_Block_Patterns_Registry::get_instance()->is_registered( $pattern['slug'] )
- );
- }
-
- /**
- * Test that a pattern should be registered with an enabled feature flag.
- */
- public function test_register_a_pattern_with_an_enabled_feature_flag() {
- add_filter( 'woocommerce_admin_features', array( $this, 'enable_feature_flag' ) );
-
- $pattern = [
- 'title' => 'My Pattern',
- 'slug' => 'my-pattern',
- 'content' => 'My pattern content',
- 'featureFlag' => 'enabled-feature-flag',
- ];
-
- $this->pattern_registry->register_block_pattern( 'source', $pattern, [] );
-
- $this->assertTrue(
- \WP_Block_Patterns_Registry::get_instance()->is_registered( $pattern['slug'] )
- );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'enable_feature_flag' ) );
- }
-
/**
* Test that a pattern should not be registered without a title.
*/
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Notes/ScheduledUpdatesPromotionTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Notes/ScheduledUpdatesPromotionTest.php
index 63edd5163c4..50e2fbdab1d 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Notes/ScheduledUpdatesPromotionTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Notes/ScheduledUpdatesPromotionTest.php
@@ -16,79 +16,30 @@ use WC_Unit_Test_Case;
*/
class ScheduledUpdatesPromotionTest extends WC_Unit_Test_Case {
- /**
- * Enable the analytics-scheduled-import feature.
- *
- * @param array $features Existing features.
- * @return array Modified features.
- */
- public function enable_feature( $features ) {
- $features[] = 'analytics-scheduled-import';
- return $features;
- }
-
- /**
- * Disable the analytics-scheduled-import feature.
- *
- * @param array $features Existing features.
- * @return array Modified features.
- */
- public function disable_feature( $features ) {
- return array_diff( $features, array( 'analytics-scheduled-import' ) );
- }
-
- /**
- * Test is_applicable returns false when feature flag is disabled.
- */
- public function test_is_applicable_returns_false_when_feature_disabled() {
- // Disable the feature (it's enabled by default in feature-config.php).
- add_filter( 'woocommerce_admin_features', array( $this, 'disable_feature' ) );
-
- // Delete option to simulate existing installation.
- delete_option( 'woocommerce_analytics_scheduled_import' );
-
- $this->assertFalse( ScheduledUpdatesPromotion::is_applicable() );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'disable_feature' ) );
- }
-
/**
* Test is_applicable returns true for existing installations.
*/
public function test_is_applicable_returns_true_for_existing_installations() {
- // Enable feature flag.
- add_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
-
// Delete option to simulate existing installation (doesn't exist).
delete_option( 'woocommerce_analytics_scheduled_import' );
$this->assertTrue( ScheduledUpdatesPromotion::is_applicable() );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
}
/**
* Test is_applicable returns false for new installations.
*/
public function test_is_applicable_returns_false_for_new_installations() {
- // Enable feature flag.
- add_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
-
// Set option to 'yes' to simulate new installation (scheduled enabled).
update_option( 'woocommerce_analytics_scheduled_import', 'yes' );
$this->assertFalse( ScheduledUpdatesPromotion::is_applicable() );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
}
/**
* Test get_note returns note for existing installations.
*/
public function test_get_note_returns_note_for_existing_installations() {
- // Enable feature flag.
- add_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
-
// Delete option to simulate existing installation (doesn't exist).
delete_option( 'woocommerce_analytics_scheduled_import' );
@@ -102,33 +53,23 @@ class ScheduledUpdatesPromotionTest extends WC_Unit_Test_Case {
$actions = $note->get_actions();
$this->assertCount( 1, $actions, 'Note should have 1 action' );
$this->assertEquals( 'scheduled-updates-enable', $actions[0]->name );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
}
/**
* Test get_note returns null when not applicable.
*/
public function test_get_note_returns_null_when_not_applicable() {
- // Disable the feature (it's enabled by default in feature-config.php).
- add_filter( 'woocommerce_admin_features', array( $this, 'disable_feature' ) );
-
- delete_option( 'woocommerce_analytics_scheduled_import' );
+ update_option( 'woocommerce_analytics_scheduled_import', 'yes' );
$note = ScheduledUpdatesPromotion::get_note();
$this->assertNull( $note );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'disable_feature' ) );
}
/**
* Test that note is added via possibly_add_note for existing installations.
*/
public function test_possibly_add_note_adds_note_for_existing_installations() {
- // Enable feature flag.
- add_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
-
// Delete option to simulate existing installation.
delete_option( 'woocommerce_analytics_scheduled_import' );
@@ -139,17 +80,12 @@ class ScheduledUpdatesPromotionTest extends WC_Unit_Test_Case {
$note_ids = $data_store->get_notes_with_name( ScheduledUpdatesPromotion::NOTE_NAME );
$this->assertNotEmpty( $note_ids, 'Note should be created for existing installations' );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
}
/**
* Test that possibly_add_note prevents duplicates.
*/
public function test_possibly_add_note_prevents_duplicates() {
- // Enable feature flag.
- add_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
-
// Delete option to simulate existing installation.
delete_option( 'woocommerce_analytics_scheduled_import' );
@@ -164,8 +100,6 @@ class ScheduledUpdatesPromotionTest extends WC_Unit_Test_Case {
$note_ids = $data_store->get_notes_with_name( ScheduledUpdatesPromotion::NOTE_NAME );
$this->assertCount( 1, $note_ids, 'Only one note should exist' );
-
- remove_filter( 'woocommerce_admin_features', array( $this, 'enable_feature' ) );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php
index ea162197c00..011bbb9592b 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php
@@ -6,7 +6,6 @@ namespace Automattic\WooCommerce\Tests\Internal\Admin\Schedulers;
use Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler;
use Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore as OrdersStatsDataStore;
use WC_Unit_Test_Case;
-use Automattic\WooCommerce\Admin\Features\Features;
/**
* OrdersScheduler Test.
@@ -21,8 +20,7 @@ class OrdersSchedulerTest extends WC_Unit_Test_Case {
public function setUp(): void {
parent::setUp();
- // Enable the analytics-scheduled-import feature.
- Features::enable( 'analytics-scheduled-import' );
+ update_option( OrdersScheduler::SCHEDULED_IMPORT_OPTION, 'yes' );
}
/**
@@ -41,7 +39,7 @@ class OrdersSchedulerTest extends WC_Unit_Test_Case {
// Clean up any scheduled actions.
$this->clear_scheduled_batch_processor();
- Features::disable( 'analytics-scheduled-import' );
+ delete_option( OrdersScheduler::SCHEDULED_IMPORT_OPTION );
}
/**
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9ac01c6dc0f..4898c6c2312 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2921,6 +2921,9 @@ importers:
'@wordpress/date':
specifier: catalog:wp-min
version: 5.33.1
+ '@wordpress/deprecated':
+ specifier: catalog:wp-min
+ version: 4.33.1
'@wordpress/dom':
specifier: catalog:wp-min
version: 4.33.1
@@ -4457,13 +4460,13 @@ packages:
engines: {node: '>=6.0.0'}
'@ariakit/core@0.3.11':
- resolution: {integrity: sha512-+MnOeqnA4FLI/7vqsZLbZQHHN4ofd9kvkNjz44fNi0gqmD+ZbMWiDkFAvZII75dYnxYw5ZPpWjA4waK22VBWig==}
+ resolution: {integrity: sha512-+MnOeqnA4FLI/7vqsZLbZQHHN4ofd9kvkNjz44fNi0gqmD+ZbMWiDkFAvZII75dYnxYw5ZPpWjA4waK22VBWig==, tarball: https://registry.npmjs.org/@ariakit/core/-/core-0.3.11.tgz}
'@ariakit/core@0.4.19':
resolution: {integrity: sha512-PUj/J1eX/b+DkcYwP6m7/tzDUiX1SVST89coljTN6BdQwLYMSkhg71jXcZwmTX19jQmqV9VqhVkKeabLnvciQQ==}
'@ariakit/react-core@0.3.14':
- resolution: {integrity: sha512-16Qj6kDPglpdWtU5roY9q+G66naOjauTY5HvUIaL2aLY0187ATaRrABIKoMMzTtJyhvsud4jFlzivz+/zCQ8yw==}
+ resolution: {integrity: sha512-16Qj6kDPglpdWtU5roY9q+G66naOjauTY5HvUIaL2aLY0187ATaRrABIKoMMzTtJyhvsud4jFlzivz+/zCQ8yw==, tarball: https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.3.14.tgz}
peerDependencies:
react: ^17.0.0 || ^18.0.0
react-dom: ^17.0.0 || ^18.0.0
@@ -4475,7 +4478,7 @@ packages:
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
'@ariakit/react@0.3.14':
- resolution: {integrity: sha512-h71BPMZ2eW+E2ESbdYxSAEMR1DozYzd5eHE5IOzGd9Egi5u7EZxqmuW4CXVXZ1Y6vbaDMV3SudgPh7iHS/ArFw==}
+ resolution: {integrity: sha512-h71BPMZ2eW+E2ESbdYxSAEMR1DozYzd5eHE5IOzGd9Egi5u7EZxqmuW4CXVXZ1Y6vbaDMV3SudgPh7iHS/ArFw==, tarball: https://registry.npmjs.org/@ariakit/react/-/react-0.3.14.tgz}
peerDependencies:
react: ^17.0.0 || ^18.0.0
react-dom: ^17.0.0 || ^18.0.0
@@ -5385,7 +5388,7 @@ packages:
optional: true
'@base-ui/react@1.5.0':
- resolution: {integrity: sha512-z1gSAlced1yY+iM+mHDEtIkD8UI3Ebs52MuBPxvV6f5hRutk+xvCH/wuB7hDqDzK9JG5FoMz5nhrqtSs1wjt1A==}
+ resolution: {integrity: sha512-z1gSAlced1yY+iM+mHDEtIkD8UI3Ebs52MuBPxvV6f5hRutk+xvCH/wuB7hDqDzK9JG5FoMz5nhrqtSs1wjt1A==, tarball: https://registry.npmjs.org/@base-ui/react/-/react-1.5.0.tgz}
engines: {node: '>=14.0.0'}
peerDependencies:
'@date-fns/tz': ^1.2.0
@@ -5412,7 +5415,7 @@ packages:
optional: true
'@base-ui/utils@0.2.9':
- resolution: {integrity: sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw==}
+ resolution: {integrity: sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw==, tarball: https://registry.npmjs.org/@base-ui/utils/-/utils-0.2.9.tgz}
peerDependencies:
'@types/react': 18.3.x
react: ^17 || ^18 || ^19
@@ -5428,7 +5431,7 @@ packages:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
'@bufbuild/protobuf@2.12.0':
- resolution: {integrity: sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==}
+ resolution: {integrity: sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==, tarball: https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz}
'@bundled-es-modules/cookie@2.0.1':
resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==}
@@ -5455,7 +5458,7 @@ packages:
hasBin: true
'@colors/colors@1.5.0':
- resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
+ resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==, tarball: https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz}
engines: {node: '>=0.1.90'}
'@commander-js/extra-typings@0.1.0':
@@ -5517,10 +5520,10 @@ packages:
postcss-selector-parser: ^7.0.0
'@date-fns/tz@1.4.1':
- resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==}
+ resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==, tarball: https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz}
'@date-fns/utc@2.1.1':
- resolution: {integrity: sha512-SlJDfG6RPeEX8wEVv6ZB3kak4MmbtyiI2qX/5zuKdordbrhB/iaJ58GVMZgJ6P1sJaM1gMgENFYYeg1JWrCFrA==}
+ resolution: {integrity: sha512-SlJDfG6RPeEX8wEVv6ZB3kak4MmbtyiI2qX/5zuKdordbrhB/iaJ58GVMZgJ6P1sJaM1gMgENFYYeg1JWrCFrA==, tarball: https://registry.npmjs.org/@date-fns/utc/-/utc-2.1.1.tgz}
'@discoveryjs/json-ext@0.5.7':
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
@@ -5607,34 +5610,34 @@ packages:
deprecated: this package has been merged into the main effect package
'@emnapi/core@1.9.2':
- resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==}
+ resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==, tarball: https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz}
'@emnapi/runtime@1.9.2':
- resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==}
+ resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==, tarball: https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz}
'@emnapi/wasi-threads@1.2.1':
- resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
+ resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==, tarball: https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz}
'@emotion/babel-plugin@11.13.5':
resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==}
'@emotion/cache@11.14.0':
- resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==}
+ resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==, tarball: https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz}
'@emotion/css@11.13.5':
- resolution: {integrity: sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w==}
+ resolution: {integrity: sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w==, tarball: https://registry.npmjs.org/@emotion/css/-/css-11.13.5.tgz}
'@emotion/hash@0.9.2':
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
'@emotion/is-prop-valid@0.8.8':
- resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
+ resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==, tarball: https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz}
'@emotion/is-prop-valid@1.4.0':
resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==}
'@emotion/memoize@0.7.4':
- resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==}
+ resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==, tarball: https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz}
'@emotion/memoize@0.9.0':
resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
@@ -5649,10 +5652,10 @@ packages:
optional: true
'@emotion/serialize@1.3.3':
- resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==}
+ resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==, tarball: https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz}
'@emotion/sheet@1.4.0':
- resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
+ resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==, tarball: https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz}
'@emotion/styled@11.14.1':
resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==}
@@ -5665,7 +5668,7 @@ packages:
optional: true
'@emotion/unitless@0.10.0':
- resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==}
+ resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==, tarball: https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz}
'@emotion/use-insertion-effect-with-fallbacks@1.2.0':
resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==}
@@ -5676,7 +5679,7 @@ packages:
resolution: {integrity: sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==}
'@emotion/utils@1.4.2':
- resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==}
+ resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==, tarball: https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz}
'@emotion/weak-memoize@0.4.0':
resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==}
@@ -5686,283 +5689,283 @@ packages:
engines: {node: ^14 || ^16 || ^17 || ^18 || ^19}
'@esbuild/aix-ppc64@0.24.2':
- resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
+ resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.18.20':
- resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
+ resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm64@0.24.2':
- resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==}
+ resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.18.20':
- resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
+ resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
'@esbuild/android-arm@0.24.2':
- resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==}
+ resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.18.20':
- resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
+ resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
'@esbuild/android-x64@0.24.2':
- resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==}
+ resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.18.20':
- resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
+ resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-arm64@0.24.2':
- resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==}
+ resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.18.20':
- resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
+ resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
'@esbuild/darwin-x64@0.24.2':
- resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==}
+ resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.18.20':
- resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
+ resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-arm64@0.24.2':
- resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==}
+ resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.18.20':
- resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
+ resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
'@esbuild/freebsd-x64@0.24.2':
- resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==}
+ resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.18.20':
- resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
+ resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm64@0.24.2':
- resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==}
+ resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.18.20':
- resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
+ resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
'@esbuild/linux-arm@0.24.2':
- resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==}
+ resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.18.20':
- resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
+ resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-ia32@0.24.2':
- resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==}
+ resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.18.20':
- resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
+ resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-loong64@0.24.2':
- resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==}
+ resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.18.20':
- resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
+ resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-mips64el@0.24.2':
- resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==}
+ resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.18.20':
- resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
+ resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-ppc64@0.24.2':
- resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==}
+ resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.18.20':
- resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
+ resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-riscv64@0.24.2':
- resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==}
+ resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.18.20':
- resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
+ resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-s390x@0.24.2':
- resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==}
+ resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.18.20':
- resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
+ resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
'@esbuild/linux-x64@0.24.2':
- resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==}
+ resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-arm64@0.24.2':
- resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==}
+ resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==, tarball: https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.18.20':
- resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
+ resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
'@esbuild/netbsd-x64@0.24.2':
- resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==}
+ resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.24.2':
- resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==}
+ resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.18.20':
- resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
+ resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
'@esbuild/openbsd-x64@0.24.2':
- resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==}
+ resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.18.20':
- resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
+ resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
'@esbuild/sunos-x64@0.24.2':
- resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==}
+ resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.18.20':
- resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
+ resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-arm64@0.24.2':
- resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==}
+ resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.18.20':
- resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
+ resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-ia32@0.24.2':
- resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==}
+ resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.18.20':
- resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
+ resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
'@esbuild/win32-x64@0.24.2':
- resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==}
+ resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -6410,10 +6413,10 @@ packages:
engines: {node: '>=18'}
'@napi-rs/wasm-runtime@0.2.12':
- resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
+ resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz}
'@napi-rs/wasm-runtime@1.1.3':
- resolution: {integrity: sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==}
+ resolution: {integrity: sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz}
peerDependencies:
'@emnapi/core': ^1.7.1
'@emnapi/runtime': ^1.7.1
@@ -6422,7 +6425,7 @@ packages:
resolution: {integrity: sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==}
'@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3':
- resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==}
+ resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==, tarball: https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz}
'@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
@@ -6984,110 +6987,110 @@ packages:
'@opentelemetry/api': ^1.1.0
'@oxc-resolver/binding-android-arm-eabi@11.19.1':
- resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==}
+ resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.19.1.tgz}
cpu: [arm]
os: [android]
'@oxc-resolver/binding-android-arm64@11.19.1':
- resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==}
+ resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.19.1.tgz}
cpu: [arm64]
os: [android]
'@oxc-resolver/binding-darwin-arm64@11.19.1':
- resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==}
+ resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.19.1.tgz}
cpu: [arm64]
os: [darwin]
'@oxc-resolver/binding-darwin-x64@11.19.1':
- resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==}
+ resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.19.1.tgz}
cpu: [x64]
os: [darwin]
'@oxc-resolver/binding-freebsd-x64@11.19.1':
- resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==}
+ resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.19.1.tgz}
cpu: [x64]
os: [freebsd]
'@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1':
- resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==}
+ resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.19.1.tgz}
cpu: [arm]
os: [linux]
'@oxc-resolver/binding-linux-arm-musleabihf@11.19.1':
- resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==}
+ resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.19.1.tgz}
cpu: [arm]
os: [linux]
'@oxc-resolver/binding-linux-arm64-gnu@11.19.1':
- resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==}
+ resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.19.1.tgz}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-arm64-musl@11.19.1':
- resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==}
+ resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.19.1.tgz}
cpu: [arm64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-linux-ppc64-gnu@11.19.1':
- resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==}
+ resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.19.1.tgz}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-riscv64-gnu@11.19.1':
- resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==}
+ resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.19.1.tgz}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-riscv64-musl@11.19.1':
- resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==}
+ resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.19.1.tgz}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-linux-s390x-gnu@11.19.1':
- resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==}
+ resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.19.1.tgz}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-x64-gnu@11.19.1':
- resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==}
+ resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.19.1.tgz}
cpu: [x64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-x64-musl@11.19.1':
- resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==}
+ resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.19.1.tgz}
cpu: [x64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-openharmony-arm64@11.19.1':
- resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==}
+ resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.19.1.tgz}
cpu: [arm64]
os: [openharmony]
'@oxc-resolver/binding-wasm32-wasi@11.19.1':
- resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==}
+ resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.19.1.tgz}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
'@oxc-resolver/binding-win32-arm64-msvc@11.19.1':
- resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==}
+ resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.19.1.tgz}
cpu: [arm64]
os: [win32]
'@oxc-resolver/binding-win32-ia32-msvc@11.19.1':
- resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==}
+ resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.19.1.tgz}
cpu: [ia32]
os: [win32]
'@oxc-resolver/binding-win32-x64-msvc@11.19.1':
- resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==}
+ resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.19.1.tgz}
cpu: [x64]
os: [win32]
@@ -7181,7 +7184,7 @@ packages:
hasBin: true
'@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz}
engines: {node: '>=14'}
'@pkgr/core@0.2.9':
@@ -8855,79 +8858,79 @@ packages:
engines: {node: '>=14'}
'@swc/core-darwin-arm64@1.15.24':
- resolution: {integrity: sha512-uM5ZGfFXjtvtJ+fe448PVBEbn/CSxS3UAyLj3O9xOqKIWy3S6hPTXSPbszxkSsGDYKi+YFhzAsR4r/eXLxEQ0g==}
+ resolution: {integrity: sha512-uM5ZGfFXjtvtJ+fe448PVBEbn/CSxS3UAyLj3O9xOqKIWy3S6hPTXSPbszxkSsGDYKi+YFhzAsR4r/eXLxEQ0g==, tarball: https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
'@swc/core-darwin-x64@1.15.24':
- resolution: {integrity: sha512-fMIb/Zfn929pw25VMBhV7Ji2Dl+lCWtUPNdYJQYOke+00E5fcQ9ynxtP8+qhUo/HZc+mYQb1gJxwHM9vty+lXg==}
+ resolution: {integrity: sha512-fMIb/Zfn929pw25VMBhV7Ji2Dl+lCWtUPNdYJQYOke+00E5fcQ9ynxtP8+qhUo/HZc+mYQb1gJxwHM9vty+lXg==, tarball: https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
'@swc/core-linux-arm-gnueabihf@1.15.24':
- resolution: {integrity: sha512-vOkjsyjjxnoYx3hMEWcGxQrMgnNrRm6WAegBXrN8foHtDAR+zpdhpGF5a4lj1bNPgXAvmysjui8cM1ov/Clkaw==}
+ resolution: {integrity: sha512-vOkjsyjjxnoYx3hMEWcGxQrMgnNrRm6WAegBXrN8foHtDAR+zpdhpGF5a4lj1bNPgXAvmysjui8cM1ov/Clkaw==, tarball: https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
'@swc/core-linux-arm64-gnu@1.15.24':
- resolution: {integrity: sha512-h/oNu+upkXJ6Cicnq7YGVj9PkdfarLCdQa8l/FlHYvfv8CEiMaeeTnpLU7gSBH/rGxosM6Qkfa/J9mThGF9CLA==}
+ resolution: {integrity: sha512-h/oNu+upkXJ6Cicnq7YGVj9PkdfarLCdQa8l/FlHYvfv8CEiMaeeTnpLU7gSBH/rGxosM6Qkfa/J9mThGF9CLA==, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@swc/core-linux-arm64-musl@1.15.24':
- resolution: {integrity: sha512-ZpF/pRe1guk6sKzQI9D1jAORtjTdNlyeXn9GDz8ophof/w2WhojRblvSDJaGe7rJjcPN8AaOkhwdRUh7q8oYIg==}
+ resolution: {integrity: sha512-ZpF/pRe1guk6sKzQI9D1jAORtjTdNlyeXn9GDz8ophof/w2WhojRblvSDJaGe7rJjcPN8AaOkhwdRUh7q8oYIg==, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@swc/core-linux-ppc64-gnu@1.15.24':
- resolution: {integrity: sha512-QZEsZfisHTSJlmyChgDFNmKPb3W6Lhbfo/O76HhIngfEdnQNmukS38/VSe1feho+xkV5A5hETyCbx3sALBZKAQ==}
+ resolution: {integrity: sha512-QZEsZfisHTSJlmyChgDFNmKPb3W6Lhbfo/O76HhIngfEdnQNmukS38/VSe1feho+xkV5A5hETyCbx3sALBZKAQ==, tarball: https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@swc/core-linux-s390x-gnu@1.15.24':
- resolution: {integrity: sha512-DLdJKVsJgglqQrJBuoUYNmzm3leI7kUZhLbZGHv42onfKsGf6JDS3+bzCUQfte/XOqDjh/tmmn1DR/CF/tCJFw==}
+ resolution: {integrity: sha512-DLdJKVsJgglqQrJBuoUYNmzm3leI7kUZhLbZGHv42onfKsGf6JDS3+bzCUQfte/XOqDjh/tmmn1DR/CF/tCJFw==, tarball: https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@swc/core-linux-x64-gnu@1.15.24':
- resolution: {integrity: sha512-IpLYfposPA/XLxYOKpRfeccl1p5dDa3+okZDHHTchBkXEaVCnq5MADPmIWwIYj1tudt7hORsEHccG5no6IUQRw==}
+ resolution: {integrity: sha512-IpLYfposPA/XLxYOKpRfeccl1p5dDa3+okZDHHTchBkXEaVCnq5MADPmIWwIYj1tudt7hORsEHccG5no6IUQRw==, tarball: https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@swc/core-linux-x64-musl@1.15.24':
- resolution: {integrity: sha512-JHy3fMSc0t/EPWgo74+OK5TGr51aElnzqfUPaiRf2qJ/BfX5CUCfMiWVBuhI7qmVMBnk1jTRnL/xZnOSHDPLYg==}
+ resolution: {integrity: sha512-JHy3fMSc0t/EPWgo74+OK5TGr51aElnzqfUPaiRf2qJ/BfX5CUCfMiWVBuhI7qmVMBnk1jTRnL/xZnOSHDPLYg==, tarball: https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@swc/core-win32-arm64-msvc@1.15.24':
- resolution: {integrity: sha512-Txj+qUH1z2bUd1P3JvwByfjKFti3cptlAxhWgmunBUUxy/IW3CXLZ6l6Gk4liANadKkU71nIU1X30Z5vpMT3BA==}
+ resolution: {integrity: sha512-Txj+qUH1z2bUd1P3JvwByfjKFti3cptlAxhWgmunBUUxy/IW3CXLZ6l6Gk4liANadKkU71nIU1X30Z5vpMT3BA==, tarball: https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
'@swc/core-win32-ia32-msvc@1.15.24':
- resolution: {integrity: sha512-15D/nl3XwrhFpMv+MADFOiVwv3FvH9j8c6Rf8EXBT3Q5LoMh8YnDnSgPYqw1JzPnksvsBX6QPXLiPqmcR/Z4qQ==}
+ resolution: {integrity: sha512-15D/nl3XwrhFpMv+MADFOiVwv3FvH9j8c6Rf8EXBT3Q5LoMh8YnDnSgPYqw1JzPnksvsBX6QPXLiPqmcR/Z4qQ==, tarball: https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
'@swc/core-win32-x64-msvc@1.15.24':
- resolution: {integrity: sha512-PR0PlTlPra2JbaDphrOAzm6s0v9rA0F17YzB+XbWD95B4g2cWcZY9LAeTa4xll70VLw9Jr7xBrlohqlQmelMFQ==}
+ resolution: {integrity: sha512-PR0PlTlPra2JbaDphrOAzm6s0v9rA0F17YzB+XbWD95B4g2cWcZY9LAeTa4xll70VLw9Jr7xBrlohqlQmelMFQ==, tarball: https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.24.tgz}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
@@ -8952,23 +8955,23 @@ packages:
engines: {node: '>=10'}
'@tabby_ai/hijri-converter@1.0.5':
- resolution: {integrity: sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ==}
+ resolution: {integrity: sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ==, tarball: https://registry.npmjs.org/@tabby_ai/hijri-converter/-/hijri-converter-1.0.5.tgz}
engines: {node: '>=16.0.0'}
'@tannin/compile@1.1.0':
- resolution: {integrity: sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==}
+ resolution: {integrity: sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==, tarball: https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz}
'@tannin/evaluate@1.2.0':
- resolution: {integrity: sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==}
+ resolution: {integrity: sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==, tarball: https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz}
'@tannin/plural-forms@1.1.0':
- resolution: {integrity: sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==}
+ resolution: {integrity: sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==, tarball: https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz}
'@tannin/postfix@1.1.0':
- resolution: {integrity: sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==}
+ resolution: {integrity: sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==, tarball: https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz}
'@tannin/sprintf@1.3.3':
- resolution: {integrity: sha512-RwARl+hFwhzy0tg9atWcchLFvoQiOh4rrP7uG2N5E4W80BPCUX0ElcUR9St43fxB9EfjsW2df9Qp+UsTbvQDjA==}
+ resolution: {integrity: sha512-RwARl+hFwhzy0tg9atWcchLFvoQiOh4rrP7uG2N5E4W80BPCUX0ElcUR9St43fxB9EfjsW2df9Qp+UsTbvQDjA==, tarball: https://registry.npmjs.org/@tannin/sprintf/-/sprintf-1.3.3.tgz}
'@tanstack/history@1.161.6':
resolution: {integrity: sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==}
@@ -9111,7 +9114,7 @@ packages:
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
'@tybys/wasm-util@0.10.1':
- resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+ resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==, tarball: https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz}
'@types/aria-query@4.2.2':
resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==}
@@ -9241,7 +9244,7 @@ packages:
resolution: {integrity: sha512-XDbrTSBlQV9nxE1GiDL3FaOPy4G/KaJkhDutBX48Kg8CYZMBARyyDFGCWfWJn4pobmInmwud1xxH7VJMAr0CKQ==}
'@types/gradient-parser@1.1.0':
- resolution: {integrity: sha512-SaEcbgQscHtGJ1QL+ajgDTmmqU2f6T+00jZRcFlVHUW2Asivc84LNUev/UQFyu117AsdyrtI+qpwLvgjJXJxmw==}
+ resolution: {integrity: sha512-SaEcbgQscHtGJ1QL+ajgDTmmqU2f6T+00jZRcFlVHUW2Asivc84LNUev/UQFyu117AsdyrtI+qpwLvgjJXJxmw==, tarball: https://registry.npmjs.org/@types/gradient-parser/-/gradient-parser-1.1.0.tgz}
'@types/gtag.js@0.0.10':
resolution: {integrity: sha512-98Hy7woUb3jMAMXkZQwfIOYNyfxmI0+U4m0PpCGdnd/FHk0tDpQFCqgXdNkdEoXsKkcGya/2Gew1cAJjKJspVw==}
@@ -9250,7 +9253,7 @@ packages:
resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==}
'@types/highlight-words-core@1.2.1':
- resolution: {integrity: sha512-9VZUA5omXBfn+hDxFjUDu1FOJTBM3LmvqfDey+Z6Aa8B8/JmF5SMj6FBrjfgJ/Q3YXOZd3qyTDfJyMZSs/wCUA==}
+ resolution: {integrity: sha512-9VZUA5omXBfn+hDxFjUDu1FOJTBM3LmvqfDey+Z6Aa8B8/JmF5SMj6FBrjfgJ/Q3YXOZd3qyTDfJyMZSs/wCUA==, tarball: https://registry.npmjs.org/@types/highlight-words-core/-/highlight-words-core-1.2.1.tgz}
'@types/history@4.7.11':
resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==}
@@ -9350,7 +9353,7 @@ packages:
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
'@types/mousetrap@1.6.15':
- resolution: {integrity: sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==}
+ resolution: {integrity: sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==, tarball: https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.15.tgz}
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
@@ -9416,12 +9419,12 @@ packages:
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
'@types/react-dom@16.9.25':
- resolution: {integrity: sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==}
+ resolution: {integrity: sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==, tarball: https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.25.tgz}
peerDependencies:
'@types/react': 18.3.x
'@types/react-dom@17.0.26':
- resolution: {integrity: sha512-Z+2VcYXJwOqQ79HreLU/1fyQ88eXSSFh6I3JdrEHQIfYSI0kCQpTGvOrbE6jFGGYXKsHuwY9tBa/w5Uo6KzrEg==}
+ resolution: {integrity: sha512-Z+2VcYXJwOqQ79HreLU/1fyQ88eXSSFh6I3JdrEHQIfYSI0kCQpTGvOrbE6jFGGYXKsHuwY9tBa/w5Uo6KzrEg==, tarball: https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.26.tgz}
peerDependencies:
'@types/react': 18.3.x
@@ -9547,16 +9550,16 @@ packages:
resolution: {integrity: sha512-XDc596rkiNLOg0SZRONHojDRd7oE/+96nCBTQq51fJpAfgtHCPXQUs5hYJNaImxqWeuNrqYGpBgU5fFS7ZqRHw==}
'@types/wordpress__block-library@2.6.3':
- resolution: {integrity: sha512-Rr5iO7k1j6B0d5N6ZSZjspE/Ko9fBrfTsytw8v2VgR4kGs8Z3KM/lg0Nb5UNqTBjbdv7eIvsuNvQcTzlc+IlJA==}
+ resolution: {integrity: sha512-Rr5iO7k1j6B0d5N6ZSZjspE/Ko9fBrfTsytw8v2VgR4kGs8Z3KM/lg0Nb5UNqTBjbdv7eIvsuNvQcTzlc+IlJA==, tarball: https://registry.npmjs.org/@types/wordpress__block-library/-/wordpress__block-library-2.6.3.tgz}
'@types/wordpress__blocks@12.5.18':
- resolution: {integrity: sha512-KDugvZn2fEd1mIyYSE4j0QS4vkXOyz1r4akFrnUyJBoIBVQNqDopqXW2qX7kIrTXk9MydWZpdReNDg2Me02s4g==}
+ resolution: {integrity: sha512-KDugvZn2fEd1mIyYSE4j0QS4vkXOyz1r4akFrnUyJBoIBVQNqDopqXW2qX7kIrTXk9MydWZpdReNDg2Me02s4g==, tarball: https://registry.npmjs.org/@types/wordpress__blocks/-/wordpress__blocks-12.5.18.tgz}
'@types/wordpress__edit-post@8.4.2':
- resolution: {integrity: sha512-rH+ut+I4eedDTvwXnJOrH9jEyi+PhJZQ+KZ31k3BYb8Cmd1qdRK2hJ+kdZu0QJp4XP3HA0/Q6troqYfpkF8B+A==}
+ resolution: {integrity: sha512-rH+ut+I4eedDTvwXnJOrH9jEyi+PhJZQ+KZ31k3BYb8Cmd1qdRK2hJ+kdZu0QJp4XP3HA0/Q6troqYfpkF8B+A==, tarball: https://registry.npmjs.org/@types/wordpress__edit-post/-/wordpress__edit-post-8.4.2.tgz}
'@types/wordpress__viewport@5.5.3':
- resolution: {integrity: sha512-ZVCNZ4LccDf8nYa9y7nI1cmKpNxDy28WieKpmj3pxXhjVyXzKQ4VM/otqHAo7NMckMVDoLXaZLvKUtaLDZ+QwQ==}
+ resolution: {integrity: sha512-ZVCNZ4LccDf8nYa9y7nI1cmKpNxDy28WieKpmj3pxXhjVyXzKQ4VM/otqHAo7NMckMVDoLXaZLvKUtaLDZ+QwQ==, tarball: https://registry.npmjs.org/@types/wordpress__viewport/-/wordpress__viewport-5.5.3.tgz}
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
@@ -9571,7 +9574,7 @@ packages:
resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==}
'@types/yauzl@2.10.3':
- resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
+ resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==, tarball: https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz}
'@typescript-eslint/eslint-plugin@5.62.0':
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
@@ -9720,113 +9723,113 @@ packages:
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
- resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
+ resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz}
cpu: [arm]
os: [android]
'@unrs/resolver-binding-android-arm64@1.11.1':
- resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
+ resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz}
cpu: [arm64]
os: [android]
'@unrs/resolver-binding-darwin-arm64@1.11.1':
- resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
+ resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz}
cpu: [arm64]
os: [darwin]
'@unrs/resolver-binding-darwin-x64@1.11.1':
- resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
+ resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz}
cpu: [x64]
os: [darwin]
'@unrs/resolver-binding-freebsd-x64@1.11.1':
- resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
+ resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz}
cpu: [x64]
os: [freebsd]
'@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
- resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
+ resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz}
cpu: [arm]
os: [linux]
'@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
- resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
+ resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz}
cpu: [arm]
os: [linux]
'@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
- resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
+ resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
- resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
+ resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz}
cpu: [arm64]
os: [linux]
libc: [musl]
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
- resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
+ resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
- resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
+ resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
- resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
+ resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
- resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
+ resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
- resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
+ resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz}
cpu: [x64]
os: [linux]
libc: [glibc]
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
- resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
+ resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz}
cpu: [x64]
os: [linux]
libc: [musl]
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
- resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
+ resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
'@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
- resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
+ resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz}
cpu: [arm64]
os: [win32]
'@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
- resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
+ resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz}
cpu: [ia32]
os: [win32]
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
- resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
+ resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz}
cpu: [x64]
os: [win32]
'@use-gesture/core@10.3.1':
- resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==}
+ resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==, tarball: https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz}
'@use-gesture/react@10.3.1':
- resolution: {integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==}
+ resolution: {integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==, tarball: https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz}
peerDependencies:
react: '>= 16.8.0'
@@ -9987,7 +9990,7 @@ packages:
react: ^17.0.0-0
'@wolfy1339/lru-cache@11.0.2-patch.1':
- resolution: {integrity: sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==}
+ resolution: {integrity: sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==, tarball: https://registry.npmjs.org/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz}
engines: {node: 18 >=18.20 || 20 || >=22}
'@woocommerce/settings@1.0.0':
@@ -9995,11 +9998,11 @@ packages:
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
'@wordpress/a11y@3.58.0':
- resolution: {integrity: sha512-7NnJKl4+pxP6kV/jvXaJcZZCGzW7zaj6YeMnyjUd96cH4ta1ykBIveWgejerFOGsbK+88FnStcxSFj+dbDXs/w==}
+ resolution: {integrity: sha512-7NnJKl4+pxP6kV/jvXaJcZZCGzW7zaj6YeMnyjUd96cH4ta1ykBIveWgejerFOGsbK+88FnStcxSFj+dbDXs/w==, tarball: https://registry.npmjs.org/@wordpress/a11y/-/a11y-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/a11y@4.33.1':
- resolution: {integrity: sha512-W/MeUMZPSsgYnF6/0cXTYq1JBnCd22dBsWtYJw+Ujgx7s4h52LMnx/dIGE1Xi3XzT4nPUD1DvSw0U3lIMWW5Fg==}
+ resolution: {integrity: sha512-W/MeUMZPSsgYnF6/0cXTYq1JBnCd22dBsWtYJw+Ujgx7s4h52LMnx/dIGE1Xi3XzT4nPUD1DvSw0U3lIMWW5Fg==, tarball: https://registry.npmjs.org/@wordpress/a11y/-/a11y-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/a11y@4.45.0':
@@ -10011,7 +10014,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/admin-ui@1.1.5':
- resolution: {integrity: sha512-noGT9f321cMDDUKGNtjqbyt9NsG/O43jcvkY58UAJAs1i3LCQ0heSUY6/+Wml66kjr+3qbe0r7ZrgQ0jlgxMng==}
+ resolution: {integrity: sha512-noGT9f321cMDDUKGNtjqbyt9NsG/O43jcvkY58UAJAs1i3LCQ0heSUY6/+Wml66kjr+3qbe0r7ZrgQ0jlgxMng==, tarball: https://registry.npmjs.org/@wordpress/admin-ui/-/admin-ui-1.1.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/admin-ui@1.12.0':
@@ -10021,17 +10024,17 @@ packages:
react: ^18.0.0
'@wordpress/admin-ui@2.3.1':
- resolution: {integrity: sha512-bmC2OqpXNPqMBZkVMXy4DNZC0Td8hM5Z2dH13a+F6j2NeeftkfduGofEJiONFgqFMzw3zEt3tz/JdaQ+ydRSyA==}
+ resolution: {integrity: sha512-bmC2OqpXNPqMBZkVMXy4DNZC0Td8hM5Z2dH13a+F6j2NeeftkfduGofEJiONFgqFMzw3zEt3tz/JdaQ+ydRSyA==, tarball: https://registry.npmjs.org/@wordpress/admin-ui/-/admin-ui-2.3.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/api-fetch@6.55.0':
- resolution: {integrity: sha512-1HrCUsJdeRY5Y0IjplotINwqMRO81e7O7VhBScuKk7iOuDm/E1ioKv2uLGnPNWziYu+Zf025byxOqVzXDyM2gw==}
+ resolution: {integrity: sha512-1HrCUsJdeRY5Y0IjplotINwqMRO81e7O7VhBScuKk7iOuDm/E1ioKv2uLGnPNWziYu+Zf025byxOqVzXDyM2gw==, tarball: https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-6.55.0.tgz}
engines: {node: '>=12'}
'@wordpress/api-fetch@7.33.1':
- resolution: {integrity: sha512-kxk7Og2CZLOMUZtDfOXSGapem4ToP15JB24PfixJLS0dKfrlUBci4ShjJ3z3jdIx01gf1gfP4NFjqzicJKb+Rg==}
+ resolution: {integrity: sha512-kxk7Og2CZLOMUZtDfOXSGapem4ToP15JB24PfixJLS0dKfrlUBci4ShjJ3z3jdIx01gf1gfP4NFjqzicJKb+Rg==, tarball: https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-7.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/api-fetch@7.48.1':
@@ -10079,14 +10082,14 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/base-styles@10.0.1':
- resolution: {integrity: sha512-Kkayj4f6KzcMW2TFaahADE0aoDpYeqadIinvIp0hxY6+zn/uqK1Ml7x5idLZ/jbyzzbVlI31eid3HtblGY3+og==}
+ resolution: {integrity: sha512-Kkayj4f6KzcMW2TFaahADE0aoDpYeqadIinvIp0hxY6+zn/uqK1Ml7x5idLZ/jbyzzbVlI31eid3HtblGY3+og==, tarball: https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-10.0.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/base-styles@4.49.0':
- resolution: {integrity: sha512-yFRYqNtd26ULZ0oAHhCu/IcaA0XHI3E7kRCKajZqUvyRQj7YprXnpD3o0/pnwvF6ZFTXzCX8pXHjUc2TIv97ig==}
+ resolution: {integrity: sha512-yFRYqNtd26ULZ0oAHhCu/IcaA0XHI3E7kRCKajZqUvyRQj7YprXnpD3o0/pnwvF6ZFTXzCX8pXHjUc2TIv97ig==, tarball: https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-4.49.0.tgz}
'@wordpress/base-styles@5.23.0':
- resolution: {integrity: sha512-1mtX3jA9el2ZDkAJp7YEN1bX+DzfX0h496uxpRk+evmQJLZxBMPeu5datJFtwkWbVitOsR88WCDvUoNoKJMSuw==}
+ resolution: {integrity: sha512-1mtX3jA9el2ZDkAJp7YEN1bX+DzfX0h496uxpRk+evmQJLZxBMPeu5datJFtwkWbVitOsR88WCDvUoNoKJMSuw==, tarball: https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-5.23.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/base-styles@6.20.0':
@@ -10094,19 +10097,19 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/base-styles@6.9.1':
- resolution: {integrity: sha512-UCtTANAdym5jpTEZS17WHrKLu7R52gQRgKuwsRm5uZWUb4g4Vq8NX52CBIesF1viFyKfM++HpmteFkrL7p0SMg==}
+ resolution: {integrity: sha512-UCtTANAdym5jpTEZS17WHrKLu7R52gQRgKuwsRm5uZWUb4g4Vq8NX52CBIesF1viFyKfM++HpmteFkrL7p0SMg==, tarball: https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-6.9.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/base-styles@7.0.0':
- resolution: {integrity: sha512-Q0BbZzfeYbQZKHnyNT4RF8RGVugN5jStGtpRKhBYQW7ut7sS61LbbpP7jR0D0sDPYoEEC8jKZQSZwSM23B4jow==}
+ resolution: {integrity: sha512-Q0BbZzfeYbQZKHnyNT4RF8RGVugN5jStGtpRKhBYQW7ut7sS61LbbpP7jR0D0sDPYoEEC8jKZQSZwSM23B4jow==, tarball: https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-7.0.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/blob@3.58.0':
- resolution: {integrity: sha512-6L3WqbOWEGFOSs3vLMwJ83YScggCiJ9NvZj1kC7mgeiP302UP2Fxkt4KlfjeTsD350XcvakkD/57wRkHXd819Q==}
+ resolution: {integrity: sha512-6L3WqbOWEGFOSs3vLMwJ83YScggCiJ9NvZj1kC7mgeiP302UP2Fxkt4KlfjeTsD350XcvakkD/57wRkHXd819Q==, tarball: https://registry.npmjs.org/@wordpress/blob/-/blob-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/blob@4.33.1':
- resolution: {integrity: sha512-3a0gY6+f1UcF82mbviSFzRDzQ8dEACwISkXNrwvV7Y70ke5F1UHWWkux4S15f7OcaeTs/L4SWTqZ0y5ufzHioA==}
+ resolution: {integrity: sha512-3a0gY6+f1UcF82mbviSFzRDzQ8dEACwISkXNrwvV7Y70ke5F1UHWWkux4S15f7OcaeTs/L4SWTqZ0y5ufzHioA==, tarball: https://registry.npmjs.org/@wordpress/blob/-/blob-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/blob@4.48.1':
@@ -10114,7 +10117,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/block-editor@12.26.0':
- resolution: {integrity: sha512-wkBP37hB6Fb1AaUIjry6S3LlFrjnVq3Seg8ktZPLozDv2cyODs/ym8+wjv8TR/aiuSWdk0dZZywYMNc+vHEfEg==}
+ resolution: {integrity: sha512-wkBP37hB6Fb1AaUIjry6S3LlFrjnVq3Seg8ktZPLozDv2cyODs/ym8+wjv8TR/aiuSWdk0dZZywYMNc+vHEfEg==, tarball: https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-12.26.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -10128,7 +10131,7 @@ packages:
react-dom: ^18.0.0
'@wordpress/block-editor@15.6.9':
- resolution: {integrity: sha512-X5S7oWsTCpNIUHbsx/ZMN+2AXnILn3EeotUWAj8DsHtFFgfiDnbo2kKPaWANgGtHJ+GNWZPr0RUyS9Gmtdwn1A==}
+ resolution: {integrity: sha512-X5S7oWsTCpNIUHbsx/ZMN+2AXnILn3EeotUWAj8DsHtFFgfiDnbo2kKPaWANgGtHJ+GNWZPr0RUyS9Gmtdwn1A==, tarball: https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-15.6.9.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10142,7 +10145,7 @@ packages:
react-dom: ^18.0.0
'@wordpress/block-library@9.33.10':
- resolution: {integrity: sha512-9qrBXTc1BR539L78KuMCZ7PHt4US822NSKKVNcgVTkPH2qHyUDvr6t680HRHCI7VYWq1NXp9teZo7PEZNVfhVA==}
+ resolution: {integrity: sha512-9qrBXTc1BR539L78KuMCZ7PHt4US822NSKKVNcgVTkPH2qHyUDvr6t680HRHCI7VYWq1NXp9teZo7PEZNVfhVA==, tarball: https://registry.npmjs.org/@wordpress/block-library/-/block-library-9.33.10.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10157,7 +10160,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/blocks@12.35.0':
- resolution: {integrity: sha512-BwjMca4aGuttu3C0nLLpt6MBg6IBCogA6ulGTyg+0YdKnwac52k+2wfersqAem8AFgG0hTDwrIpLsWLxpF9dtg==}
+ resolution: {integrity: sha512-BwjMca4aGuttu3C0nLLpt6MBg6IBCogA6ulGTyg+0YdKnwac52k+2wfersqAem8AFgG0hTDwrIpLsWLxpF9dtg==, tarball: https://registry.npmjs.org/@wordpress/blocks/-/blocks-12.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -10169,7 +10172,7 @@ packages:
react: ^18.0.0
'@wordpress/blocks@15.6.3':
- resolution: {integrity: sha512-AFYre+06ZVtyv0KSVwCOUY+HSEdAaQRxFrRZnSsZ5FEs0pMMIsulFYay8QvlVVTtBUKbYlxKEDi8kD1DI+8jxA==}
+ resolution: {integrity: sha512-AFYre+06ZVtyv0KSVwCOUY+HSEdAaQRxFrRZnSsZ5FEs0pMMIsulFYay8QvlVVTtBUKbYlxKEDi8kD1DI+8jxA==, tarball: https://registry.npmjs.org/@wordpress/blocks/-/blocks-15.6.3.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10191,7 +10194,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/commands@0.29.0':
- resolution: {integrity: sha512-HqTrYfQw/5cdT2hPgmuKW6gugnt1Pqtg9zjRHUa+D4ME7mjR4dYQoHRgnFM+hm8OOuEZRVBsa1kYO3t3041Jew==}
+ resolution: {integrity: sha512-HqTrYfQw/5cdT2hPgmuKW6gugnt1Pqtg9zjRHUa+D4ME7mjR4dYQoHRgnFM+hm8OOuEZRVBsa1kYO3t3041Jew==, tarball: https://registry.npmjs.org/@wordpress/commands/-/commands-0.29.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -10204,7 +10207,7 @@ packages:
react: ^18.0.0
'@wordpress/commands@1.33.5':
- resolution: {integrity: sha512-m8a/9ahGzEVYj77EfS6crzjq2Gq97DOXbeSqRSHrpePE/NSXPh6AAABRP/dKCI/0AysjJ0v/bKKTVnsFgkk0YA==}
+ resolution: {integrity: sha512-m8a/9ahGzEVYj77EfS6crzjq2Gq97DOXbeSqRSHrpePE/NSXPh6AAABRP/dKCI/0AysjJ0v/bKKTVnsFgkk0YA==, tarball: https://registry.npmjs.org/@wordpress/commands/-/commands-1.33.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10224,28 +10227,28 @@ packages:
reakit-utils: ^0.15.1
'@wordpress/components@25.16.0':
- resolution: {integrity: sha512-voQuMsO5JbH+JW33TnWurwwvpSb8IQ4XU5wyVMubX4TUwadt+/2ToNJbZIDXoaJPei7vbM81Ft+pH+zGlN8CyA==}
+ resolution: {integrity: sha512-voQuMsO5JbH+JW33TnWurwwvpSb8IQ4XU5wyVMubX4TUwadt+/2ToNJbZIDXoaJPei7vbM81Ft+pH+zGlN8CyA==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-25.16.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@27.6.0':
- resolution: {integrity: sha512-f+fXENkgrPs5GLo2yu9fEAdVX0KriEatRcjDUyw0+DbNbJR62sCdDtGdhJRW4jPUUoUowxaGO0y4+jvQWxnbyg==}
+ resolution: {integrity: sha512-f+fXENkgrPs5GLo2yu9fEAdVX0KriEatRcjDUyw0+DbNbJR62sCdDtGdhJRW4jPUUoUowxaGO0y4+jvQWxnbyg==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-27.6.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@28.13.0':
- resolution: {integrity: sha512-JaGcXYtFCvHqa62dtxMAMhu6afvefFOuwfUTNiLYg60CA4UDITt6gf+qhpvKNOzVg4qQRw10o/nryrOMoMAEEg==}
+ resolution: {integrity: sha512-JaGcXYtFCvHqa62dtxMAMhu6afvefFOuwfUTNiLYg60CA4UDITt6gf+qhpvKNOzVg4qQRw10o/nryrOMoMAEEg==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-28.13.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@29.12.0':
- resolution: {integrity: sha512-jE96pUj84OZya54VusRdEIdTiLjbe2Qst3GbHZcQpA5GiSkPBmGjKWpO6FxR7kRDT4GMnZoVxgtV6xJk4IaNQw==}
+ resolution: {integrity: sha512-jE96pUj84OZya54VusRdEIdTiLjbe2Qst3GbHZcQpA5GiSkPBmGjKWpO6FxR7kRDT4GMnZoVxgtV6xJk4IaNQw==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-29.12.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10259,58 +10262,58 @@ packages:
react-dom: ^18.0.0
'@wordpress/components@30.6.5':
- resolution: {integrity: sha512-jSDpUz1BBQvpWUGwqZUlI22PMGMtiN5ooKS4GlQqjUmEBJH4llwiRblkZBKgdznv+5KDYyDiRNIGCz/hLSdwZw==}
+ resolution: {integrity: sha512-jSDpUz1BBQvpWUGwqZUlI22PMGMtiN5ooKS4GlQqjUmEBJH4llwiRblkZBKgdznv+5KDYyDiRNIGCz/hLSdwZw==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-30.6.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@30.9.0':
- resolution: {integrity: sha512-mx0df0TjChmpCtqQn3iFHphqaLQVNk5Yprs+3NJSfm1kWuZPKfVys6AtmhfBgXs/VrrJk34Z+1N+nqXovHuXnw==}
+ resolution: {integrity: sha512-mx0df0TjChmpCtqQn3iFHphqaLQVNk5Yprs+3NJSfm1kWuZPKfVys6AtmhfBgXs/VrrJk34Z+1N+nqXovHuXnw==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-30.9.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@32.6.0':
- resolution: {integrity: sha512-MpOr0mGTkKDRjxK5LKm86Uoj9p9Z6KkrvhkNVi5zVKCftyHVMK+tun7wL2Qn/JZVLbxZpB1kW5sJ5aMf3T2ToA==}
+ resolution: {integrity: sha512-MpOr0mGTkKDRjxK5LKm86Uoj9p9Z6KkrvhkNVi5zVKCftyHVMK+tun7wL2Qn/JZVLbxZpB1kW5sJ5aMf3T2ToA==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-32.6.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@33.0.0':
- resolution: {integrity: sha512-VeLDtfz8612bdRqgQiSMtIIEGDi4ZByj0XUvjT7E6RVLgczQyV9DTpGOPyL6PbTyAluIx6hjt9bzsaC+bM6G+w==}
+ resolution: {integrity: sha512-VeLDtfz8612bdRqgQiSMtIIEGDi4ZByj0XUvjT7E6RVLgczQyV9DTpGOPyL6PbTyAluIx6hjt9bzsaC+bM6G+w==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-33.0.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/components@35.0.1':
- resolution: {integrity: sha512-EiTeufX2spZ09kjI8Aa4c7dG6A3WyRSGyHTcCsVnIoE/ykOnAjtGSxnVRAT1KefrJ9RGI8JaTld48wjrB/CS5A==}
+ resolution: {integrity: sha512-EiTeufX2spZ09kjI8Aa4c7dG6A3WyRSGyHTcCsVnIoE/ykOnAjtGSxnVRAT1KefrJ9RGI8JaTld48wjrB/CS5A==, tarball: https://registry.npmjs.org/@wordpress/components/-/components-35.0.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/compose@4.2.0':
- resolution: {integrity: sha512-8CJ4wzTXT9ZP+uIvN1d2cPBv06ZmhUh+UKzSf7v1o7T28SaYRcoZbsvDD2dnXbS2ZwWPIYAD9waNLWjCBq/izA==}
+ resolution: {integrity: sha512-8CJ4wzTXT9ZP+uIvN1d2cPBv06ZmhUh+UKzSf7v1o7T28SaYRcoZbsvDD2dnXbS2ZwWPIYAD9waNLWjCBq/izA==, tarball: https://registry.npmjs.org/@wordpress/compose/-/compose-4.2.0.tgz}
engines: {node: '>=12'}
'@wordpress/compose@6.35.0':
- resolution: {integrity: sha512-PfruhCxxxJokDQHc2YBgerEiHV7BIxQk9g5vU4/f9X/0PBQWUTuxOzSFcAba03vnjfAgtPTSMp50T50hcJwXfA==}
+ resolution: {integrity: sha512-PfruhCxxxJokDQHc2YBgerEiHV7BIxQk9g5vU4/f9X/0PBQWUTuxOzSFcAba03vnjfAgtPTSMp50T50hcJwXfA==, tarball: https://registry.npmjs.org/@wordpress/compose/-/compose-6.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
'@wordpress/compose@7.20.0':
- resolution: {integrity: sha512-L84QUGXbXPdCAgNDNmmH+4tJuAl1MwH5an6CaQ+NaSXk4kM4xAc42znHo0n5LfsRmWxOPrtlGikxMXCaejvoyw==}
+ resolution: {integrity: sha512-L84QUGXbXPdCAgNDNmmH+4tJuAl1MwH5an6CaQ+NaSXk4kM4xAc42znHo0n5LfsRmWxOPrtlGikxMXCaejvoyw==, tarball: https://registry.npmjs.org/@wordpress/compose/-/compose-7.20.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/compose@7.33.1':
- resolution: {integrity: sha512-1satS+7EKlzZOCR++uP8mAy3BJPKX2eeTZHVW3669n0xM1xdmzl9JXyEbtEqaFVYhI3dHTq5kLwrm+aSpn0zag==}
+ resolution: {integrity: sha512-1satS+7EKlzZOCR++uP8mAy3BJPKX2eeTZHVW3669n0xM1xdmzl9JXyEbtEqaFVYhI3dHTq5kLwrm+aSpn0zag==, tarball: https://registry.npmjs.org/@wordpress/compose/-/compose-7.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10322,7 +10325,7 @@ packages:
react: ^18.0.0
'@wordpress/compose@8.1.1':
- resolution: {integrity: sha512-AEC9yOS5CuTk34F+oiWebhQrxgICnb/v/KScQBUVm6zbs1AMFtu5ku+Zk0A3YTD0tO/hNzXLbvsXhJdh1bGkRA==}
+ resolution: {integrity: sha512-AEC9yOS5CuTk34F+oiWebhQrxgICnb/v/KScQBUVm6zbs1AMFtu5ku+Zk0A3YTD0tO/hNzXLbvsXhJdh1bGkRA==, tarball: https://registry.npmjs.org/@wordpress/compose/-/compose-8.1.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10334,7 +10337,7 @@ packages:
react: ^18.0.0
'@wordpress/core-data@6.35.0':
- resolution: {integrity: sha512-VnESF55nkAkKHQVwj0Oo8AU6w/yWjg/RQb+wKqJRnDuHEKHDAF5PI+9lYmcAsbXdnAc2yyf3lwBGk4w8m4uxlA==}
+ resolution: {integrity: sha512-VnESF55nkAkKHQVwj0Oo8AU6w/yWjg/RQb+wKqJRnDuHEKHDAF5PI+9lYmcAsbXdnAc2yyf3lwBGk4w8m4uxlA==, tarball: https://registry.npmjs.org/@wordpress/core-data/-/core-data-6.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -10348,14 +10351,14 @@ packages:
react-dom: ^18.0.0
'@wordpress/core-data@7.48.1':
- resolution: {integrity: sha512-ITnh9M8RStzvl4+zSlz0ORPWih3VXChN5X+hYEHj80KlB+pBBOuE+JghTPF3wYEH/VmYxDV1IJmsuOC2luor+w==}
+ resolution: {integrity: sha512-ITnh9M8RStzvl4+zSlz0ORPWih3VXChN5X+hYEHj80KlB+pBBOuE+JghTPF3wYEH/VmYxDV1IJmsuOC2luor+w==, tarball: https://registry.npmjs.org/@wordpress/core-data/-/core-data-7.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/data-controls@4.33.1':
- resolution: {integrity: sha512-+gD47q6WuZ2MYMxwUBwBTYACMayrZoyG6W6OR1Q2ggOfkmoQb4OlxEWJPdCIC8GxJJwVh8ej9HjzzI3S/tDsJg==}
+ resolution: {integrity: sha512-+gD47q6WuZ2MYMxwUBwBTYACMayrZoyG6W6OR1Q2ggOfkmoQb4OlxEWJPdCIC8GxJJwVh8ej9HjzzI3S/tDsJg==, tarball: https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10373,7 +10376,7 @@ packages:
react: ^18.0.0
'@wordpress/data@10.45.0':
- resolution: {integrity: sha512-OR/uMpcEbCh1aBkbzateXffNrL829M+N92qtuD+Gt08Mey129WIEVR9kBC2Tf02VtXs644OKZD6cz77KlxH8XA==}
+ resolution: {integrity: sha512-OR/uMpcEbCh1aBkbzateXffNrL829M+N92qtuD+Gt08Mey129WIEVR9kBC2Tf02VtXs644OKZD6cz77KlxH8XA==, tarball: https://registry.npmjs.org/@wordpress/data/-/data-10.45.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10385,19 +10388,19 @@ packages:
react: ^18.0.0
'@wordpress/data@5.2.0':
- resolution: {integrity: sha512-NlPIC8PdKnPly9CnynQS1di59Af3eiCZrQgZm1VssfA620NDoJA5p3dlDYj/Ts4Ryzp78HCi7wjhkmbsHpnd6g==}
+ resolution: {integrity: sha512-NlPIC8PdKnPly9CnynQS1di59Af3eiCZrQgZm1VssfA620NDoJA5p3dlDYj/Ts4Ryzp78HCi7wjhkmbsHpnd6g==, tarball: https://registry.npmjs.org/@wordpress/data/-/data-5.2.0.tgz}
engines: {node: '>=12'}
peerDependencies:
redux: ^4.1.0
'@wordpress/data@9.28.0':
- resolution: {integrity: sha512-EDPpZdkngdoW7EMzPpGj0BmNcr7syJO67pgTODtN/4XFIdYL2RKzFyn3nlLBKhX17UsE/ALq9WdijacH4QJ9qw==}
+ resolution: {integrity: sha512-EDPpZdkngdoW7EMzPpGj0BmNcr7syJO67pgTODtN/4XFIdYL2RKzFyn3nlLBKhX17UsE/ALq9WdijacH4QJ9qw==, tarball: https://registry.npmjs.org/@wordpress/data/-/data-9.28.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
'@wordpress/dataviews@10.1.7':
- resolution: {integrity: sha512-Zz9aWvuOkZCfTNHEh7r3HFCSgjpGjcuHb8Cn0kzTy3O+ViL4V25Ny0l9spqqOanELRF/L4Eboj1agTgg/OhKNA==}
+ resolution: {integrity: sha512-Zz9aWvuOkZCfTNHEh7r3HFCSgjpGjcuHb8Cn0kzTy3O+ViL4V25Ny0l9spqqOanELRF/L4Eboj1agTgg/OhKNA==, tarball: https://registry.npmjs.org/@wordpress/dataviews/-/dataviews-10.1.7.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10411,14 +10414,14 @@ packages:
react-dom: ^18.0.0
'@wordpress/dataviews@14.2.0':
- resolution: {integrity: sha512-jTsXH3fDEQbvtK7N/giZJtE/NdDYN/LOlf6dkbfh89GyJmvwuikQZjpX10DexqOjc8AcNPUd1hU2b1sL8d99HA==}
+ resolution: {integrity: sha512-jTsXH3fDEQbvtK7N/giZJtE/NdDYN/LOlf6dkbfh89GyJmvwuikQZjpX10DexqOjc8AcNPUd1hU2b1sL8d99HA==, tarball: https://registry.npmjs.org/@wordpress/dataviews/-/dataviews-14.2.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/dataviews@16.0.1':
- resolution: {integrity: sha512-OyDOPvtCIL0AV4wTGSrFHhBVEYwkBJvmfleSjXzGWc09u3BPIiefazoGN4GvtJPJbvieSyelXuVyN+JARIRUug==}
+ resolution: {integrity: sha512-OyDOPvtCIL0AV4wTGSrFHhBVEYwkBJvmfleSjXzGWc09u3BPIiefazoGN4GvtJPJbvieSyelXuVyN+JARIRUug==, tarball: https://registry.npmjs.org/@wordpress/dataviews/-/dataviews-16.0.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10435,23 +10438,23 @@ packages:
- '@wordpress/base-styles'
'@wordpress/date@4.58.0':
- resolution: {integrity: sha512-yFT7DU0H9W0lsDytMaVMmjho08X1LeBMIQMppxdtKB04Ujx58hVh7gtunOsstUQ7pVg23nE2eLaVfx5JOdjzAw==}
+ resolution: {integrity: sha512-yFT7DU0H9W0lsDytMaVMmjho08X1LeBMIQMppxdtKB04Ujx58hVh7gtunOsstUQ7pVg23nE2eLaVfx5JOdjzAw==, tarball: https://registry.npmjs.org/@wordpress/date/-/date-4.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/date@5.20.0':
- resolution: {integrity: sha512-V34zSLveuXTe8wvnIpUXroP7dP9FK1HzMmGNB5JtoPhrqJeNvP4fzju8RJwBGpU1sFaqO3w+EZoNdTV9k0hqxA==}
+ resolution: {integrity: sha512-V34zSLveuXTe8wvnIpUXroP7dP9FK1HzMmGNB5JtoPhrqJeNvP4fzju8RJwBGpU1sFaqO3w+EZoNdTV9k0hqxA==, tarball: https://registry.npmjs.org/@wordpress/date/-/date-5.20.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/date@5.33.1':
- resolution: {integrity: sha512-8M25DKrC39v3IgjWScy722NiNYdlodjUawjLJBjdtaO73ZEtPXrWVocT+HKFqDVAoTGqF/J43IFxxW020+udXA==}
+ resolution: {integrity: sha512-8M25DKrC39v3IgjWScy722NiNYdlodjUawjLJBjdtaO73ZEtPXrWVocT+HKFqDVAoTGqF/J43IFxxW020+udXA==, tarball: https://registry.npmjs.org/@wordpress/date/-/date-5.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/date@5.45.0':
- resolution: {integrity: sha512-34v3hCxn68kYzWs8bhuAt8cfMxdFX9ukKn3a3FB+tAJXpxafnPCcZoWfJHn4I8hepCbreFrf3UiGdA+id2kQ4A==}
+ resolution: {integrity: sha512-34v3hCxn68kYzWs8bhuAt8cfMxdFX9ukKn3a3FB+tAJXpxafnPCcZoWfJHn4I8hepCbreFrf3UiGdA+id2kQ4A==, tarball: https://registry.npmjs.org/@wordpress/date/-/date-5.45.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/date@5.48.1':
- resolution: {integrity: sha512-SD6AzzmxtsrTbSkZFV6nklYzYgZFDuCxX41kxRmIQGTBNP0f4DvLjwlUCpLN/lHEerctx4XdkZAghvGOHOKvbg==}
+ resolution: {integrity: sha512-SD6AzzmxtsrTbSkZFV6nklYzYgZFDuCxX41kxRmIQGTBNP0f4DvLjwlUCpLN/lHEerctx4XdkZAghvGOHOKvbg==, tarball: https://registry.npmjs.org/@wordpress/date/-/date-5.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/dependency-extraction-webpack-plugin@3.7.0':
@@ -10479,43 +10482,43 @@ packages:
webpack: ^5.0.0
'@wordpress/deprecated@3.58.0':
- resolution: {integrity: sha512-knweE2lLEUxWRr6A48sHiO0ww5pPybGe2NVIZVq/y7EaYCMdpy6gYA0ZdVqMKZvtxKKqicJfwigcn+hinsTvUQ==}
+ resolution: {integrity: sha512-knweE2lLEUxWRr6A48sHiO0ww5pPybGe2NVIZVq/y7EaYCMdpy6gYA0ZdVqMKZvtxKKqicJfwigcn+hinsTvUQ==, tarball: https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/deprecated@4.33.1':
- resolution: {integrity: sha512-dDOGfYtebSj0iSmOAJD7HiqXacx6lLJZkhRKPeffXG8e990EBVa2qgcRt2jcQHaSO/h9gmOsGmC7trEG66YzMA==}
+ resolution: {integrity: sha512-dDOGfYtebSj0iSmOAJD7HiqXacx6lLJZkhRKPeffXG8e990EBVa2qgcRt2jcQHaSO/h9gmOsGmC7trEG66YzMA==, tarball: https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/deprecated@4.45.0':
- resolution: {integrity: sha512-qer/fk/lgmmisb8/hj1xZtsbJbZhCoOblhyxI2k7RRul7rQDdk+fm28LJYV+eIF0ldSVX30f4dmz1pvcVHQEEg==}
+ resolution: {integrity: sha512-qer/fk/lgmmisb8/hj1xZtsbJbZhCoOblhyxI2k7RRul7rQDdk+fm28LJYV+eIF0ldSVX30f4dmz1pvcVHQEEg==, tarball: https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-4.45.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/deprecated@4.48.1':
- resolution: {integrity: sha512-ZfJSCxWr4Ss5qGja9W7L6+8vcrbX0n+tKDe2TrYvTq6GiqEc+0MrajIl4vi/58jhceHbSze1ITX/ocC3Ed3NLg==}
+ resolution: {integrity: sha512-ZfJSCxWr4Ss5qGja9W7L6+8vcrbX0n+tKDe2TrYvTq6GiqEc+0MrajIl4vi/58jhceHbSze1ITX/ocC3Ed3NLg==, tarball: https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-4.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/dom-ready@3.58.0':
- resolution: {integrity: sha512-sDgRPjNBToRKgYrpwvMRv2Yc7/17+sp8hm/rRnbubwb+d/DbGkK4Tc/r4sNLSZCqUAtcBXq9uk1lzvhge3QUSg==}
+ resolution: {integrity: sha512-sDgRPjNBToRKgYrpwvMRv2Yc7/17+sp8hm/rRnbubwb+d/DbGkK4Tc/r4sNLSZCqUAtcBXq9uk1lzvhge3QUSg==, tarball: https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/dom-ready@4.33.1':
- resolution: {integrity: sha512-jrHN/arTKp2iuYj24byFgabBhZsZ3WUXCSKT16d/1MZUXGQt876XXu6r5rwpLtnVsX2gFiZ/DzdRKCL4RV9Wpg==}
+ resolution: {integrity: sha512-jrHN/arTKp2iuYj24byFgabBhZsZ3WUXCSKT16d/1MZUXGQt876XXu6r5rwpLtnVsX2gFiZ/DzdRKCL4RV9Wpg==, tarball: https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/dom-ready@4.48.1':
- resolution: {integrity: sha512-EYd2H8cYSk8H3wSnTK1wTtuC+hOCmMmZrCEBWzgHevs1n3B9g0nwBafSiRWpzc0vA2vculkNNtlSfy3ByJ2hag==}
+ resolution: {integrity: sha512-EYd2H8cYSk8H3wSnTK1wTtuC+hOCmMmZrCEBWzgHevs1n3B9g0nwBafSiRWpzc0vA2vculkNNtlSfy3ByJ2hag==, tarball: https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-4.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/dom@3.58.0':
- resolution: {integrity: sha512-t3xSr/nqekj2qwUGRAqSeGx6116JOBxzI+VBiUfZrjGEnuyKdLelXDEeYtcwbb7etMkj/6F60/NB7GTl5IwizQ==}
+ resolution: {integrity: sha512-t3xSr/nqekj2qwUGRAqSeGx6116JOBxzI+VBiUfZrjGEnuyKdLelXDEeYtcwbb7etMkj/6F60/NB7GTl5IwizQ==, tarball: https://registry.npmjs.org/@wordpress/dom/-/dom-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/dom@4.33.1':
- resolution: {integrity: sha512-1ow6ikYbE+p2xMCykZecGqRmZBqz0Z90KQ06EbKFr9tJ9tSgp05Jm6J7Op3VclJxJ+6as5js+28ppps3eVzGcg==}
+ resolution: {integrity: sha512-1ow6ikYbE+p2xMCykZecGqRmZBqz0Z90KQ06EbKFr9tJ9tSgp05Jm6J7Op3VclJxJ+6as5js+28ppps3eVzGcg==, tarball: https://registry.npmjs.org/@wordpress/dom/-/dom-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/dom@4.48.1':
- resolution: {integrity: sha512-UmouS3KAAUf6q90adAM37FZ3Tq+w+5UfNVUEKRtZjzbH3gMZJTKmYXpG9dkYyLLmicXgOrcG1GQ0qTX91MjAuA==}
+ resolution: {integrity: sha512-UmouS3KAAUf6q90adAM37FZ3Tq+w+5UfNVUEKRtZjzbH3gMZJTKmYXpG9dkYyLLmicXgOrcG1GQ0qTX91MjAuA==, tarball: https://registry.npmjs.org/@wordpress/dom/-/dom-4.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/e2e-test-utils-playwright@0.26.0':
@@ -10525,13 +10528,13 @@ packages:
'@playwright/test': '>=1'
'@wordpress/e2e-test-utils-playwright@1.33.2':
- resolution: {integrity: sha512-lKC7VPxeT17605GtKYTUIBGG1a/m9V0CmCEbcjaAfWjxFKUVgaAGELWsgaUICipUUInQuHZJO6wUsdZOXZnc5w==}
+ resolution: {integrity: sha512-lKC7VPxeT17605GtKYTUIBGG1a/m9V0CmCEbcjaAfWjxFKUVgaAGELWsgaUICipUUInQuHZJO6wUsdZOXZnc5w==, tarball: https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-1.33.2.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
'@playwright/test': '>=1'
'@wordpress/e2e-test-utils-playwright@1.44.0':
- resolution: {integrity: sha512-iUKHGH8TjW1s0cpkcHF6y/APOmy4YnwBfzdBNCITK4+4fuSZnTV7vZyzBU3adthGcBSMGQ9w8MTE2AzGLtlG3w==}
+ resolution: {integrity: sha512-iUKHGH8TjW1s0cpkcHF6y/APOmy4YnwBfzdBNCITK4+4fuSZnTV7vZyzBU3adthGcBSMGQ9w8MTE2AzGLtlG3w==, tarball: https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-1.44.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
'@playwright/test': '>=1'
@@ -10545,7 +10548,7 @@ packages:
react-dom: ^18.0.0
'@wordpress/editor@13.35.0':
- resolution: {integrity: sha512-AngLr3JrZ62efsmSHi6+drQPlbifnSr86VLr69fKWzOL2xTOcr+kpwN+HdhmPmgrnrKfxhxsVBLZ2SXp7zXAWg==}
+ resolution: {integrity: sha512-AngLr3JrZ62efsmSHi6+drQPlbifnSr86VLr69fKWzOL2xTOcr+kpwN+HdhmPmgrnrKfxhxsVBLZ2SXp7zXAWg==, tarball: https://registry.npmjs.org/@wordpress/editor/-/editor-13.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -10559,19 +10562,19 @@ packages:
react-dom: ^18.0.0
'@wordpress/element@3.2.0':
- resolution: {integrity: sha512-YXJhtBF8FnFYwA9X6Dvs4k6yJf5wy1lhU04VNJVzoUDwCt/pK747RGePIPDdUWVd3X/TlyNH2yLRtcCyOC/SzQ==}
+ resolution: {integrity: sha512-YXJhtBF8FnFYwA9X6Dvs4k6yJf5wy1lhU04VNJVzoUDwCt/pK747RGePIPDdUWVd3X/TlyNH2yLRtcCyOC/SzQ==, tarball: https://registry.npmjs.org/@wordpress/element/-/element-3.2.0.tgz}
engines: {node: '>=12'}
'@wordpress/element@4.20.0':
- resolution: {integrity: sha512-Ou7EoGtGe4FUL6fKALINXJLKoSfyWTBJzkJfN2HzSgM1wira9EuWahl8MQN0HAUaWeOoDqMKPvnglfS+kC8JLA==}
+ resolution: {integrity: sha512-Ou7EoGtGe4FUL6fKALINXJLKoSfyWTBJzkJfN2HzSgM1wira9EuWahl8MQN0HAUaWeOoDqMKPvnglfS+kC8JLA==, tarball: https://registry.npmjs.org/@wordpress/element/-/element-4.20.0.tgz}
engines: {node: '>=12'}
'@wordpress/element@5.35.0':
- resolution: {integrity: sha512-puswpGcIdS+0A2g28uHriMkZqqRCmzFczue5Tk99VNtzBdehyk7Ae+DZ4xw5yT6GqYai8NTqv6MRwCB78uh5Mw==}
+ resolution: {integrity: sha512-puswpGcIdS+0A2g28uHriMkZqqRCmzFczue5Tk99VNtzBdehyk7Ae+DZ4xw5yT6GqYai8NTqv6MRwCB78uh5Mw==, tarball: https://registry.npmjs.org/@wordpress/element/-/element-5.35.0.tgz}
engines: {node: '>=12'}
'@wordpress/element@6.33.1':
- resolution: {integrity: sha512-8Y2TEkduT1cAGVfh5HoERpJIVvCcfHI1k+PGgG3wzy85me6hjgA/P7l90yBt/9i9Omt5+buGfnklobstECR8zg==}
+ resolution: {integrity: sha512-8Y2TEkduT1cAGVfh5HoERpJIVvCcfHI1k+PGgG3wzy85me6hjgA/P7l90yBt/9i9Omt5+buGfnklobstECR8zg==, tarball: https://registry.npmjs.org/@wordpress/element/-/element-6.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/element@6.45.0':
@@ -10579,7 +10582,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/element@8.0.1':
- resolution: {integrity: sha512-otYhxfm6ZKkcLCl/tI1rB70z6MVDvTL+RiPOWXi4qm0niJf4isSXCcB91ffj1gzJXKbEpszHfysIoU9L2gCSGQ==}
+ resolution: {integrity: sha512-otYhxfm6ZKkcLCl/tI1rB70z6MVDvTL+RiPOWXi4qm0niJf4isSXCcB91ffj1gzJXKbEpszHfysIoU9L2gCSGQ==, tarball: https://registry.npmjs.org/@wordpress/element/-/element-8.0.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/env@11.9.0':
@@ -10596,7 +10599,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/escape-html@3.48.1':
- resolution: {integrity: sha512-TQJK6sBcmMA5+xMjiAFuivcZ27wUgAfVCgB/fGf7YoxVC+BnCCIanAsHgpY0d4juGUK6LXzDEhU6ZgOpGkGqIQ==}
+ resolution: {integrity: sha512-TQJK6sBcmMA5+xMjiAFuivcZ27wUgAfVCgB/fGf7YoxVC+BnCCIanAsHgpY0d4juGUK6LXzDEhU6ZgOpGkGqIQ==, tarball: https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-3.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/eslint-plugin@14.7.0':
@@ -10658,7 +10661,7 @@ packages:
react: ^18.0.0
'@wordpress/format-library@5.33.9':
- resolution: {integrity: sha512-9RTyCFuaXSSF4Rz4rnz0Elge71nSn7UWyvskMQtZNN5nMGjH9D5NK5JoYKANpt1v0Cx/vfUkLTywBrU0v2+pLA==}
+ resolution: {integrity: sha512-9RTyCFuaXSSF4Rz4rnz0Elge71nSn7UWyvskMQtZNN5nMGjH9D5NK5JoYKANpt1v0Cx/vfUkLTywBrU0v2+pLA==, tarball: https://registry.npmjs.org/@wordpress/format-library/-/format-library-5.33.9.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10673,27 +10676,27 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/hooks@3.58.0':
- resolution: {integrity: sha512-9LB0ZHnZRQlORttux9t/xbAskF+dk2ujqzPGsVzc92mSKpQP3K2a5Wy74fUnInguB1vLUNHT6nrNdkVom5qX1Q==}
+ resolution: {integrity: sha512-9LB0ZHnZRQlORttux9t/xbAskF+dk2ujqzPGsVzc92mSKpQP3K2a5Wy74fUnInguB1vLUNHT6nrNdkVom5qX1Q==, tarball: https://registry.npmjs.org/@wordpress/hooks/-/hooks-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/hooks@4.33.1':
- resolution: {integrity: sha512-p9RbNsZJnsGY45MEV3QfYHS4dMmKe0B1f/RUXEL8ZLa36aUWZrUX7PJxvmmpeuPrboHQwT4MDps9kwHO4V6GVg==}
+ resolution: {integrity: sha512-p9RbNsZJnsGY45MEV3QfYHS4dMmKe0B1f/RUXEL8ZLa36aUWZrUX7PJxvmmpeuPrboHQwT4MDps9kwHO4V6GVg==, tarball: https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/hooks@4.48.1':
- resolution: {integrity: sha512-QZh3Cv9TMJkrCQikuZSsDKTgX+6BBzYJe0MFKp7yP8drj/dtRpkqo5+eYmovBq3pk+HoyP7UJ1vTOb3GPJeU6Q==}
+ resolution: {integrity: sha512-QZh3Cv9TMJkrCQikuZSsDKTgX+6BBzYJe0MFKp7yP8drj/dtRpkqo5+eYmovBq3pk+HoyP7UJ1vTOb3GPJeU6Q==, tarball: https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/html-entities@3.58.0':
- resolution: {integrity: sha512-FU7b6QZdwTCuLKq6wCl0IZqqOMcMRxMcekVVytzTse7hYk9dvL1qQL/U4eQ/CNyKqiT9u7fb5NKTQILOzoolVQ==}
+ resolution: {integrity: sha512-FU7b6QZdwTCuLKq6wCl0IZqqOMcMRxMcekVVytzTse7hYk9dvL1qQL/U4eQ/CNyKqiT9u7fb5NKTQILOzoolVQ==, tarball: https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/html-entities@4.20.0':
- resolution: {integrity: sha512-ZOQ9zsfs5p32K+uAEy2vbY7rnAG5KjMdXwOn4v2FPeXF6A6jWQudK/smV7nRB3ZMaSZnzQ54tiUXbuSpCmmGYA==}
+ resolution: {integrity: sha512-ZOQ9zsfs5p32K+uAEy2vbY7rnAG5KjMdXwOn4v2FPeXF6A6jWQudK/smV7nRB3ZMaSZnzQ54tiUXbuSpCmmGYA==, tarball: https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-4.20.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/html-entities@4.33.1':
- resolution: {integrity: sha512-HdpnRRvTMstX58U4Yr+UisIrFLcG97PGegAczMxeq9Q1n3ol5FCkEegBTQIJffAZ5IadBsPZ77fjoVtLK7RViQ==}
+ resolution: {integrity: sha512-HdpnRRvTMstX58U4Yr+UisIrFLcG97PGegAczMxeq9Q1n3ol5FCkEegBTQIJffAZ5IadBsPZ77fjoVtLK7RViQ==, tarball: https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/html-entities@4.48.1':
@@ -10701,17 +10704,17 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/i18n@4.58.0':
- resolution: {integrity: sha512-VfvS3BWv/RDjRKD6PscIcvYfWKnGJcI/DEqyDgUMhxCM6NRwoL478CsUKTiGJIymeyRodNRfprdcF086DpGKYw==}
+ resolution: {integrity: sha512-VfvS3BWv/RDjRKD6PscIcvYfWKnGJcI/DEqyDgUMhxCM6NRwoL478CsUKTiGJIymeyRodNRfprdcF086DpGKYw==, tarball: https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.58.0.tgz}
engines: {node: '>=12'}
hasBin: true
'@wordpress/i18n@5.26.0':
- resolution: {integrity: sha512-YHzaUWlCuN2ynl47qbsdMkTGtP52+E1giDOdWBgUaSexUYjbeFxKFUzRMB0Wuh1psL80+VzvJOH/mU440KAJnA==}
+ resolution: {integrity: sha512-YHzaUWlCuN2ynl47qbsdMkTGtP52+E1giDOdWBgUaSexUYjbeFxKFUzRMB0Wuh1psL80+VzvJOH/mU440KAJnA==, tarball: https://registry.npmjs.org/@wordpress/i18n/-/i18n-5.26.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
hasBin: true
'@wordpress/i18n@6.18.0':
- resolution: {integrity: sha512-6dYCih4wUwi7Csu4RNfHiAKkgWhpSQdl8YthvQUF59Sfsoia3RCdtd4K2l7W4f18ldFA/RXjShMjvSexWy6OyQ==}
+ resolution: {integrity: sha512-6dYCih4wUwi7Csu4RNfHiAKkgWhpSQdl8YthvQUF59Sfsoia3RCdtd4K2l7W4f18ldFA/RXjShMjvSexWy6OyQ==, tarball: https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.18.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
hasBin: true
@@ -10721,12 +10724,12 @@ packages:
hasBin: true
'@wordpress/i18n@6.6.1':
- resolution: {integrity: sha512-aEFSF+5dp0UhdMGHyNUwhcL0Sg/kp0NtCSMrfcQrXRM6uD/+y8ih0mHeULww5V919NUrzXIZSZGfOaOIiQVXXg==}
+ resolution: {integrity: sha512-aEFSF+5dp0UhdMGHyNUwhcL0Sg/kp0NtCSMrfcQrXRM6uD/+y8ih0mHeULww5V919NUrzXIZSZGfOaOIiQVXXg==, tarball: https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.6.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
hasBin: true
'@wordpress/icons@10.32.0':
- resolution: {integrity: sha512-1WvJdT361X1LnetYBpBWUjAVXZzl+pBdIwHbYRAp8ej47EI/igPmNxmq81nFd40s8fer/9qtipielcqSI6H2rA==}
+ resolution: {integrity: sha512-1WvJdT361X1LnetYBpBWUjAVXZzl+pBdIwHbYRAp8ej47EI/igPmNxmq81nFd40s8fer/9qtipielcqSI6H2rA==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-10.32.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/icons@10.6.0':
@@ -10734,7 +10737,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/icons@11.0.1':
- resolution: {integrity: sha512-vXkWiAxwDjWBcj72oXbJyuDtIvNvk1JnnmYzQUpIjKjvScRPcj+Kt40nFYk/5kPnNAhBqVNcZ7tWK7NctSslJA==}
+ resolution: {integrity: sha512-vXkWiAxwDjWBcj72oXbJyuDtIvNvk1JnnmYzQUpIjKjvScRPcj+Kt40nFYk/5kPnNAhBqVNcZ7tWK7NctSslJA==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-11.0.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/icons@11.8.0':
@@ -10744,35 +10747,35 @@ packages:
react: ^18.0.0
'@wordpress/icons@12.2.0':
- resolution: {integrity: sha512-Fiw7bmfHDNPjTdCrBF23/9K0VN/GUi73d2ZPZaeWdXhTmIX62T9KYvb1c+WnlBkX7GpXgJO6Q8mypQCY9mw5SQ==}
+ resolution: {integrity: sha512-Fiw7bmfHDNPjTdCrBF23/9K0VN/GUi73d2ZPZaeWdXhTmIX62T9KYvb1c+WnlBkX7GpXgJO6Q8mypQCY9mw5SQ==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-12.2.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/icons@13.0.0':
- resolution: {integrity: sha512-+CLbvNdzMUHxQK5I6gFdHb3X6EVAH6SOSIj0xtMWm6PZO+Nnf7tXHfNBuxqTnGfxT5grtfb6D3A9ZMBU+Tpv+Q==}
+ resolution: {integrity: sha512-+CLbvNdzMUHxQK5I6gFdHb3X6EVAH6SOSIj0xtMWm6PZO+Nnf7tXHfNBuxqTnGfxT5grtfb6D3A9ZMBU+Tpv+Q==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-13.0.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/icons@13.3.0':
- resolution: {integrity: sha512-Y/iE3aeHQ4XkX0fffiTPCUfjT8wNw1I7hDJkKqpaLmkD+C5NKWixRrDVfRnaJqU/MxY8RdyVC/nGng2MLPNH0A==}
+ resolution: {integrity: sha512-Y/iE3aeHQ4XkX0fffiTPCUfjT8wNw1I7hDJkKqpaLmkD+C5NKWixRrDVfRnaJqU/MxY8RdyVC/nGng2MLPNH0A==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-13.3.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/icons@14.0.1':
- resolution: {integrity: sha512-Vf3wXrS8JWwozKGQ3vS8WQBwmzZyk0ih3W92kE+xPDK2K5QPrlW4MjbSV8gYbNAHC6NECPSWrEGI3DmbgvAP3w==}
+ resolution: {integrity: sha512-Vf3wXrS8JWwozKGQ3vS8WQBwmzZyk0ih3W92kE+xPDK2K5QPrlW4MjbSV8gYbNAHC6NECPSWrEGI3DmbgvAP3w==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-14.0.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/icons@4.1.0':
- resolution: {integrity: sha512-1FpEjT9kJbr0cWbgdgIwd2DoeerWijcVx3qCZ/WMFKNElBH9lfZLuWPI1hpX102HGWFcEi3VlbVpdBGeCeYQWg==}
+ resolution: {integrity: sha512-1FpEjT9kJbr0cWbgdgIwd2DoeerWijcVx3qCZ/WMFKNElBH9lfZLuWPI1hpX102HGWFcEi3VlbVpdBGeCeYQWg==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-4.1.0.tgz}
engines: {node: '>=12'}
'@wordpress/icons@9.49.0':
- resolution: {integrity: sha512-Z8F+ledkfkcKDuS1c/RkM0dEWdfv2AXs6bCgey89p0atJSscf7qYbMJR9zE5rZ5aqXyFfV0DAFKJEgayNqneNQ==}
+ resolution: {integrity: sha512-Z8F+ledkfkcKDuS1c/RkM0dEWdfv2AXs6bCgey89p0atJSscf7qYbMJR9zE5rZ5aqXyFfV0DAFKJEgayNqneNQ==, tarball: https://registry.npmjs.org/@wordpress/icons/-/icons-9.49.0.tgz}
engines: {node: '>=12'}
'@wordpress/image-cropper@1.12.1':
@@ -10783,38 +10786,38 @@ packages:
react-dom: ^18.0.0
'@wordpress/interactivity-router@1.8.0':
- resolution: {integrity: sha512-i2Lb9008DmPyh/DyCWhvVkwUha2zhLqPfBtMAUQuwes2prDLyl8FnWVS6bwXXYpu6qKkLhFz6hzXt3O988u53Q==}
+ resolution: {integrity: sha512-i2Lb9008DmPyh/DyCWhvVkwUha2zhLqPfBtMAUQuwes2prDLyl8FnWVS6bwXXYpu6qKkLhFz6hzXt3O988u53Q==, tarball: https://registry.npmjs.org/@wordpress/interactivity-router/-/interactivity-router-1.8.0.tgz}
engines: {node: '>=12'}
'@wordpress/interactivity-router@2.33.3':
- resolution: {integrity: sha512-sQBbpSnzOsYFaEoF+SLsKFHb+5grgmdhfMrLlJEIP/HK063W053ipfWsj1IUmv2dz/mNVgB0+EoY7oBbws1axA==}
+ resolution: {integrity: sha512-sQBbpSnzOsYFaEoF+SLsKFHb+5grgmdhfMrLlJEIP/HK063W053ipfWsj1IUmv2dz/mNVgB0+EoY7oBbws1axA==, tarball: https://registry.npmjs.org/@wordpress/interactivity-router/-/interactivity-router-2.33.3.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/interactivity-router@2.44.0':
- resolution: {integrity: sha512-lpq1y1dPzgh5FjxAhsEYp9QcBED+eWOwUyQCKio+WE0dGBRnFf5Sghr2d+e99TDvhrQvB11Zal7pNCnPps9iWw==}
+ resolution: {integrity: sha512-lpq1y1dPzgh5FjxAhsEYp9QcBED+eWOwUyQCKio+WE0dGBRnFf5Sghr2d+e99TDvhrQvB11Zal7pNCnPps9iWw==, tarball: https://registry.npmjs.org/@wordpress/interactivity-router/-/interactivity-router-2.44.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/interactivity@5.7.0':
- resolution: {integrity: sha512-zB2CZwj4TWpE5OJtFfpma1OYvrsLTMgWpRJ2ojRuNqBruZfQAUqOXsn6JyTTWs6bgyd4dr/WOZay4Wr4isleUw==}
+ resolution: {integrity: sha512-zB2CZwj4TWpE5OJtFfpma1OYvrsLTMgWpRJ2ojRuNqBruZfQAUqOXsn6JyTTWs6bgyd4dr/WOZay4Wr4isleUw==, tarball: https://registry.npmjs.org/@wordpress/interactivity/-/interactivity-5.7.0.tgz}
engines: {node: '>=12'}
'@wordpress/interactivity@6.33.3':
- resolution: {integrity: sha512-IOklCB4RiIK8os1XvJojTb+7d8gN3kTi9MxDZDe/M+yzbOvzK2zDZAtg4KHpRJdADfZmHvZgY8lLFXPsiX+F8A==}
+ resolution: {integrity: sha512-IOklCB4RiIK8os1XvJojTb+7d8gN3kTi9MxDZDe/M+yzbOvzK2zDZAtg4KHpRJdADfZmHvZgY8lLFXPsiX+F8A==, tarball: https://registry.npmjs.org/@wordpress/interactivity/-/interactivity-6.33.3.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/interactivity@6.48.1':
- resolution: {integrity: sha512-Qc+VoBt2XNoOuVMZwjQtZJ8iQfh7mJsSjPlxzSMyYRHGPa+WqfWO50LY/vyXYPs5s5FoMsb3S64ty/p//1DI2w==}
+ resolution: {integrity: sha512-Qc+VoBt2XNoOuVMZwjQtZJ8iQfh7mJsSjPlxzSMyYRHGPa+WqfWO50LY/vyXYPs5s5FoMsb3S64ty/p//1DI2w==, tarball: https://registry.npmjs.org/@wordpress/interactivity/-/interactivity-6.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/interface@5.35.0':
- resolution: {integrity: sha512-ClRQQVZQ6dpMwlcFLigdtqLdc8rXRwW4c2MUQTHctnU4Y9Lean+PV4ZhX/QN32gS/vhseCDzO0hg+gjQY6cdjQ==}
+ resolution: {integrity: sha512-ClRQQVZQ6dpMwlcFLigdtqLdc8rXRwW4c2MUQTHctnU4Y9Lean+PV4ZhX/QN32gS/vhseCDzO0hg+gjQY6cdjQ==, tarball: https://registry.npmjs.org/@wordpress/interface/-/interface-5.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/interface@9.18.5':
- resolution: {integrity: sha512-OCNCTogPS/kHPVjIAHtQ2y9WaX1fm1oK1cXQs6RezKtO1y/+nFH2L5pjzF7ifG1ECe5KL7REX4kJXgDTIwDV9g==}
+ resolution: {integrity: sha512-OCNCTogPS/kHPVjIAHtQ2y9WaX1fm1oK1cXQs6RezKtO1y/+nFH2L5pjzF7ifG1ECe5KL7REX4kJXgDTIwDV9g==, tarball: https://registry.npmjs.org/@wordpress/interface/-/interface-9.18.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10828,11 +10831,11 @@ packages:
react-dom: ^18.0.0
'@wordpress/is-shallow-equal@4.58.0':
- resolution: {integrity: sha512-NH2lbXo/6ix1t4Zu9UBXpXNtoLwSaYmIRSyDH34XNb0ic8a7yjEOhYWVW3LTfSCv9dJVyxlM5TJPtL85q7LdeQ==}
+ resolution: {integrity: sha512-NH2lbXo/6ix1t4Zu9UBXpXNtoLwSaYmIRSyDH34XNb0ic8a7yjEOhYWVW3LTfSCv9dJVyxlM5TJPtL85q7LdeQ==, tarball: https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-4.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/is-shallow-equal@5.33.1':
- resolution: {integrity: sha512-QMOwATwFjFr6Z9geS8EjuEVGN0gkpANypjqIBE8iTDtfKhY99LTtxbTaguviqKfVP7l73v1B0GJfHtkPExhJkA==}
+ resolution: {integrity: sha512-QMOwATwFjFr6Z9geS8EjuEVGN0gkpANypjqIBE8iTDtfKhY99LTtxbTaguviqKfVP7l73v1B0GJfHtkPExhJkA==, tarball: https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-5.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/is-shallow-equal@5.48.1':
@@ -10904,7 +10907,7 @@ packages:
react: ^18.0.0
'@wordpress/keyboard-shortcuts@5.33.1':
- resolution: {integrity: sha512-ql+qQ+AW9rnaS6jBv3J5MT8ku0qijAYCq6rIvfEiA1W84i5+LB9JYxxzrFH8v5uGU4ZjqqRQEmcDd+lorlT4Vg==}
+ resolution: {integrity: sha512-ql+qQ+AW9rnaS6jBv3J5MT8ku0qijAYCq6rIvfEiA1W84i5+LB9JYxxzrFH8v5uGU4ZjqqRQEmcDd+lorlT4Vg==, tarball: https://registry.npmjs.org/@wordpress/keyboard-shortcuts/-/keyboard-shortcuts-5.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10916,15 +10919,15 @@ packages:
react: ^18.0.0
'@wordpress/keycodes@3.58.0':
- resolution: {integrity: sha512-Q/LRKpx8ndzuHlkxSQ2BD+NTYYKQPIneNNMng8hTAfyU7RFwXpqj06HpeOFGh4XIdPKCs/8hmucoLJRmmLmZJA==}
+ resolution: {integrity: sha512-Q/LRKpx8ndzuHlkxSQ2BD+NTYYKQPIneNNMng8hTAfyU7RFwXpqj06HpeOFGh4XIdPKCs/8hmucoLJRmmLmZJA==, tarball: https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/keycodes@4.33.1':
- resolution: {integrity: sha512-acuH0ogiY92ClslUpezZyEzfm1Ubx2bftevn/PxbsVq52UCOu14CAKgnO9sYqVuMpXT+zXveRMySixyKHB1wnA==}
+ resolution: {integrity: sha512-acuH0ogiY92ClslUpezZyEzfm1Ubx2bftevn/PxbsVq52UCOu14CAKgnO9sYqVuMpXT+zXveRMySixyKHB1wnA==, tarball: https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/keycodes@4.45.0':
- resolution: {integrity: sha512-N+Wp572xZovLM45cYo6HfUNTQNDfEqakAYIOcY8bUqA2iFelN6AUkNfUIkIxmrE0EqkQAQ5odES03g8ym7e1IA==}
+ resolution: {integrity: sha512-N+Wp572xZovLM45cYo6HfUNTQNDfEqakAYIOcY8bUqA2iFelN6AUkNfUIkIxmrE0EqkQAQ5odES03g8ym7e1IA==, tarball: https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-4.45.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/keycodes@4.48.1':
@@ -10932,7 +10935,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/latex-to-mathml@1.16.0':
- resolution: {integrity: sha512-WEXC9GKgMLXXqbezKZWw9cwozS4/dM23VDresod1nqfvgMSpvtgHsFP98wJWg2iQyA6SIksSuD/SROSaBCZ17A==}
+ resolution: {integrity: sha512-WEXC9GKgMLXXqbezKZWw9cwozS4/dM23VDresod1nqfvgMSpvtgHsFP98wJWg2iQyA6SIksSuD/SROSaBCZ17A==, tarball: https://registry.npmjs.org/@wordpress/latex-to-mathml/-/latex-to-mathml-1.16.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/media-fields@0.9.0':
@@ -10942,11 +10945,11 @@ packages:
react: ^18.0.0
'@wordpress/media-utils@4.49.0':
- resolution: {integrity: sha512-6xfkK3ehy2siAvQXnF9ZiEiPJHmQr6tOlwnFML7dSrnNzOyWxprTxvsdXMP51O2r/kLozdc/gr60fnQAMs70vw==}
+ resolution: {integrity: sha512-6xfkK3ehy2siAvQXnF9ZiEiPJHmQr6tOlwnFML7dSrnNzOyWxprTxvsdXMP51O2r/kLozdc/gr60fnQAMs70vw==, tarball: https://registry.npmjs.org/@wordpress/media-utils/-/media-utils-4.49.0.tgz}
engines: {node: '>=12'}
'@wordpress/media-utils@5.33.1':
- resolution: {integrity: sha512-Ty4gPDoKesy3nTu6b2nU2bee1Vqk90Cf1MHsoalo+6lw/UDlvX+RsogUzTVwUH9n2jG4rYQFPZY1KI/1pxj1rg==}
+ resolution: {integrity: sha512-Ty4gPDoKesy3nTu6b2nU2bee1Vqk90Cf1MHsoalo+6lw/UDlvX+RsogUzTVwUH9n2jG4rYQFPZY1KI/1pxj1rg==, tarball: https://registry.npmjs.org/@wordpress/media-utils/-/media-utils-5.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/media-utils@5.44.0':
@@ -10956,7 +10959,7 @@ packages:
react: ^18.0.0
'@wordpress/notices@4.26.0':
- resolution: {integrity: sha512-Lu98xQdtZHgC3d32IFalZbOiIu8aRFWlEQXXfRutD7EhXXp6FIXvnvc054700/Dk1mg9P/bWd0zm/cigkXgfkA==}
+ resolution: {integrity: sha512-Lu98xQdtZHgC3d32IFalZbOiIu8aRFWlEQXXfRutD7EhXXp6FIXvnvc054700/Dk1mg9P/bWd0zm/cigkXgfkA==, tarball: https://registry.npmjs.org/@wordpress/notices/-/notices-4.26.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -10968,7 +10971,7 @@ packages:
react: ^18.0.0
'@wordpress/notices@5.48.1':
- resolution: {integrity: sha512-igkUhvyvp+C61HcE7OBiCPkPYMae8k0BQBZblepXghkX82zlqVe5NiueepWTwY7pFDDEsZlxl9sYF2DWf6HF3w==}
+ resolution: {integrity: sha512-igkUhvyvp+C61HcE7OBiCPkPYMae8k0BQBZblepXghkX82zlqVe5NiueepWTwY7pFDDEsZlxl9sYF2DWf6HF3w==, tarball: https://registry.npmjs.org/@wordpress/notices/-/notices-5.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -10986,14 +10989,14 @@ packages:
npm-package-json-lint: '>=6.0.0'
'@wordpress/patterns@1.19.0':
- resolution: {integrity: sha512-L0NhNn6P2YuZRgZNlZP0IFYKoVjQI5Vf/4edgG8yjYwuXLkanJvBZWglswu4Z8jzlsBN72o0n3K37FO8VzcnmA==}
+ resolution: {integrity: sha512-L0NhNn6P2YuZRgZNlZP0IFYKoVjQI5Vf/4edgG8yjYwuXLkanJvBZWglswu4Z8jzlsBN72o0n3K37FO8VzcnmA==, tarball: https://registry.npmjs.org/@wordpress/patterns/-/patterns-1.19.0.tgz}
engines: {node: '>=16.0.0'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/patterns@2.33.9':
- resolution: {integrity: sha512-CqSMtixhEA0pT/WQUmlfF6zovPCqw/+qnom5nvezipdtTMZNmehFnGwoSmyegADH56zIzkGJRnjWT6WoPLfeOg==}
+ resolution: {integrity: sha512-CqSMtixhEA0pT/WQUmlfF6zovPCqw/+qnom5nvezipdtTMZNmehFnGwoSmyegADH56zIzkGJRnjWT6WoPLfeOg==, tarball: https://registry.npmjs.org/@wordpress/patterns/-/patterns-2.33.9.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11007,14 +11010,14 @@ packages:
react-dom: ^18.0.0
'@wordpress/plugins@6.26.0':
- resolution: {integrity: sha512-GsV9mSlHF+Tn3BHCLR+nM+7FmyWDOcxHHSBwHUVNbghrmLM4Hy/Jvs8vcirTZivGEbQSB6EBJO7QIFRrXk0PpQ==}
+ resolution: {integrity: sha512-GsV9mSlHF+Tn3BHCLR+nM+7FmyWDOcxHHSBwHUVNbghrmLM4Hy/Jvs8vcirTZivGEbQSB6EBJO7QIFRrXk0PpQ==, tarball: https://registry.npmjs.org/@wordpress/plugins/-/plugins-6.26.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/plugins@7.33.5':
- resolution: {integrity: sha512-kTNhyX1FKTSWBmxfHWoqEo5+iM96ThHXGqFGzeAFt+W35EeHzt9a/H++9yfcxMqDyjR1IRjoB261bX+oLPuw9Q==}
+ resolution: {integrity: sha512-kTNhyX1FKTSWBmxfHWoqEo5+iM96ThHXGqFGzeAFt+W35EeHzt9a/H++9yfcxMqDyjR1IRjoB261bX+oLPuw9Q==, tarball: https://registry.npmjs.org/@wordpress/plugins/-/plugins-7.33.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11028,19 +11031,19 @@ packages:
react-dom: ^18.0.0
'@wordpress/postcss-plugins-preset@3.10.0':
- resolution: {integrity: sha512-vBXy+8e6BpUvmxcIFgldvFlTFA6kAlC+J86GcDEoIq/IFVoqSJlnX1s1QHXgG3CzTHjIlN/FNJxGxYinSMJhng==}
+ resolution: {integrity: sha512-vBXy+8e6BpUvmxcIFgldvFlTFA6kAlC+J86GcDEoIq/IFVoqSJlnX1s1QHXgG3CzTHjIlN/FNJxGxYinSMJhng==, tarball: https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-3.10.0.tgz}
engines: {node: '>=12'}
peerDependencies:
postcss: ^8.0.0
'@wordpress/postcss-plugins-preset@4.42.0':
- resolution: {integrity: sha512-5xmKF7IUsqS5JcmJlHKHq7RaR6ZpaLj3n9c+X0X0/Oo7ZCIGp6WeDQngx13sH4NJoKXrZ9g4n1rbzhEKeo/Wtg==}
+ resolution: {integrity: sha512-5xmKF7IUsqS5JcmJlHKHq7RaR6ZpaLj3n9c+X0X0/Oo7ZCIGp6WeDQngx13sH4NJoKXrZ9g4n1rbzhEKeo/Wtg==, tarball: https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-4.42.0.tgz}
engines: {node: '>=14'}
peerDependencies:
postcss: ^8.0.0
'@wordpress/postcss-plugins-preset@5.33.1':
- resolution: {integrity: sha512-mlxJflCUP3An6UXCQY137HajhQTKxPn+lL+p2PgeAtv6PVhwc8Gmv1RJP2QiGIPxrmI/KzrmHubSMjK1LYA12A==}
+ resolution: {integrity: sha512-mlxJflCUP3An6UXCQY137HajhQTKxPn+lL+p2PgeAtv6PVhwc8Gmv1RJP2QiGIPxrmI/KzrmHubSMjK1LYA12A==, tarball: https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-5.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
postcss: ^8.0.0
@@ -11052,7 +11055,7 @@ packages:
postcss: ^8.0.0
'@wordpress/postcss-plugins-preset@5.44.0':
- resolution: {integrity: sha512-D3GGSSmPKHUywK+pIHXsfnX6MXsjMb6rfQ33hX2hfOLZUR5VVt/DFJE3teinnyveQKOKeFcytiMr1pP2gH12RA==}
+ resolution: {integrity: sha512-D3GGSSmPKHUywK+pIHXsfnX6MXsjMb6rfQ33hX2hfOLZUR5VVt/DFJE3teinnyveQKOKeFcytiMr1pP2gH12RA==, tarball: https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-5.44.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
postcss: ^8.0.0
@@ -11071,7 +11074,7 @@ packages:
react-dom: ^18.0.0
'@wordpress/preferences@4.33.5':
- resolution: {integrity: sha512-5tPfWv5Kw/+KAfFzsZKojK3FHNDiMVwj8GusXAqbsCSy9YsyAxifaEXeul684RYFdizLK3gWqe4S0K6GaLs0CA==}
+ resolution: {integrity: sha512-5tPfWv5Kw/+KAfFzsZKojK3FHNDiMVwj8GusXAqbsCSy9YsyAxifaEXeul684RYFdizLK3gWqe4S0K6GaLs0CA==, tarball: https://registry.npmjs.org/@wordpress/preferences/-/preferences-4.33.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11109,37 +11112,37 @@ packages:
prettier: '>=3'
'@wordpress/primitives@2.2.0':
- resolution: {integrity: sha512-WupgR+tt6fKGZE1UKy2gz3wDdpRL9MWQbVuetXv/7TPAz2ofOS2fZIsXNrl4D0HkA82gYh8w8s2TXK0XNyAAow==}
+ resolution: {integrity: sha512-WupgR+tt6fKGZE1UKy2gz3wDdpRL9MWQbVuetXv/7TPAz2ofOS2fZIsXNrl4D0HkA82gYh8w8s2TXK0XNyAAow==, tarball: https://registry.npmjs.org/@wordpress/primitives/-/primitives-2.2.0.tgz}
engines: {node: '>=12'}
'@wordpress/primitives@3.56.0':
- resolution: {integrity: sha512-NXBq1ODjl6inMWx/l7KCbATcjdoeIOqYeL9i9alqdAfWeKx1EH9PIvKWylIkqZk7erXxCxldiRkuyjTtwjNBxw==}
+ resolution: {integrity: sha512-NXBq1ODjl6inMWx/l7KCbATcjdoeIOqYeL9i9alqdAfWeKx1EH9PIvKWylIkqZk7erXxCxldiRkuyjTtwjNBxw==, tarball: https://registry.npmjs.org/@wordpress/primitives/-/primitives-3.56.0.tgz}
engines: {node: '>=12'}
'@wordpress/primitives@4.33.1':
- resolution: {integrity: sha512-CVdk+tyyGVB4ube6O/uS9BgdDly2imImqE6SM/Aa5N4O6BI6mIgLhLQoKqj7WBKIdI0qTMndyGHfqqoUWBD5wA==}
+ resolution: {integrity: sha512-CVdk+tyyGVB4ube6O/uS9BgdDly2imImqE6SM/Aa5N4O6BI6mIgLhLQoKqj7WBKIdI0qTMndyGHfqqoUWBD5wA==, tarball: https://registry.npmjs.org/@wordpress/primitives/-/primitives-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/primitives@4.45.0':
- resolution: {integrity: sha512-x+i6EKUvz96EkUb2KuBTLNGm8d5+ZS0FYjUEnIhp5dtWxjMe8dJT6LS+n363vg+K28LVvjptiTAaByccnNKc9w==}
+ resolution: {integrity: sha512-x+i6EKUvz96EkUb2KuBTLNGm8d5+ZS0FYjUEnIhp5dtWxjMe8dJT6LS+n363vg+K28LVvjptiTAaByccnNKc9w==, tarball: https://registry.npmjs.org/@wordpress/primitives/-/primitives-4.45.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/primitives@4.48.1':
- resolution: {integrity: sha512-nzAcsXhBxw9x2q/ImVa45Ft80TO+e/WgCDmWaU3Zb2trogwThxZTezkE0oeQ6PSxSeGYM6nBgk+qqFCG8wyMhQ==}
+ resolution: {integrity: sha512-nzAcsXhBxw9x2q/ImVa45Ft80TO+e/WgCDmWaU3Zb2trogwThxZTezkE0oeQ6PSxSeGYM6nBgk+qqFCG8wyMhQ==, tarball: https://registry.npmjs.org/@wordpress/primitives/-/primitives-4.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/priority-queue@2.58.0':
- resolution: {integrity: sha512-W+qCS8HJWsXG8gE6yK/H/IObowcghPrQMM3cQHtfd/U05yFNU1Bd/fbj3AO1fVRztktS47lIpi9m3ll1evPEHA==}
+ resolution: {integrity: sha512-W+qCS8HJWsXG8gE6yK/H/IObowcghPrQMM3cQHtfd/U05yFNU1Bd/fbj3AO1fVRztktS47lIpi9m3ll1evPEHA==, tarball: https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-2.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/priority-queue@3.33.1':
- resolution: {integrity: sha512-m3S+bfVIGmDHVrCzTdQu5oHP6aBIM0pf5AYVpfdA2addJHLICtAMrPYdD+4MXekh8a38DzPekZa03vGv3ws3zQ==}
+ resolution: {integrity: sha512-m3S+bfVIGmDHVrCzTdQu5oHP6aBIM0pf5AYVpfdA2addJHLICtAMrPYdD+4MXekh8a38DzPekZa03vGv3ws3zQ==, tarball: https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-3.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/priority-queue@3.48.1':
@@ -11159,7 +11162,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/redux-routine@4.58.0':
- resolution: {integrity: sha512-r0mMWFeJr93yPy2uY/M5+gdUUYj0Zu8+21OFFb5hyQ0z7UHIa3IdgQxzCaTbV1LDA1ZYJrjHeCnA6s4gNHjA2Q==}
+ resolution: {integrity: sha512-r0mMWFeJr93yPy2uY/M5+gdUUYj0Zu8+21OFFb5hyQ0z7UHIa3IdgQxzCaTbV1LDA1ZYJrjHeCnA6s4gNHjA2Q==, tarball: https://registry.npmjs.org/@wordpress/redux-routine/-/redux-routine-4.58.0.tgz}
engines: {node: '>=12'}
peerDependencies:
redux: '>=4'
@@ -11185,17 +11188,17 @@ packages:
react-dom: ^18.0.0
'@wordpress/rich-text@4.2.0':
- resolution: {integrity: sha512-e+wfrkKtZIcFZJZLxkrikiXbxlr6nuGg+V94uKMLrzJEWdw7w/8l3dNhWHRGPkldXIEGrF/mV40ibjUa2p3Sfg==}
+ resolution: {integrity: sha512-e+wfrkKtZIcFZJZLxkrikiXbxlr6nuGg+V94uKMLrzJEWdw7w/8l3dNhWHRGPkldXIEGrF/mV40ibjUa2p3Sfg==, tarball: https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-4.2.0.tgz}
engines: {node: '>=12'}
'@wordpress/rich-text@6.35.0':
- resolution: {integrity: sha512-h6/XftSqo9UQZebuNZyLfOVu+ButBLITW/BILsKeJhSpmM19VNdz8UhVGLp+xQPE+/GPCIMJrhhqipISDfc2Ig==}
+ resolution: {integrity: sha512-h6/XftSqo9UQZebuNZyLfOVu+ButBLITW/BILsKeJhSpmM19VNdz8UhVGLp+xQPE+/GPCIMJrhhqipISDfc2Ig==, tarball: https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-6.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
'@wordpress/rich-text@7.33.2':
- resolution: {integrity: sha512-jy8DPBN6f0WeQM1jL+yGX29xHgzDdyrGoXYEGrGt2ngpGYMca2ZrG9ZLcpQlU6S3sLV/n1jtjZntWrFFYRzgQA==}
+ resolution: {integrity: sha512-jy8DPBN6f0WeQM1jL+yGX29xHgzDdyrGoXYEGrGt2ngpGYMca2ZrG9ZLcpQlU6S3sLV/n1jtjZntWrFFYRzgQA==, tarball: https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-7.33.2.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11282,7 +11285,7 @@ packages:
react-dom: ^18.0.0
'@wordpress/server-side-render@4.35.0':
- resolution: {integrity: sha512-yTbq31iGFc9VaRMtdCLlyZtbwCN+WdiECEqY6MsMXf31/TDmUcdZPxRTORy3Rz2HxEpFfUMjpRz7A8wn1QZmzA==}
+ resolution: {integrity: sha512-yTbq31iGFc9VaRMtdCLlyZtbwCN+WdiECEqY6MsMXf31/TDmUcdZPxRTORy3Rz2HxEpFfUMjpRz7A8wn1QZmzA==, tarball: https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-4.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
@@ -11296,14 +11299,14 @@ packages:
react-dom: ^18.0.0
'@wordpress/server-side-render@6.9.5':
- resolution: {integrity: sha512-/69swIXXWg4+bvd6nL6N9xLy6JE2YgtduyVSjaBE4Z1Ri0VKXLK3c3j6PBp39QlhgSUpN2TJnLb22R4GMOw52w==}
+ resolution: {integrity: sha512-/69swIXXWg4+bvd6nL6N9xLy6JE2YgtduyVSjaBE4Z1Ri0VKXLK3c3j6PBp39QlhgSUpN2TJnLb22R4GMOw52w==, tarball: https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-6.9.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/shortcode@3.58.0':
- resolution: {integrity: sha512-yM3Y25XqLfz/X6xXowXbrTvk+tslKeALNNESI5nGt1X7wWPsYQDOqyBb1HT9TglSLFgWYlQlNtgEbz07dEiDgQ==}
+ resolution: {integrity: sha512-yM3Y25XqLfz/X6xXowXbrTvk+tslKeALNNESI5nGt1X7wWPsYQDOqyBb1HT9TglSLFgWYlQlNtgEbz07dEiDgQ==, tarball: https://registry.npmjs.org/@wordpress/shortcode/-/shortcode-3.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/shortcode@4.48.1':
@@ -11323,7 +11326,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/style-runtime@0.4.1':
- resolution: {integrity: sha512-guZ0p9a5ZQyyCFPwVqDkhDNVXdXAhIqNkPGSNIGguEtt3OtSOskEMwYJHyXZYX8nlbH0FyKflGJhE4G6QlIWlw==}
+ resolution: {integrity: sha512-guZ0p9a5ZQyyCFPwVqDkhDNVXdXAhIqNkPGSNIGguEtt3OtSOskEMwYJHyXZYX8nlbH0FyKflGJhE4G6QlIWlw==, tarball: https://registry.npmjs.org/@wordpress/style-runtime/-/style-runtime-0.4.1.tgz}
engines: {node: '>=20.10.0', npm: '>=10.2.3'}
'@wordpress/stylelint-config@19.1.0':
@@ -11376,7 +11379,7 @@ packages:
optional: true
'@wordpress/theme@0.15.1':
- resolution: {integrity: sha512-0SqH40Sd4pKH8YkDjQ4JM2NJzdhliO19QTPHAOAGA+tXuh+YwHOwFxX8Mg0v/vvI4XJD11zuiKGr+grBI7icTQ==}
+ resolution: {integrity: sha512-0SqH40Sd4pKH8YkDjQ4JM2NJzdhliO19QTPHAOAGA+tXuh+YwHOwFxX8Mg0v/vvI4XJD11zuiKGr+grBI7icTQ==, tarball: https://registry.npmjs.org/@wordpress/theme/-/theme-0.15.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11395,28 +11398,28 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/ui@0.11.0':
- resolution: {integrity: sha512-V1R3CTQ8MltuajZ53PCHGe9mmRwyx1RpjHA2wWOv+79dV0qQ1Y/psL0YTMY4eteL4SNAlBcjJVP66zD5O6yF8Q==}
+ resolution: {integrity: sha512-V1R3CTQ8MltuajZ53PCHGe9mmRwyx1RpjHA2wWOv+79dV0qQ1Y/psL0YTMY4eteL4SNAlBcjJVP66zD5O6yF8Q==, tarball: https://registry.npmjs.org/@wordpress/ui/-/ui-0.11.0.tgz}
engines: {node: '>=20.10.0', npm: '>=10.2.3'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/ui@0.12.0':
- resolution: {integrity: sha512-n/xfyagM90CcikLtlvNcjsFZtpt1wTpboOZPyCp9wqF6akAyJ4SUg9hXb/UA7pC8JqGe1Dg/hXJnFn/td8pvRA==}
+ resolution: {integrity: sha512-n/xfyagM90CcikLtlvNcjsFZtpt1wTpboOZPyCp9wqF6akAyJ4SUg9hXb/UA7pC8JqGe1Dg/hXJnFn/td8pvRA==, tarball: https://registry.npmjs.org/@wordpress/ui/-/ui-0.12.0.tgz}
engines: {node: '>=20.10.0', npm: '>=10.2.3'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/ui@0.15.1':
- resolution: {integrity: sha512-zFErzf84zc7dGXrCa9fPKUpMhYx86B8n5GeshC7Ut/nfE7yp09g/Bono5S7KhY1OJx7Z1Jur9t+4vnv5cocBbA==}
+ resolution: {integrity: sha512-zFErzf84zc7dGXrCa9fPKUpMhYx86B8n5GeshC7Ut/nfE7yp09g/Bono5S7KhY1OJx7Z1Jur9t+4vnv5cocBbA==, tarball: https://registry.npmjs.org/@wordpress/ui/-/ui-0.15.1.tgz}
engines: {node: '>=20.10.0', npm: '>=10.2.3'}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
'@wordpress/undo-manager@0.18.0':
- resolution: {integrity: sha512-upbzPEToa095XG+2JXLHaolF1LfXEMFS0lNMYV37myoUS+eZ7/tl9Gx+yU2+OqWy57TMwx33NlWUX/n+ynzPRw==}
+ resolution: {integrity: sha512-upbzPEToa095XG+2JXLHaolF1LfXEMFS0lNMYV37myoUS+eZ7/tl9Gx+yU2+OqWy57TMwx33NlWUX/n+ynzPRw==, tarball: https://registry.npmjs.org/@wordpress/undo-manager/-/undo-manager-0.18.0.tgz}
engines: {node: '>=12'}
'@wordpress/undo-manager@1.48.1':
@@ -11424,7 +11427,7 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/upload-media@0.18.5':
- resolution: {integrity: sha512-4u+mMPicEuw7tMPIgCtgI5BWckWODjYayA7aOP0sQWdG90Vq1z7nGDlxHeeb/PkQxnZPh+3oA6V79OWV5ZS/Fg==}
+ resolution: {integrity: sha512-4u+mMPicEuw7tMPIgCtgI5BWckWODjYayA7aOP0sQWdG90Vq1z7nGDlxHeeb/PkQxnZPh+3oA6V79OWV5ZS/Fg==, tarball: https://registry.npmjs.org/@wordpress/upload-media/-/upload-media-0.18.5.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11438,11 +11441,11 @@ packages:
react-dom: ^18.0.0
'@wordpress/url@3.59.0':
- resolution: {integrity: sha512-GxvoMjYCav0w4CiX0i0h3qflrE/9rhLIZg5aPCQjbrBdwTxYR3Exfw0IJYcmVaTKXQOUU8fOxlDxULsbLmKe9w==}
+ resolution: {integrity: sha512-GxvoMjYCav0w4CiX0i0h3qflrE/9rhLIZg5aPCQjbrBdwTxYR3Exfw0IJYcmVaTKXQOUU8fOxlDxULsbLmKe9w==, tarball: https://registry.npmjs.org/@wordpress/url/-/url-3.59.0.tgz}
engines: {node: '>=12'}
'@wordpress/url@4.33.1':
- resolution: {integrity: sha512-t4MKPofYLHTIVE+NV36WBmlnzHsnZFkXsACdu/InF0u5pmyc/ZgXmq44qi6h/PmbGoUKnRQisulMIvGfEVBTeA==}
+ resolution: {integrity: sha512-t4MKPofYLHTIVE+NV36WBmlnzHsnZFkXsACdu/InF0u5pmyc/ZgXmq44qi6h/PmbGoUKnRQisulMIvGfEVBTeA==, tarball: https://registry.npmjs.org/@wordpress/url/-/url-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/url@4.48.1':
@@ -11450,19 +11453,19 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/viewport@5.35.0':
- resolution: {integrity: sha512-iCIVbFcA1CzGXEVu5COoi6DRdh3m3zEMWOYKKqF1C7W/LhZnTNRsHOZbHq0tv7MOkwx0Nl7+hDJlPRM0B3fb7A==}
+ resolution: {integrity: sha512-iCIVbFcA1CzGXEVu5COoi6DRdh3m3zEMWOYKKqF1C7W/LhZnTNRsHOZbHq0tv7MOkwx0Nl7+hDJlPRM0B3fb7A==, tarball: https://registry.npmjs.org/@wordpress/viewport/-/viewport-5.35.0.tgz}
engines: {node: '>=12'}
peerDependencies:
react: ^18.0.0
'@wordpress/viewport@6.33.1':
- resolution: {integrity: sha512-UmXx/UhJZqRYYCj+ZbG2XpObUa/UP2ydxC7hAVj3uc/xYrB8M3OOcYnQ+WQejAoyNs4sTe6VpzDZRn/rdcExMw==}
+ resolution: {integrity: sha512-UmXx/UhJZqRYYCj+ZbG2XpObUa/UP2ydxC7hAVj3uc/xYrB8M3OOcYnQ+WQejAoyNs4sTe6VpzDZRn/rdcExMw==, tarball: https://registry.npmjs.org/@wordpress/viewport/-/viewport-6.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
'@wordpress/viewport@6.48.1':
- resolution: {integrity: sha512-W/bpuh4ndoNUdH2Cfuq2N+vBWU5mSyPdG5bQOaHeK31c2YQfti/3sQTbGZ9h+wHCoUGfI1az87kimPMbqr9GqQ==}
+ resolution: {integrity: sha512-W/bpuh4ndoNUdH2Cfuq2N+vBWU5mSyPdG5bQOaHeK31c2YQfti/3sQTbGZ9h+wHCoUGfI1az87kimPMbqr9GqQ==, tarball: https://registry.npmjs.org/@wordpress/viewport/-/viewport-6.48.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
peerDependencies:
react: ^18.0.0
@@ -11476,15 +11479,15 @@ packages:
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/warning@2.58.0':
- resolution: {integrity: sha512-9bZlORhyMY2nbWozeyC5kqJsFzEPP4DCLhGmjtbv+YWGHttUrxUZEfrKdqO+rUODA8rP5zeIly1nCQOUnkw4Lg==}
+ resolution: {integrity: sha512-9bZlORhyMY2nbWozeyC5kqJsFzEPP4DCLhGmjtbv+YWGHttUrxUZEfrKdqO+rUODA8rP5zeIly1nCQOUnkw4Lg==, tarball: https://registry.npmjs.org/@wordpress/warning/-/warning-2.58.0.tgz}
engines: {node: '>=12'}
'@wordpress/warning@3.33.1':
- resolution: {integrity: sha512-ciDPM0AEu1s3xjDUwiTRxWiY0sTKTXI4R8NYO57g9+RuP4M5JnLK5/mdLVFCiWNo27tkUPFAgzHop7ssj3inew==}
+ resolution: {integrity: sha512-ciDPM0AEu1s3xjDUwiTRxWiY0sTKTXI4R8NYO57g9+RuP4M5JnLK5/mdLVFCiWNo27tkUPFAgzHop7ssj3inew==, tarball: https://registry.npmjs.org/@wordpress/warning/-/warning-3.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/warning@3.45.0':
- resolution: {integrity: sha512-NQ9tAhPdwhfceVIzWra1rbumvgAFAEDTgZlWsX880zLiq1F8JTwBouwW6wfIhA3XLcY6Yj7cBBYLa8vnNiDZDw==}
+ resolution: {integrity: sha512-NQ9tAhPdwhfceVIzWra1rbumvgAFAEDTgZlWsX880zLiq1F8JTwBouwW6wfIhA3XLcY6Yj7cBBYLa8vnNiDZDw==, tarball: https://registry.npmjs.org/@wordpress/warning/-/warning-3.45.0.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/warning@3.48.1':
@@ -11502,7 +11505,7 @@ packages:
engines: {node: '>=12'}
'@wordpress/wordcount@4.33.1':
- resolution: {integrity: sha512-Qg9+Ah9rEH8vOZAThF8CQS+TrWOmpKbGtRy+ZgLghc+mr2FGpyal3hwsoS3yFW6CUSf23YTWw2k2osEeTf2erQ==}
+ resolution: {integrity: sha512-Qg9+Ah9rEH8vOZAThF8CQS+TrWOmpKbGtRy+ZgLghc+mr2FGpyal3hwsoS3yFW6CUSf23YTWw2k2osEeTf2erQ==, tarball: https://registry.npmjs.org/@wordpress/wordcount/-/wordcount-4.33.1.tgz}
engines: {node: '>=18.12.0', npm: '>=8.19.2'}
'@wordpress/wordcount@4.48.1':
@@ -12320,7 +12323,7 @@ packages:
optional: true
bare-fs@4.7.0:
- resolution: {integrity: sha512-xzqKsCFxAek9aezYhjJuJRXBIaYlg/0OGDTZp+T8eYmYMlm66cs6cYko02drIyjN2CBbi+I6L7YfXyqpqtKRXA==}
+ resolution: {integrity: sha512-xzqKsCFxAek9aezYhjJuJRXBIaYlg/0OGDTZp+T8eYmYMlm66cs6cYko02drIyjN2CBbi+I6L7YfXyqpqtKRXA==, tarball: https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.0.tgz}
engines: {bare: '>=1.16.0'}
peerDependencies:
bare-buffer: '*'
@@ -12333,7 +12336,7 @@ packages:
engines: {bare: '>=1.14.0'}
bare-path@3.0.0:
- resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==}
+ resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==, tarball: https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz}
bare-stream@2.13.0:
resolution: {integrity: sha512-3zAJRZMDFGjdn+RVnNpF9kuELw+0Fl3lpndM4NcEOhb9zwtSo/deETfuIwMSE5BXanA0FrN1qVjffGwAg2Y7EA==}
@@ -12476,7 +12479,7 @@ packages:
engines: {node: '>=8'}
brcast@2.0.2:
- resolution: {integrity: sha512-Tfn5JSE7hrUlFcOoaLzVvkbgIemIorMIyoMr3TgvszWW7jFt2C9PdeMLtysYD9RU0MmU17b69+XJG1eRY2OBRg==}
+ resolution: {integrity: sha512-Tfn5JSE7hrUlFcOoaLzVvkbgIemIorMIyoMr3TgvszWW7jFt2C9PdeMLtysYD9RU0MmU17b69+XJG1eRY2OBRg==, tarball: https://registry.npmjs.org/brcast/-/brcast-2.0.2.tgz}
brorand@1.1.0:
resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==}
@@ -12934,13 +12937,13 @@ packages:
resolution: {integrity: sha512-ydG4nDZesbFurnNq0VVCp/yyomIBh+X/1fZPI/P24zbnG4dtC4tQAfI5uQsomigsUMeiRO2wiTPizLWQh+IAyQ==}
clipboard@2.0.11:
- resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
+ resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==, tarball: https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz}
cliui@3.2.0:
resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==}
cliui@5.0.0:
- resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==}
+ resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==, tarball: https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
@@ -13051,7 +13054,7 @@ packages:
resolution: {integrity: sha512-Ajpjd8asqZ6EdxQeqGzU5WBhhTfJ/0cA4Wlbre7e5vXfmDSmda7Ov6jeKoru+b0vHcb1CqvuroTHp5zIWzhVMA==}
colord@2.9.3:
- resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
+ resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==, tarball: https://registry.npmjs.org/colord/-/colord-2.9.3.tgz}
colorette@1.4.0:
resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
@@ -13060,7 +13063,7 @@ packages:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
colorjs.io@0.5.2:
- resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
+ resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==, tarball: https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz}
colorjs.io@0.6.1:
resolution: {integrity: sha512-8lyR2wHzuIykCpqHKgluGsqQi5iDm3/a2IgP2GBZrasn2sBRkE4NOGsglZxWLs/jZQoNkmA/KM/8NV16rLUdBg==}
@@ -13671,7 +13674,7 @@ packages:
resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==}
date-fns-jalali@4.1.0-0:
- resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==}
+ resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==, tarball: https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz}
date-fns-tz@3.2.0:
resolution: {integrity: sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==}
@@ -13683,10 +13686,10 @@ packages:
engines: {node: '>=0.11'}
date-fns@3.6.0:
- resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
+ resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==, tarball: https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz}
date-fns@4.1.0:
- resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
+ resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==, tarball: https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz}
dateformat@3.0.3:
resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==}
@@ -13786,7 +13789,7 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
deepmerge@1.5.2:
- resolution: {integrity: sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==}
+ resolution: {integrity: sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==, tarball: https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz}
engines: {node: '>=0.10.0'}
deepmerge@4.3.1:
@@ -13828,7 +13831,7 @@ packages:
optional: true
default-browser-id@1.0.4:
- resolution: {integrity: sha512-qPy925qewwul9Hifs+3sx1ZYn14obHxpkX+mPD369w4Rzg+YkJBgi3SOvwUq81nWSjqGUegIgEPwD8u+HUnxlw==}
+ resolution: {integrity: sha512-qPy925qewwul9Hifs+3sx1ZYn14obHxpkX+mPD369w4Rzg+YkJBgi3SOvwUq81nWSjqGUegIgEPwD8u+HUnxlw==, tarball: https://registry.npmjs.org/default-browser-id/-/default-browser-id-1.0.4.tgz}
engines: {node: '>=0.10.0'}
hasBin: true
@@ -13891,7 +13894,7 @@ packages:
engines: {node: '>=0.4.0'}
delegate@3.2.0:
- resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
+ resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==, tarball: https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz}
delegates@1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
@@ -13995,7 +13998,7 @@ packages:
engines: {node: '>=0.3.1'}
diff@4.0.4:
- resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==}
+ resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==, tarball: https://registry.npmjs.org/diff/-/diff-4.0.4.tgz}
engines: {node: '>=0.3.1'}
diff@5.2.2:
@@ -14022,7 +14025,7 @@ packages:
engines: {node: '>=8'}
direction@1.0.4:
- resolution: {integrity: sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ==}
+ resolution: {integrity: sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ==, tarball: https://registry.npmjs.org/direction/-/direction-1.0.4.tgz}
hasBin: true
discontinuous-range@1.0.0:
@@ -14254,7 +14257,7 @@ packages:
resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==}
encoding@0.1.13:
- resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
+ resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==, tarball: https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz}
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
@@ -14691,7 +14694,7 @@ packages:
eslint: ^7.5.0 || ^8.0.0
eslint-plugin-wpcalypso@4.1.0:
- resolution: {integrity: sha512-2gZdaaX5rS7vve5FfIBTANPFXfQstxMppUFR8KzrY5cJPt7hIhpg9lOb4y0hVYNdJkhZxkvEWw8yoJhaUc1OYQ==}
+ resolution: {integrity: sha512-2gZdaaX5rS7vve5FfIBTANPFXfQstxMppUFR8KzrY5cJPt7hIhpg9lOb4y0hVYNdJkhZxkvEWw8yoJhaUc1OYQ==, tarball: https://registry.npmjs.org/eslint-plugin-wpcalypso/-/eslint-plugin-wpcalypso-4.1.0.tgz}
engines: {node: '>=10'}
peerDependencies:
eslint: '>=5'
@@ -14946,7 +14949,7 @@ packages:
engines: {'0': node >=0.6.0}
fast-average-color@9.5.2:
- resolution: {integrity: sha512-FbaU8iPTPljP7tmnVhXbCyASNw/zxnmaNDf88gn5pTXlNvejl9w4FapeWMh6UNDwIjhJJU28EPfQWwW032YgPA==}
+ resolution: {integrity: sha512-FbaU8iPTPljP7tmnVhXbCyASNw/zxnmaNDf88gn5pTXlNvejl9w4FapeWMh6UNDwIjhJJU28EPfQWwW032YgPA==, tarball: https://registry.npmjs.org/fast-average-color/-/fast-average-color-9.5.2.tgz}
engines: {node: '>= 12'}
fast-check@3.23.2:
@@ -15345,7 +15348,7 @@ packages:
engines: {node: '>=0.10.0'}
framer-motion@10.18.0:
- resolution: {integrity: sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==}
+ resolution: {integrity: sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==, tarball: https://registry.npmjs.org/framer-motion/-/framer-motion-10.18.0.tgz}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
@@ -15356,7 +15359,7 @@ packages:
optional: true
framer-motion@11.18.2:
- resolution: {integrity: sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==}
+ resolution: {integrity: sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==, tarball: https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
@@ -15428,18 +15431,18 @@ packages:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fsevents@1.2.13:
- resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==}
+ resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz}
engines: {node: '>= 4.0'}
os: [darwin]
deprecated: Upgrade to fsevents v2 to mitigate potential security issues
fsevents@2.3.2:
- resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
@@ -15501,7 +15504,7 @@ packages:
engines: {node: '>=8.0.0'}
get-port@5.1.1:
- resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==}
+ resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==, tarball: https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz}
engines: {node: '>=8'}
get-proto@1.0.1:
@@ -15559,7 +15562,7 @@ packages:
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
gettext-parser@1.4.0:
- resolution: {integrity: sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==}
+ resolution: {integrity: sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==, tarball: https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz}
gh-pages@5.0.0:
resolution: {integrity: sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==}
@@ -15702,7 +15705,7 @@ packages:
hasBin: true
good-listener@1.2.2:
- resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==}
+ resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==, tarball: https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
@@ -15724,11 +15727,11 @@ packages:
engines: {node: '>=0.10.0'}
gradient-parser@1.0.2:
- resolution: {integrity: sha512-gR6nY33xC9yJoH4wGLQtZQMXDi6RI3H37ERu7kQCVUzlXjNedpZM7xcA489Opwbq0BSGohtWGsWsntupmxelMg==}
+ resolution: {integrity: sha512-gR6nY33xC9yJoH4wGLQtZQMXDi6RI3H37ERu7kQCVUzlXjNedpZM7xcA489Opwbq0BSGohtWGsWsntupmxelMg==, tarball: https://registry.npmjs.org/gradient-parser/-/gradient-parser-1.0.2.tgz}
engines: {node: '>=0.10.0'}
gradient-parser@1.1.1:
- resolution: {integrity: sha512-Hu0YfNU+38EsTmnUfLXUKFMXq9yz7htGYpF4x+dlbBhUCvIvzLt0yVLT/gJRmvLKFJdqNFrz4eKkIUjIXSr7Tw==}
+ resolution: {integrity: sha512-Hu0YfNU+38EsTmnUfLXUKFMXq9yz7htGYpF4x+dlbBhUCvIvzLt0yVLT/gJRmvLKFJdqNFrz4eKkIUjIXSr7Tw==, tarball: https://registry.npmjs.org/gradient-parser/-/gradient-parser-1.1.1.tgz}
engines: {node: '>=0.10.0'}
grapheme-splitter@1.0.4:
@@ -16006,7 +16009,7 @@ packages:
resolution: {integrity: sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==}
highlight-words-core@1.2.3:
- resolution: {integrity: sha512-m1O9HW3/GNHxzSIXWw1wCNXXsgLlxrP0OI6+ycGUhiUHkikqW3OrwVHz+lxeNBe5yqLESdIcj8PowHQ2zLvUvQ==}
+ resolution: {integrity: sha512-m1O9HW3/GNHxzSIXWw1wCNXXsgLlxrP0OI6+ycGUhiUHkikqW3OrwVHz+lxeNBe5yqLESdIcj8PowHQ2zLvUvQ==, tarball: https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.3.tgz}
highlight.js@10.7.3:
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
@@ -16055,7 +16058,7 @@ packages:
resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==}
hpq@1.4.0:
- resolution: {integrity: sha512-ycJQMRaRPBcfnoT1gS5I1XCvbbw9KO94Y0vkwksuOjcJMqNZtb03MF2tCItLI2mQbkZWSSeFinoRDPmjzv4tKg==}
+ resolution: {integrity: sha512-ycJQMRaRPBcfnoT1gS5I1XCvbbw9KO94Y0vkwksuOjcJMqNZtb03MF2tCItLI2mQbkZWSSeFinoRDPmjzv4tKg==, tarball: https://registry.npmjs.org/hpq/-/hpq-1.4.0.tgz}
html-dom-parser@3.1.2:
resolution: {integrity: sha512-mLTtl3pVn3HnqZSZzW3xVs/mJAKrG1yIw3wlp+9bdoZHHLaBRvELdpfShiPVLyjPypq1Fugv2KMDoGHW4lVXnw==}
@@ -16309,7 +16312,7 @@ packages:
resolution: {integrity: sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw==}
immutable@5.1.6:
- resolution: {integrity: sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==}
+ resolution: {integrity: sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==, tarball: https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz}
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
@@ -16707,7 +16710,7 @@ packages:
engines: {node: '>=0.10.0'}
is-plain-object@5.0.0:
- resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
+ resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==, tarball: https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz}
engines: {node: '>=0.10.0'}
is-potential-custom-element-name@1.0.1:
@@ -17548,7 +17551,7 @@ packages:
engines: {node: '>=0.10.0'}
legacy-javascript@0.0.1:
- resolution: {integrity: sha512-lPyntS4/aS7jpuvOlitZDFifBCb4W8L/3QU0PLbUTUj+zYah8rfVjYic88yG7ZKTxhS5h9iz7duT8oUXKszLhg==}
+ resolution: {integrity: sha512-lPyntS4/aS7jpuvOlitZDFifBCb4W8L/3QU0PLbUTUj+zYah8rfVjYic88yG7ZKTxhS5h9iz7duT8oUXKszLhg==, tarball: https://registry.npmjs.org/legacy-javascript/-/legacy-javascript-0.0.1.tgz}
leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
@@ -18213,7 +18216,7 @@ packages:
hasBin: true
mime@3.0.0:
- resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
+ resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==, tarball: https://registry.npmjs.org/mime/-/mime-3.0.0.tgz}
engines: {node: '>=10.0.0'}
hasBin: true
@@ -18392,13 +18395,13 @@ packages:
resolution: {integrity: sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==}
motion-dom@11.18.1:
- resolution: {integrity: sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==}
+ resolution: {integrity: sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==, tarball: https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz}
motion-utils@11.18.1:
- resolution: {integrity: sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==}
+ resolution: {integrity: sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==, tarball: https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz}
mousetrap@1.6.5:
- resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==}
+ resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==, tarball: https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz}
move-concurrently@1.0.1:
resolution: {integrity: sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==}
@@ -18475,7 +18478,7 @@ packages:
resolution: {integrity: sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==}
ndb@1.1.5:
- resolution: {integrity: sha512-YiK+1wRe9SnZIyZ3kLDmogV2/Z0+8uPgHNbk3ExXzJg6IEFSenfskkn82v5ajPUJKkeEpsaK+ae1eT1be8Hllw==}
+ resolution: {integrity: sha512-YiK+1wRe9SnZIyZ3kLDmogV2/Z0+8uPgHNbk3ExXzJg6IEFSenfskkn82v5ajPUJKkeEpsaK+ae1eT1be8Hllw==, tarball: https://registry.npmjs.org/ndb/-/ndb-1.1.5.tgz}
engines: {node: '>=8.0.0'}
hasBin: true
@@ -18567,10 +18570,10 @@ packages:
resolution: {integrity: sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==}
node-notifier@8.0.2:
- resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==}
+ resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==, tarball: https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz}
node-pty@0.9.0:
- resolution: {integrity: sha512-MBnCQl83FTYOu7B4xWw10AW77AAh7ThCE1VXEv+JeWj8mSpGo+0bwgsV+b23ljBFwEM9OmsOv3kM27iUPPm84g==}
+ resolution: {integrity: sha512-MBnCQl83FTYOu7B4xWw10AW77AAh7ThCE1VXEv+JeWj8mSpGo+0bwgsV+b23ljBFwEM9OmsOv3kM27iUPPm84g==, tarball: https://registry.npmjs.org/node-pty/-/node-pty-0.9.0.tgz}
node-releases@2.0.37:
resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==}
@@ -18637,7 +18640,7 @@ packages:
engines: {node: '>=10'}
normalize-wheel@1.0.1:
- resolution: {integrity: sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==}
+ resolution: {integrity: sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==, tarball: https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz}
npm-bundled@1.1.2:
resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==}
@@ -19106,7 +19109,7 @@ packages:
resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
parsel-js@1.2.2:
- resolution: {integrity: sha512-AVJMlwQ4bL2Y0VvYJGk+Fp7eX4SCH2uFoNApmn4yKWACUewZ+alwW3tyoe1r5Z3aLYQTuAuPZIyGghMfO/Tlxw==}
+ resolution: {integrity: sha512-AVJMlwQ4bL2Y0VvYJGk+Fp7eX4SCH2uFoNApmn4yKWACUewZ+alwW3tyoe1r5Z3aLYQTuAuPZIyGghMfO/Tlxw==, tarball: https://registry.npmjs.org/parsel-js/-/parsel-js-1.2.2.tgz}
parseurl@1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
@@ -19204,7 +19207,7 @@ packages:
resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==}
path-to-regexp@6.3.0:
- resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
+ resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==, tarball: https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz}
path-type@1.1.0:
resolution: {integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==}
@@ -19459,7 +19462,7 @@ packages:
postcss-syntax: '>=0.36.0'
postcss-import@16.1.1:
- resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==}
+ resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==, tarball: https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.1.tgz}
engines: {node: '>=18.0.0'}
peerDependencies:
postcss: ^8.0.0
@@ -19720,7 +19723,7 @@ packages:
postcss: ^8.4.31
postcss-prefix-selector@1.16.1:
- resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==}
+ resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==, tarball: https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.1.tgz}
peerDependencies:
postcss: '>4 <9'
@@ -19839,7 +19842,7 @@ packages:
postcss: ^8.4.31
postcss-urlrebase@1.4.0:
- resolution: {integrity: sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==}
+ resolution: {integrity: sha512-rRaxMmWvXrn8Rk1PqsxmaJwldRHsr0WbbASKKCZYxXwotHkM/5X/6IrwaEe8pdzpbNGCEY86yhYMN0MhgOkADA==, tarball: https://registry.npmjs.org/postcss-urlrebase/-/postcss-urlrebase-1.4.0.tgz}
peerDependencies:
postcss: ^8.3.0
@@ -19905,12 +19908,12 @@ packages:
engines: {node: '>=6.0.0'}
prettier@2.3.0:
- resolution: {integrity: sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==}
+ resolution: {integrity: sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==, tarball: https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz}
engines: {node: '>=10.13.0'}
hasBin: true
prettier@2.8.8:
- resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
+ resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==, tarball: https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz}
engines: {node: '>=10.13.0'}
hasBin: true
@@ -20227,7 +20230,7 @@ packages:
hasBin: true
re-resizable@6.11.2:
- resolution: {integrity: sha512-2xI2P3OHs5qw7K0Ud1aLILK6MQxW50TcO+DetD9eIV58j84TqYeHoZcL9H4GXFXXIh7afhH8mv5iUCXII7OW7A==}
+ resolution: {integrity: sha512-2xI2P3OHs5qw7K0Ud1aLILK6MQxW50TcO+DetD9eIV58j84TqYeHoZcL9H4GXFXXIh7afhH8mv5iUCXII7OW7A==, tarball: https://registry.npmjs.org/re-resizable/-/re-resizable-6.11.2.tgz}
peerDependencies:
react: ^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -20242,7 +20245,7 @@ packages:
react-dom: ^0.14.0 || ^15.0.0 || ^16.0.0
react-colorful@5.6.1:
- resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==}
+ resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==, tarball: https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
@@ -20264,7 +20267,7 @@ packages:
react-with-direction: ^1.3.1
react-day-picker@9.14.0:
- resolution: {integrity: sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==}
+ resolution: {integrity: sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==, tarball: https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.14.0.tgz}
engines: {node: '>=18'}
peerDependencies:
react: '>=16.8.0'
@@ -20290,7 +20293,7 @@ packages:
engines: {node: '>=16.14.0'}
react-dom@17.0.2:
- resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==}
+ resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==, tarball: https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz}
peerDependencies:
react: 17.0.2
@@ -20300,7 +20303,7 @@ packages:
react: ^18.3.1
react-easy-crop@5.5.7:
- resolution: {integrity: sha512-kYo4NtMeXFQB7h1U+h5yhUkE46WQbQdq7if54uDlbMdZHdRgNehfvaFrXnFw5NR1PNoUOJIfTwLnWmEx/MaZnA==}
+ resolution: {integrity: sha512-kYo4NtMeXFQB7h1U+h5yhUkE46WQbQdq7if54uDlbMdZHdRgNehfvaFrXnFw5NR1PNoUOJIfTwLnWmEx/MaZnA==, tarball: https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.5.7.tgz}
peerDependencies:
react: '>=16.4.0'
react-dom: '>=16.4.0'
@@ -20549,7 +20552,7 @@ packages:
react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-with-direction@1.4.0:
- resolution: {integrity: sha512-ybHNPiAmaJpoWwugwqry9Hd1Irl2hnNXlo/2SXQBwbLn/jGMauMS2y9jw+ydyX5V9ICryCqObNSthNt5R94xpg==}
+ resolution: {integrity: sha512-ybHNPiAmaJpoWwugwqry9Hd1Irl2hnNXlo/2SXQBwbLn/jGMauMS2y9jw+ydyX5V9ICryCqObNSthNt5R94xpg==, tarball: https://registry.npmjs.org/react-with-direction/-/react-with-direction-1.4.0.tgz}
peerDependencies:
react: ^0.14 || ^15 || ^16
react-dom: ^0.14 || ^15 || ^16
@@ -20579,7 +20582,7 @@ packages:
react-with-direction: ^1.3.1
react@17.0.2:
- resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
+ resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==, tarball: https://registry.npmjs.org/react/-/react-17.0.2.tgz}
engines: {node: '>=0.10.0'}
react@18.3.1:
@@ -20587,7 +20590,7 @@ packages:
engines: {node: '>=0.10.0'}
read-cache@1.0.0:
- resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==, tarball: https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz}
read-cmd-shim@3.0.1:
resolution: {integrity: sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g==}
@@ -20815,7 +20818,7 @@ packages:
resolution: {integrity: sha512-EpFcOa/ISetVHEXqu+VwI96KZBmq+a8LJnGkaeFw45epGlxIZz5dhEEnNZMsQXgORu3qaMoLX4qJCzOik6ytAg==}
remove-accents@0.5.0:
- resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==}
+ resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==, tarball: https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz}
remove-trailing-separator@1.1.0:
resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
@@ -21071,7 +21074,7 @@ packages:
engines: {node: '>=0.4'}
safe-buffer@5.1.2:
- resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+ resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, tarball: https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@@ -21104,119 +21107,119 @@ packages:
hasBin: true
sass-embedded-all-unknown@1.100.0:
- resolution: {integrity: sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==}
+ resolution: {integrity: sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==, tarball: https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.100.0.tgz}
cpu: ['!arm', '!arm64', '!riscv64', '!x64']
sass-embedded-android-arm64@1.100.0:
- resolution: {integrity: sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==}
+ resolution: {integrity: sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==, tarball: https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [android]
sass-embedded-android-arm@1.100.0:
- resolution: {integrity: sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==}
+ resolution: {integrity: sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==, tarball: https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [android]
sass-embedded-android-riscv64@1.100.0:
- resolution: {integrity: sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==}
+ resolution: {integrity: sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==, tarball: https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [android]
sass-embedded-android-x64@1.100.0:
- resolution: {integrity: sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==}
+ resolution: {integrity: sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==, tarball: https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [android]
sass-embedded-darwin-arm64@1.100.0:
- resolution: {integrity: sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==}
+ resolution: {integrity: sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==, tarball: https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [darwin]
sass-embedded-darwin-x64@1.100.0:
- resolution: {integrity: sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==}
+ resolution: {integrity: sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==, tarball: https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [darwin]
sass-embedded-linux-arm64@1.100.0:
- resolution: {integrity: sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==}
+ resolution: {integrity: sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==, tarball: https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
libc: glibc
sass-embedded-linux-arm@1.100.0:
- resolution: {integrity: sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==}
+ resolution: {integrity: sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==, tarball: https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
libc: glibc
sass-embedded-linux-musl-arm64@1.100.0:
- resolution: {integrity: sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==}
+ resolution: {integrity: sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
libc: musl
sass-embedded-linux-musl-arm@1.100.0:
- resolution: {integrity: sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==}
+ resolution: {integrity: sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
libc: musl
sass-embedded-linux-musl-riscv64@1.100.0:
- resolution: {integrity: sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==}
+ resolution: {integrity: sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
libc: musl
sass-embedded-linux-musl-x64@1.100.0:
- resolution: {integrity: sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==}
+ resolution: {integrity: sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
libc: musl
sass-embedded-linux-riscv64@1.100.0:
- resolution: {integrity: sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==}
+ resolution: {integrity: sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==, tarball: https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
libc: glibc
sass-embedded-linux-x64@1.100.0:
- resolution: {integrity: sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==}
+ resolution: {integrity: sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==, tarball: https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
libc: glibc
sass-embedded-unknown-all@1.100.0:
- resolution: {integrity: sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==}
+ resolution: {integrity: sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==, tarball: https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.100.0.tgz}
os: ['!android', '!darwin', '!linux', '!win32']
sass-embedded-win32-arm64@1.100.0:
- resolution: {integrity: sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==}
+ resolution: {integrity: sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==, tarball: https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [win32]
sass-embedded-win32-x64@1.100.0:
- resolution: {integrity: sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==}
+ resolution: {integrity: sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==, tarball: https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.100.0.tgz}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [win32]
sass-embedded@1.100.0:
- resolution: {integrity: sha512-Ut8wlQSk19tm7jMK6mz6cF1+e+E7tUnW2tM02zQDPnOTcVbV8qCQG8UWxZkkNlY50+hV3hqP24OOkUlMz8xBpw==}
+ resolution: {integrity: sha512-Ut8wlQSk19tm7jMK6mz6cF1+e+E7tUnW2tM02zQDPnOTcVbV8qCQG8UWxZkkNlY50+hV3hqP24OOkUlMz8xBpw==, tarball: https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.100.0.tgz}
engines: {node: '>=16.0.0'}
hasBin: true
@@ -21340,7 +21343,7 @@ packages:
resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==}
select@1.1.2:
- resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
+ resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==, tarball: https://registry.npmjs.org/select/-/select-1.1.2.tgz}
selfsigned@2.4.1:
resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
@@ -21479,7 +21482,7 @@ packages:
resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==}
showdown@1.9.1:
- resolution: {integrity: sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==}
+ resolution: {integrity: sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==, tarball: https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz}
hasBin: true
shx@0.3.4:
@@ -22178,11 +22181,11 @@ packages:
engines: {node: '>= 0.4'}
sync-child-process@1.0.2:
- resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==}
+ resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==, tarball: https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz}
engines: {node: '>=16.0.0'}
sync-message-port@1.2.0:
- resolution: {integrity: sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==}
+ resolution: {integrity: sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==, tarball: https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.2.0.tgz}
engines: {node: '>=16.0.0'}
synchronous-promise@2.0.17:
@@ -22198,7 +22201,7 @@ packages:
hasBin: true
tabbable@6.4.0:
- resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==}
+ resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==, tarball: https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz}
table@5.4.6:
resolution: {integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==}
@@ -22212,7 +22215,7 @@ packages:
resolution: {integrity: sha512-kS7E53It6HA8S1FVFBWP7HDwgTiJtkmYk7TsowGlizzVrivR1Mf9mgjXHY1k7rOfozRVMZSfwjB3bevO4QEqpg==}
tannin@1.2.0:
- resolution: {integrity: sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==}
+ resolution: {integrity: sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==, tarball: https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz}
tapable@0.1.10:
resolution: {integrity: sha512-jX8Et4hHg57mug1/079yitEKWGB3LCwoxByLsNim89LABq8NqgiX+6iYVOsq0vX8uJHkU+DZ5fnq95f800bEsQ==}
@@ -22263,7 +22266,7 @@ packages:
resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==}
temml@0.10.34:
- resolution: {integrity: sha512-f3b5CaPwPvMviA+CtHy0qoIGWvzpRrNpXmGRc/Y1jc9gAYy+xOlndJFyn7Vfcz7cBcS8QRvv8z0EEH59sHCQxg==}
+ resolution: {integrity: sha512-f3b5CaPwPvMviA+CtHy0qoIGWvzpRrNpXmGRc/Y1jc9gAYy+xOlndJFyn7Vfcz7cBcS8QRvv8z0EEH59sHCQxg==, tarball: https://registry.npmjs.org/temml/-/temml-0.10.34.tgz}
engines: {node: '>=18.13.0'}
temp-dir@2.0.0:
@@ -22349,7 +22352,7 @@ packages:
resolution: {integrity: sha512-h0JYX+dO2Zr3abCQpS6/uFjujaOjA1DyDzGQ41+oFn9VW/ARiq9g5ln7qEP9+BTzDpOMyIfsfj4OvfgXAsMUSA==}
third-party-web@0.29.2:
- resolution: {integrity: sha512-fegtha91tq2DHphyoiBXVHjVi2YG9zFaRnboT9C28tO1en9Y3wJsfspuy40F+u5wl3hHVbw7cnd1b67kEGHb8g==}
+ resolution: {integrity: sha512-fegtha91tq2DHphyoiBXVHjVi2YG9zFaRnboT9C28tO1en9Y3wJsfspuy40F+u5wl3hHVbw7cnd1b67kEGHb8g==, tarball: https://registry.npmjs.org/third-party-web/-/third-party-web-0.29.2.tgz}
throat@5.0.0:
resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==}
@@ -22376,7 +22379,7 @@ packages:
engines: {node: '>=0.6.0'}
tiny-emitter@2.1.0:
- resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
+ resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==, tarball: https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz}
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
@@ -23143,7 +23146,7 @@ packages:
optional: true
varint@6.0.0:
- resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
+ resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==, tarball: https://registry.npmjs.org/varint/-/varint-6.0.0.tgz}
vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
@@ -23226,7 +23229,7 @@ packages:
engines: {node: '>=16.4.0'}
watchpack-chokidar2@2.0.1:
- resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==}
+ resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==, tarball: https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz}
watchpack@1.7.5:
resolution: {integrity: sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==}
@@ -23248,7 +23251,7 @@ packages:
resolution: {integrity: sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg==}
web-vitals@4.2.4:
- resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
+ resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==, tarball: https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz}
webdriver-bidi-protocol@0.4.1:
resolution: {integrity: sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==}
@@ -23538,7 +23541,7 @@ packages:
resolution: {integrity: sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==}
wp-prettier@2.2.1-beta-1:
- resolution: {integrity: sha512-+JHkqs9LC/JPp51yy1hzs3lQ7qeuWCwOcSzpQNeeY/G7oSpnF61vxt7hRh87zNRTr6ob2ndy0W8rVzhgrcA+Gw==}
+ resolution: {integrity: sha512-+JHkqs9LC/JPp51yy1hzs3lQ7qeuWCwOcSzpQNeeY/G7oSpnF61vxt7hRh87zNRTr6ob2ndy0W8rVzhgrcA+Gw==, tarball: https://registry.npmjs.org/wp-prettier/-/wp-prettier-2.2.1-beta-1.tgz}
engines: {node: '>=10.13.0'}
hasBin: true
@@ -23548,7 +23551,7 @@ packages:
hasBin: true
wp-prettier@3.0.3:
- resolution: {integrity: sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==}
+ resolution: {integrity: sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA==, tarball: https://registry.npmjs.org/wp-prettier/-/wp-prettier-3.0.3.tgz}
engines: {node: '>=14'}
hasBin: true
@@ -23563,7 +23566,7 @@ packages:
engines: {node: '>=0.10.0'}
wrap-ansi@5.1.0:
- resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==}
+ resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==, tarball: https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz}
engines: {node: '>=6'}
wrap-ansi@6.2.0:
@@ -23785,7 +23788,7 @@ packages:
hasBin: true
yargs-parser@15.0.3:
- resolution: {integrity: sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==}
+ resolution: {integrity: sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==, tarball: https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz}
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
@@ -23803,7 +23806,7 @@ packages:
engines: {node: '>=12'}
yargs@14.2.3:
- resolution: {integrity: sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==}
+ resolution: {integrity: sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==, tarball: https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz}
yargs@15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
@@ -26307,7 +26310,7 @@ snapshots:
'@types/istanbul-lib-coverage': 2.0.6
collect-v8-coverage: 1.0.3
- '@jest/test-sequencer@26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3))':
+ '@jest/test-sequencer@26.6.3':
dependencies:
'@jest/test-result': 26.6.2
graceful-fs: 4.2.11
@@ -26315,11 +26318,7 @@ snapshots:
jest-runner: 26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3))
jest-runtime: 26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3))
transitivePeerDependencies:
- - bufferutil
- - canvas
- supports-color
- - ts-node
- - utf-8-validate
'@jest/test-sequencer@29.7.0':
dependencies:
@@ -38002,7 +38001,7 @@ snapshots:
expect-puppeteer: 4.4.0
filenamify: 4.3.0
jest: 26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3))
- jest-circus: 26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3))
+ jest-circus: 26.6.3
jest-dev-server: 5.0.3
jest-environment-node: 26.6.2
markdownlint: 0.23.1
@@ -46221,7 +46220,7 @@ snapshots:
jest-util: 29.7.0
p-limit: 3.1.0
- jest-circus@26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3)):
+ jest-circus@26.6.3:
dependencies:
'@babel/traverse': 7.29.0
'@jest/environment': 26.6.2
@@ -46245,11 +46244,7 @@ snapshots:
stack-utils: 2.0.6
throat: 5.0.0
transitivePeerDependencies:
- - bufferutil
- - canvas
- supports-color
- - ts-node
- - utf-8-validate
jest-circus@29.5.0:
dependencies:
@@ -46370,7 +46365,7 @@ snapshots:
jest-config@26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3)):
dependencies:
'@babel/core': 7.25.7
- '@jest/test-sequencer': 26.6.3(ts-node@10.9.2(@swc/core@1.15.24)(@types/node@24.12.2)(typescript@5.7.3))
+ '@jest/test-sequencer': 26.6.3
'@jest/types': 26.6.2
babel-jest: 26.6.3(@babel/core@7.25.7)
chalk: 4.1.2