From 2434b7a4df9553f0627a49caa2043ec72fdca70b Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Thu, 21 Dec 2023 09:05:04 -0600 Subject: [PATCH] Catch up your branch (#2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Social: Fix auto-conversion cleanup logic (#34666) * Fix logic to be mindful of absent option * changelog * Fixup versions * Launchpad: Improve the WC task visibility check (#34648) * Improve the WC task visibility check * Bump version * Fix composer * changelog * Bump version --------- Co-authored-by: Valter Lorran * Improve sharing buttons events performance (#34652) * Backport mu-wpcom-plugin 2.0.7, jetpack 13.0-a.5 Changes (#34676) * Changelog edits. * Init new cycle * Carousel: fix unresponsive navigation (#34678) * Check for both aksimet and antispam for backwards compatibility (#34674) * Jetpack Google Fonts: Fix the fonts provided by theme are still added (#34608) * Google Fonts: Ignore the fonts that are provied by the active theme * changelog * Update syntax * Subscribers: fix the reach count above 1000 (#34689) Allows strings in translation strings. Ensures reachCount is consistently a Number, and convert it to string for localization. * Subscriptions: localize number format in access panel (#34691) * Added preemptive check full sync posts processing (#34661) * Added preemptive check to break the loop of adding metadata if we are already over the MAX SIZE * Added changelog * Added break 2 since there is no point in doing the comparison in the outer loop which will break too * Version bump * Like block: remove like module dependency (#34664) * - Remove dependency on likes module - Render master iframe (only once) * Changelog * Don't render anything when post_id is missing * Better check * Change master to main * Enqueue styles & register them on first usage * Remove require_once * Update iframe for WPCOM * Require the module * Docs: update quick start guide (#34656) * Clarify quick start guide is geared for a12s * Cleanup cloning and install script steps * Move env checker script heading below install steps * Adjust heading levels * Move jtube a11n-only note to top of its section * Add ngrok/jtube info to full dev-env guide * CRM: Ensure segments can be deleted (#34690) * Update JS unit testing packages (major) (#34694) * Update JS unit testing packages * Update indirect @adobe/css-tools dep --------- Co-authored-by: Renovate Bot Co-authored-by: Brad Jorsch * Update storybook monorepo to v7.6.5 (#34696) Co-authored-by: Renovate Bot * Show an error when one is encountered while rendering a payment button (#34380) * Render an error message when the button cannot be rendered * changelog * CRM: Resolves 3399 - make KB links consistent in settings (#34695) * Adjust wording to clarify all fields can show in Woo My Account * Add KB link * Use consistent UI to link to KB from settings * Simplify wording * Remove stray end tag * Remove errant colspan attribute * Add changelog * Only contact fields * Feature: AI Assistant UI fixes (#34383) * use spinner instead of ai icon * adjust main action button styles * only show main action buttons when there's content. Switch between icon and label for mobile. Do not show clear button is state is requesting * do not show clearbutton * changelog * fix versions * keep spinner while suggesting state * remove clear button * AI Assistant: change main action buttons style and behavior (#34370) * optimize style declaration * always use inputValue * AI Assistant: add suggestions actions (#34399) * add suggestion action buttons * add editRequest state to handle back and forth editing 'mode' * add discard callback on AI control, pass on tryAgain handler * add changelog entries * adjust behavior upon observations * AI Assistant: improve spacing and sizes for block and action buttons (#34444) * address spacing and size issues on the assistant block * modify loading icon wrapper and size * avoid height jumps when buttons wrapper is introduced * fix spacing on icon buttons * add changelogger entry for js-package * AI Assistant: fix block to bottom when content exceeds the viewport height (#34452) * fix ai block to bottom when content exceeds the viewport height * add outside wrapper * move positioning directive to outside wrapper * adjust bottom space for outside wrapper * AI Assistant: remove try again toolbar button (#34464) * make handleTryAgain optional so to remove when not present * add changelog entry * AI Assistant bar: fix positioning on mobile (#34476) * wrap assistant bar to control positioning * always make sure the assistant bar is placed AFTER the toolbar * add changelog entry * AI Assistant: add prompt to attributes (#34438) * add userPrompt to the block's attributes * set last value to default to initial prop * add requestingState to attributes to keep consistency between reloads * add changelog entry * AI assistant: change guideline component (#34496) * fix multiple line display on ai control footer message * export AI control message as FooterMessage * add changelog entry * AI Assistant: fix bottom padding issue (#34519) * fix bottom padding by using bottom directive for sticky positioning * add changelog entry * remove unnecessary directive * AI Assistant: restrict stored state value (#34522) * restrict stored states to 'init' and 'done' so we don't reload into half way scenarios * add changelog entry * fix misuse of ternary * add cancel button to get rid of the assistant block (#34524) * AI Client: fix empty prompts handling (#34547) * use a default value to keep track of changes in the prompt, allow for empty prompts to show suggestion action buttons * use null instead of a made up default value * handle edit mode logic on one-click actions (#34584) * AI Assistant: prepare new UI/UX features for merge (#34620) * consolidate changelog entry for ai-client * consolidate changelog entry for Jetpack plugin * add test instructions for the new AI Assistant UI/UX * AI Assistant: change prompt placeholder (#34671) * remove typing effect from prompt placeholders * use a fixed placeholder with suggestions on how to create a prompt * use different placeholders depending on whether there is content or not * move ternary out of jsx chunk * take i18n out of ternary * change placeholder text * remove back to edit button (#34675) * add showRemove attribute to AIControl (#34677) * Cleanup quick wins after feedback (#34679) * clean up changelog entries for ai-client * clean up changelog entries for jetpack plugin * AI assistant: fix positioning (#34700) * remove some confusing 100% widths messing with border alignments * fix colliding bottom directives on assistant bar * Membership services: small refactor (#34635) * Very small clean up * Rename abstract class filename * Create membership-abstract-token-class * Fix path * fix typing * Update class-wpcom-online-subscription-service.php * Update projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-asbtract-token-subscription-service.php Co-authored-by: Miguel Lezama * Update projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-jetpack-token-subscription-service.php Co-authored-by: Miguel Lezama * Rename file * Update class-wpcom-online-subscription-service.php * Rename references to Token_Subscription_Service * Fix naming --------- Co-authored-by: Miguel Lezama * Boost: Refactor module, index and more into React (#34662) * Create skeleton for Module component in React * Refactor UpgradeCTA to React * Added a small variant for toggle control * Use small variant of toggle control * Fix onEnable, onMountEnable, and onDisable * Do not pass yearlyPricing * Implement onEnable and onDisable * changelog * Create index component * Make module errors consistent with old design * Fix ISA alignment * Improve alignments and spacing * Add resize unavailable notice * Add fake recommendations meta * Add missing pieces * Cleanup * Remove Index.svelte * Move pricing to ds based config * Remove Module.svelte * Use React DS based moduleState management * Restore tsconfig change * Change interface for useModuleState callbacks * Call useModuleState hook directly on the component * Fix infinite loop on purchase success * Fixup project version * Fix selector in test * Make speed score dependent on useModulesState for auto-refresh to work * Fix isModuleEnabled check * Update modules-state endpoint in tests --------- Co-authored-by: Mark George * Boost: Migrate Tips to react (#34697) * Update Tips to react * add changelog * Backport crm 6.3.2 Changes (#34708) * Fix missing class fatal related to PR #34635 (#34705) * CRM: start 6.3.3-alpha release cycle (#34710) * Fix My plan dashboard js errors due to nested anchor tags (#34707) * Moved href from Button props to ExternalLink props to avoid duplicate anchor tags * Added changelog * Admin Page: avoid react warning with VideoPress card (#34713) This should avoid us getting the following warning: ``` Warning: Failed prop type: Invalid prop `overrideContent` of type `boolean` supplied to `DashItem`, expected a single ReactElement. DashItem@wp-content/plugins/jetpack/_inc/build/admin.js?ver=28b3a12169ab227bdcfa:36878:1 SettingsForm@wp-content/plugins/jetpack/_inc/build/admin.js?ver=28b3a12169ab227bdcfa:43524:3 ConnectFunction@wp-content/plugins/jetpack/_inc/build/admin.js?ver=28b3a12169ab227bdcfa:8870:68 ConnectFunction@wp-content/plugins/jetpack/_inc/build/admin.js?ver=28b3a12169ab227bdcfa:8870:68 DashVideoPress@wp-content/plugins/jetpack/_inc/build/admin.js?ver=28b3a12169ab227bdcfa:34467:1 ``` * Fix missing class fatal related to PR #34635 (#34718) * Subscriptions: update "verify your email" wall copy (#34716) Co-authored-by: Jeremy Herve * Fix sharing buttons window open (#34703) * Contact Form: add extra field settings to base field (#34704) * Contact Form: add extra field settings to base field * Fix package version * Fix the media validation notice shown even when auto conversion is enabled. (#34730) Co-authored-by: Gergely Juhasz * Add `wpcom_ai_site_prompt` option to the site settings endpoint (#34709) * Social: Fix endpoint backwards compatibility (#34566) * Readd REST controllers with updated logic * Readd class-settings classes for initial state population * changelog * Use depreacted and next_version tags * Fixup versions * Boost: Update Settings Page to react (#34714) * Update Settings Page to react * add changelog * Sharing: update Twitter and X buttons to support official X button (#34719) * Sharing: update Twitter and X buttons to support official X button See #34459 - The official Twitter button is no more; it has been updated to the X design. Let's update our preview Twitter button match. - Since we now have an official X button, let's offer it with the X service. * Adjust official button styles in wp-admin * This method is not needed * Update domain name * Update source name * Bump version by specifying Jetpack version when enqueuing * Update logo * Update icon with more radius * Social | Hide conversion notice for Simple sites (#34733) * Hide notice on simple sites * changelog * Make auto-conversion disabled if not available * Fixup versions * Sharing buttons block alternate settings screen (#34673) * build: Use a GitHub webhook to trigger the betadownload site (#34604) Once Automattic/jetpack-builder#36 is deployed, we can update our build script to produce the artifact for forked PRs and set up a GitHub webhook for the `workflow_run` event to support testing with PRs from forked repositories. This requires the GitHub "Fork pull request workflows from outside collaborators" setting to be set to "Require approval for all outside contributors" to avoid unreviewed code potentially producing malicious zips for the betadownload server. We've had that set since March 2023 (p9dueE-6Rp-p2). This also updates the Jetpack Live Branches script to remove the check for a forked PR, since we can now test with them. * Contact Form: minify stylesheets in prod (#34672) * Contact Form: minify stylesheets in prod * Update registered styles paths * Fix package version * Tools: Add the Readme to the release script (#34722) * Make sure the readme.txt file gets updated after saving changelog edits * Fix command being run * comment out a check * pass the correct flag * Undo comments * Update the next steps at the end * Fix token subscription service name (#34723) * Rename Token_Subscript_Service to Abstract_Token_Subscription_Service * changelog * Allow old class just in case * `use` classes at the top to shorten up the class check. * Content Lens: move feature to `beta` (#34740) * move `content-lens` feature to beta * changelog * Newsletter prepublish panel: update toggle appearance (#34724) * Contact Form: add accessible name to form (#34667) * Contact Form: add accessible name to form * Update accessible name on content change * Remove unused code * Fix package version * Add warning notice * Backport mu-wpcom-plugin 2.0.8, jetpack 13.0-a.7 Changes (#34742) * Changelog and readme.txt edits. * Init new cycle * Fix the stable tag * [Boost] Fix importmap deferral (#34746) * Add importmap to the set of script types we exclude from deferral * changelog * Fix versions in packages/forms * changelog --------- Co-authored-by: Mark George * Update changelog (#34747) * Admin page: remove alt attribute from decorative icon (#34715) The Alt value isn't necessary here, since the icon doesn't bring any additional info on the page for folks using screen readers. This has the added benefit of getting rid of a React warning: ``` Warning: Failed prop type: Invalid prop `alt` of type `object` supplied to `PlanIcon`, expected `string`. PlanIcon@wp-content/plugins/jetpack/_inc/build/admin.js?ver=15a830895a6f6d1e3c39:44686:1 MyPlanCard@wp-content/plugins/jetpack/_inc/build/admin.js?ver=15a830895a6f6d1e3c39:51709:20 ``` * Add/fix typo (#34712) * Fix typo * Chnagelog --------- Co-authored-by: Fabien MILLERAND * Boost: Refactor navigation into react (#34731) * Use react router * Add redirects * Fix typo * Add dummy ISA page * Add tracks * Restore getting started functionality * Move props to DS * Move connection to DS and cleanup props * Remove connection from JS constants * Improve getting started handling * Remove wrapping individual components with `DataSyncProvider` * Only start ISA if ISA is active * changelog * Use hook and component provided by react-router-dom * Remove data-sync provider wrapping from settings-page * Remove jetpack connection prop from analytics Analytics isn't collected while there is no connection. So, this prop is unnecessary anyway. * Pop bubbles for performanceHistoryNeedsUpdate * Fix priority support * Cast wpcom blogId into integer * Fix getting started with free * Fix getting started for real * Show index for missing routes * Stats: add passing select UTM parameters (#34431) This commit adds select UTM parameters to the pixel requests send to wp.com, so that we can show more statistics to site owners. --------- Co-authored-by: Gergely Márk Juhász <36671565+gmjuhasz@users.noreply.github.com> Co-authored-by: valterlorran Co-authored-by: Valter Lorran Co-authored-by: Andrii Lysenko <60262784+andrii-lysenko@users.noreply.github.com> Co-authored-by: Steve D <33553323+sdixon194@users.noreply.github.com> Co-authored-by: Kev Co-authored-by: arthur791004 Co-authored-by: Mikael Korpela Co-authored-by: Juanma Rodriguez Escriche Co-authored-by: Tim Broddin Co-authored-by: Samiff Co-authored-by: Karen Attfield Co-authored-by: Calypso Bot Co-authored-by: Renovate Bot Co-authored-by: Brad Jorsch Co-authored-by: Chris McCluskey Co-authored-by: tbradsha <32492176+tbradsha@users.noreply.github.com> Co-authored-by: Christian Gastrell Co-authored-by: MILLER/F Co-authored-by: Miguel Lezama Co-authored-by: Adnan Haque <3737780+haqadn@users.noreply.github.com> Co-authored-by: Mark George Co-authored-by: Peter Petrov Co-authored-by: Jeremy Herve Co-authored-by: Manzoor Wani Co-authored-by: Gergely Juhasz Co-authored-by: Griffith Chen Co-authored-by: Brad Jorsch Co-authored-by: Christopher Smith <8002138+chrisfromthelc@users.noreply.github.com> Co-authored-by: Damián Suárez Co-authored-by: thingalon Co-authored-by: Fabien MILLERAND Co-authored-by: Piotr Stankowski <6437642+trakos@users.noreply.github.com> --- .github/workflows/build.yml | 29 +- docs/development-environment.md | 9 + docs/quick-start.md | 74 +- pnpm-lock.yaml | 1901 ++++++----------- projects/js-packages/ai-client/CHANGELOG.md | 6 + projects/js-packages/ai-client/package.json | 8 +- .../src/components/ai-control/Readme.md | 8 +- .../src/components/ai-control/index.tsx | 275 ++- .../src/components/ai-control/style.scss | 115 +- .../components/ai-status-indicator/index.tsx | 13 +- .../components/ai-status-indicator/style.scss | 57 +- .../ai-client/src/components/index.ts | 2 +- projects/js-packages/components/CHANGELOG.md | 5 + .../components/toggle-control/index.tsx | 6 + .../toggle-control/stories/index.stories.tsx | 20 + .../toggle-control/styles.module.scss | 25 +- projects/js-packages/components/package.json | 12 +- projects/js-packages/connection/CHANGELOG.md | 5 + projects/js-packages/connection/package.json | 8 +- projects/js-packages/licensing/CHANGELOG.md | 4 + projects/js-packages/licensing/package.json | 6 +- .../js-packages/partner-coupon/CHANGELOG.md | 4 + .../js-packages/partner-coupon/package.json | 8 +- .../publicize-components/CHANGELOG.md | 9 + .../publicize-components/package.json | 6 +- .../form/auto-conversion-notice.tsx | 2 + .../src/components/form/index.js | 1 + .../src/components/form/validation-notice.tsx | 4 +- .../selectors/auto-conversion-settings.js | 3 +- .../shared-extension-utils/CHANGELOG.md | 5 + .../shared-extension-utils/package.json | 6 +- .../changelog/renovate-storybook-monorepo#4} | 3 +- projects/js-packages/storybook/package.json | 28 +- projects/packages/backup/CHANGELOG.md | 5 + projects/packages/backup/package.json | 4 +- .../backup/src/class-package-version.php | 2 +- projects/packages/forms/CHANGELOG.md | 20 + .../add-contact-form-accessible-name | 4 + .../changelog/boost-fix-importmap-deferral | 5 + .../changelog/fix-contact-form-input-stacking | 4 - .../fix-contact-form-required-checkbox | 4 - .../update-contact-form-error-message | 4 - .../update-forms-lead-capture-atomic | 4 - projects/packages/forms/composer.json | 2 +- projects/packages/forms/package.json | 2 +- .../components/jetpack-field-controls.js | 74 +- .../jetpack-manage-responses-settings.js | 17 +- .../forms/src/blocks/contact-form/edit.js | 19 +- .../hooks/use-form-accessible-name.js | 53 + .../forms/src/class-jetpack-forms.php | 2 +- .../forms/src/contact-form/class-admin.php | 2 +- .../contact-form/class-contact-form-field.php | 2 +- .../class-contact-form-plugin.php | 2 +- .../src/contact-form/class-contact-form.php | 6 +- .../src/contact-form/class-editor-view.php | 8 +- .../tools/webpack.config.contact-form.js | 71 +- .../packages/jetpack-mu-wpcom/CHANGELOG.md | 5 + .../packages/jetpack-mu-wpcom/composer.json | 2 +- .../packages/jetpack-mu-wpcom/package.json | 2 +- .../src/class-jetpack-mu-wpcom.php | 2 +- .../launchpad/launchpad-task-definitions.php | 3 +- projects/packages/my-jetpack/CHANGELOG.md | 5 + projects/packages/my-jetpack/package.json | 8 +- .../my-jetpack/src/class-initializer.php | 2 +- projects/packages/publicize/CHANGELOG.md | 10 + projects/packages/publicize/package.json | 2 +- .../class-rest-settings-controller.php | 136 ++ .../class-settings.php | 76 + .../publicize/src/class-publicize-setup.php | 4 + .../class-settings.php | 4 +- .../class-rest-settings-controller.php | 142 ++ .../social-image-generator/class-settings.php | 102 + .../social-image-generator/class-setup.php | 4 + projects/packages/search/CHANGELOG.md | 5 + projects/packages/search/package.json | 6 +- .../packages/search/src/class-package.php | 2 +- .../packages/stats/changelog/add-utm-tracking | 4 + .../stats/src/class-tracking-pixel.php | 42 +- .../stats/tests/php/test-tracking-pixel.php | 41 +- projects/packages/sync/CHANGELOG.md | 8 + projects/packages/sync/composer.json | 2 +- projects/packages/sync/src/class-defaults.php | 1 + .../sync/src/class-package-version.php | 2 +- .../packages/sync/src/modules/class-posts.php | 3 + projects/packages/videopress/CHANGELOG.md | 8 + projects/packages/videopress/package.json | 14 +- .../videopress/src/class-access-control.php | 9 +- .../videopress/src/class-package-version.php | 2 +- projects/packages/wordads/CHANGELOG.md | 5 + projects/packages/wordads/package.json | 6 +- .../packages/wordads/src/class-package.php | 2 +- ...om_ai_site_prompt-option-settings-endpoint | 5 + projects/plugins/backup/composer.json | 2 +- projects/plugins/backup/composer.lock | 4 +- projects/plugins/backup/jetpack-backup.php | 2 +- projects/plugins/boost/CHANGELOG.md | 9 +- .../plugins/boost/app/admin/class-admin.php | 2 - .../plugins/boost/app/admin/class-config.php | 29 +- .../boost/app/assets/src/css/admin-style.scss | 1 - .../assets/src/css/components/connection.scss | 4 + .../src/css/components/critical-css.scss | 26 - .../app/assets/src/css/main/dashboard.scss | 3 - .../boost/app/assets/src/js/Main.svelte | 104 +- .../assets/src/js/features/ErrorNotice.svelte | 98 - .../app/assets/src/js/features/Module.svelte | 78 - .../app/assets/src/js/features/Notice.svelte | 54 - .../js/features/ResizingUnavailable.svelte | 34 - .../assets/src/js/features/UpgradeCTA.svelte | 45 - .../boost-pricing-table.tsx | 29 +- .../critical-css-meta/critical-css-meta.tsx | 6 +- .../src/js/features/critical-css/index.ts | 1 + .../lib/stores/critical-css-state.ts | 2 + .../show-stopper-error/show-stopper-error.tsx | 1 + .../features/critical-css/status/status.tsx | 8 +- .../error-notice/error-notice.module.scss | 87 +- .../js/features/error-notice/error-notice.tsx | 12 +- .../stories/error-notice.stories.tsx | 4 +- .../quality-settings/quality-settings.tsx | 14 +- .../recommendations-meta.tsx | 7 + .../js/features/minify-meta/minify-meta.tsx | 12 +- .../src/js/features/module/lib/stores.ts | 50 + .../src/js/features/module/module.module.scss | 32 + .../assets/src/js/features/module/module.tsx | 78 + .../performance-history.tsx | 20 +- .../premium-tooltip/premium-tooltip.tsx | 4 +- .../features/speed-score/pop-out/pop-out.tsx | 20 +- .../js/features/speed-score/speed-score.tsx | 36 +- .../super-cache-info/super-cache-info.tsx | 10 +- .../features/ui/back-button/back-button.tsx | 3 +- .../ui/navigation-link/navigation-link.tsx | 24 - .../upgrade-cta/upgrade-cta.module.scss | 27 + .../js/features/upgrade-cta/upgrade-cta.tsx | 53 + .../boost/app/assets/src/js/global.d.ts | 10 - .../layout/SettingsPage/SettingsPage.svelte | 53 - .../src/js/layout/SettingsPage/Tips.svelte | 45 - .../assets/src/js/layout/header/header.tsx | 3 +- .../settings-page/settings-page.module.scss | 3 + .../js/layout/settings-page/settings-page.tsx | 57 + .../support/support.module.scss | 0 .../support/support.tsx | 6 +- .../settings-page/tips/tips.module.scss} | 17 +- .../src/js/layout/settings-page/tips/tips.tsx | 53 + .../app/assets/src/js/lib/stores/config-ds.ts | 32 + .../assets/src/js/lib/stores/connection.ts | 56 +- .../src/js/lib/stores/getting-started.ts | 15 + .../app/assets/src/js/lib/stores/minify.ts | 13 - .../app/assets/src/js/lib/stores/modules.ts | 1 - .../app/assets/src/js/lib/utils/analytics.ts | 6 +- .../src/js/lib/utils/enable-cloud-css.ts | 8 - .../app/assets/src/js/lib/utils/navigate.ts | 3 - .../app/assets/src/js/lib/utils/paid-plan.ts | 18 - .../plugins/boost/app/assets/src/js/main.tsx | 155 ++ .../critical-css-advanced.tsx | 9 - .../pages/getting-started/getting-started.tsx | 74 +- .../assets/src/js/pages/index/Index.svelte | 371 ---- .../src/js/pages/index/index.module.scss | 14 + .../app/assets/src/js/pages/index/index.tsx | 393 ++++ .../assets/src/js/pages/index/lib/hooks.ts | 29 + .../purchase-success/purchase-success.tsx | 23 +- .../assets/src/js/pages/upgrade/upgrade.tsx | 28 +- .../app/assets/src/js/svg/right-arrow.svg | 3 - .../app/assets/src/js/svg/right-arrow.tsx | 7 + .../plugins/boost/app/class-jetpack-boost.php | 12 +- .../app/data-sync/Getting_Started_Entry.php | 44 + .../features/setup-prompt/Setup_Prompt.php | 4 +- .../plugins/boost/app/lib/Premium_Pricing.php | 21 +- projects/plugins/boost/app/lib/class-cli.php | 4 +- .../boost/app/lib/class-connection.php | 20 +- .../class-render-blocking-js.php | 5 +- .../plugins/boost/changelog/boost-react-main | 5 + .../boost/changelog/boost-react-module | 5 + .../changelog/migrate-settings-page-tips | 5 + .../changelog/renovate-storybook-monorepo | 4 + .../update-boost-react-settings-page | 5 + projects/plugins/boost/package.json | 3 +- projects/plugins/boost/readme.txt | 16 +- .../lib/pages/wp-admin/JetpackBoostPage.js | 10 +- projects/plugins/boost/tsconfig.json | 2 +- projects/plugins/boost/wp-js-data-sync.php | 14 + projects/plugins/crm/CHANGELOG.md | 8 + projects/plugins/crm/ZeroBSCRM.php | 2 +- .../crm/admin/settings/client-portal.page.php | 16 +- .../plugins/crm/admin/settings/forms.page.php | 2 +- .../crm/admin/settings/general.page.php | 21 +- .../admin/settings/partials/menu.block.php | 2 +- .../plugins/crm/changelog/init-release-cycle | 2 +- projects/plugins/crm/composer.json | 2 +- .../plugins/crm/includes/ZeroBSCRM.AJAX.php | 6 +- .../plugins/crm/includes/ZeroBSCRM.Core.php | 3 +- .../crm/includes/ZeroBSCRM.Permissions.php | 3 +- .../mailpoet/admin/settings/main.page.php | 22 +- .../woo-sync/admin/settings/main.page.php | 9 +- projects/plugins/crm/package.json | 6 +- projects/plugins/crm/readme.txt | 16 +- projects/plugins/jetpack/CHANGELOG.md | 39 + .../_inc/client/at-a-glance/videopress.jsx | 5 +- .../_inc/client/my-plan/my-plan-body.jsx | 140 +- .../client/my-plan/my-plan-card/index.jsx | 2 +- .../client/my-plan/my-plan-header/index.js | 11 +- .../lib/class-jetpack-recommendations.php | 2 +- ...tomic => add-contact-form-accessible-name} | 0 .../changelog/add-dont-email-to-subs-toggle | 4 - .../changelog/add-fix-typo} | 2 +- .../changelog/add-flag-for-expired-plans | 4 - .../add-stats-passing-utm-parameters | 5 + .../changelog/boost-fix-importmap-deferral | 5 + .../jetpack/changelog/fix-admin-plan-icon-alt | 4 + .../fix-correct-subs-count-with-paywall | 4 - .../changelog/fix-like-block-disabled-case | 4 - .../jetpack/changelog/init-release-cycle | 2 +- .../refactor-memberships-checkout-modal | 4 - .../remove-like-block-special-treatment | 4 - ...e-newsletter-post-publish-initially-closed | 4 - .../plugins/jetpack/class.jetpack-admin.php | 2 +- projects/plugins/jetpack/composer.json | 2 +- projects/plugins/jetpack/composer.lock | 8 +- .../extensions/blocks/ai-assistant/block.json | 8 + .../components/toolbar-controls/index.js | 4 +- .../extensions/blocks/ai-assistant/edit.js | 56 +- .../components/ai-assistant-bar/index.tsx | 72 +- .../components/ai-assistant-bar/style.scss | 19 +- .../ai-assistant-toolbar-button/index.tsx | 5 +- .../use-suggestions-from-openai/index.js | 27 +- .../jetpack/extensions/blocks/like/like.php | 83 +- .../premium-content/_inc/access-check.php | 4 +- ...s-abstract-token-subscription-service.php} | 10 +- ...ass-jetpack-token-subscription-service.php | 8 +- .../class-token-subscription.php | 23 - ...lass-unconfigured-subscription-service.php | 7 +- ...lass-wpcom-online-subscription-service.php | 10 +- .../_inc/subscription-service/include.php | 5 +- ...php => interface-subscription-service.php} | 10 +- .../login-button/login-button.php | 4 +- .../blocks/sharing-button/sharing-button.php | 19 +- .../extensions/blocks/sharing-buttons/save.js | 3 +- .../extensions/blocks/sharing-buttons/view.js | 76 +- .../extensions/blocks/subscriptions/panel.js | 2 +- .../blocks/subscriptions/subscriptions.php | 31 +- .../plugins/jetpack/extensions/index.json | 4 +- .../extensions/shared/memberships/settings.js | 20 +- .../memberships/subscribers-affirmation.js | 57 +- projects/plugins/jetpack/jetpack.php | 4 +- ....wpcom-json-api-site-settings-endpoint.php | 1 + ...m-json-api-site-settings-v1-4-endpoint.php | 1 + .../modules/carousel/jetpack-carousel.js | 26 +- .../class-jetpack-google-font-face.php | 4 +- .../current/load-google-fonts.php | 31 +- .../memberships/class-jetpack-memberships.php | 49 +- .../modules/sharedaddy/admin-sharing.css | 21 +- .../modules/sharedaddy/admin-sharing.js | 15 +- .../sharedaddy/images/smart-twitter.png | Bin 1952 -> 0 bytes .../sharedaddy/images/smart-twitter@2x.png | Bin 1691 -> 0 bytes .../modules/sharedaddy/images/smart-x.png | Bin 0 -> 1365 bytes .../modules/sharedaddy/images/smart-x@2x.png | Bin 0 -> 3170 bytes .../modules/sharedaddy/sharing-sources.php | 81 +- .../jetpack/modules/sharedaddy/sharing.css | 3 +- .../jetpack/modules/sharedaddy/sharing.php | 136 +- .../class-jetpack-subscribe-modal.php | 4 +- projects/plugins/jetpack/package.json | 6 +- projects/plugins/jetpack/readme.txt | 69 +- .../test_class.jetpack-subscriptions.php | 4 +- .../sync/test_class.jetpack-sync-options.php | 1 + projects/plugins/jetpack/to-test.md | 117 +- ...om_ai_site_prompt-option-settings-endpoint | 5 + projects/plugins/migration/composer.lock | 4 +- projects/plugins/mu-wpcom-plugin/CHANGELOG.md | 8 + .../plugins/mu-wpcom-plugin/composer.json | 2 +- .../plugins/mu-wpcom-plugin/composer.lock | 4 +- .../mu-wpcom-plugin/mu-wpcom-plugin.php | 2 +- projects/plugins/mu-wpcom-plugin/package.json | 2 +- ...om_ai_site_prompt-option-settings-endpoint | 5 + projects/plugins/protect/composer.lock | 4 +- .../add-stats-passing-utm-parameters | 5 + ...om_ai_site_prompt-option-settings-endpoint | 5 + projects/plugins/search/composer.lock | 4 +- ...om_ai_site_prompt-option-settings-endpoint | 5 + .../renovate-major-js-unit-testing-packages | 4 + projects/plugins/social/composer.lock | 4 +- projects/plugins/social/package.json | 4 +- ...om_ai_site_prompt-option-settings-endpoint | 5 + .../renovate-major-js-unit-testing-packages | 4 + projects/plugins/starter-plugin/composer.lock | 4 +- projects/plugins/starter-plugin/package.json | 4 +- ...om_ai_site_prompt-option-settings-endpoint | 5 + projects/plugins/videopress/composer.lock | 4 +- tools/cli/package.json | 2 +- .../jetpack-live-branches.user.js | 8 +- tools/js-tools/package.json | 2 +- tools/release-plugin.sh | 28 +- 289 files changed, 4278 insertions(+), 3750 deletions(-) rename projects/{plugins/boost/changelog/init-release-cycle => js-packages/storybook/changelog/renovate-storybook-monorepo#4} (53%) create mode 100644 projects/packages/forms/changelog/add-contact-form-accessible-name create mode 100644 projects/packages/forms/changelog/boost-fix-importmap-deferral delete mode 100644 projects/packages/forms/changelog/fix-contact-form-input-stacking delete mode 100644 projects/packages/forms/changelog/fix-contact-form-required-checkbox delete mode 100644 projects/packages/forms/changelog/update-contact-form-error-message delete mode 100644 projects/packages/forms/changelog/update-forms-lead-capture-atomic create mode 100644 projects/packages/forms/src/blocks/contact-form/hooks/use-form-accessible-name.js create mode 100644 projects/packages/publicize/src/auto-conversion-settings/class-rest-settings-controller.php create mode 100644 projects/packages/publicize/src/auto-conversion-settings/class-settings.php create mode 100644 projects/packages/publicize/src/social-image-generator/class-rest-settings-controller.php create mode 100644 projects/packages/publicize/src/social-image-generator/class-settings.php create mode 100644 projects/packages/stats/changelog/add-utm-tracking create mode 100644 projects/plugins/backup/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint delete mode 100644 projects/plugins/boost/app/assets/src/js/features/ErrorNotice.svelte delete mode 100644 projects/plugins/boost/app/assets/src/js/features/Module.svelte delete mode 100644 projects/plugins/boost/app/assets/src/js/features/Notice.svelte delete mode 100644 projects/plugins/boost/app/assets/src/js/features/ResizingUnavailable.svelte delete mode 100644 projects/plugins/boost/app/assets/src/js/features/UpgradeCTA.svelte create mode 100644 projects/plugins/boost/app/assets/src/js/features/image-size-analysis/recommendations-meta/recommendations-meta.tsx create mode 100644 projects/plugins/boost/app/assets/src/js/features/module/lib/stores.ts create mode 100644 projects/plugins/boost/app/assets/src/js/features/module/module.module.scss create mode 100644 projects/plugins/boost/app/assets/src/js/features/module/module.tsx delete mode 100644 projects/plugins/boost/app/assets/src/js/features/ui/navigation-link/navigation-link.tsx create mode 100644 projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.module.scss create mode 100644 projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.tsx delete mode 100644 projects/plugins/boost/app/assets/src/js/layout/SettingsPage/SettingsPage.svelte delete mode 100644 projects/plugins/boost/app/assets/src/js/layout/SettingsPage/Tips.svelte create mode 100644 projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.module.scss create mode 100644 projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.tsx rename projects/plugins/boost/app/assets/src/js/layout/{SettingsPage => settings-page}/support/support.module.scss (100%) rename projects/plugins/boost/app/assets/src/js/layout/{SettingsPage => settings-page}/support/support.tsx (84%) rename projects/plugins/boost/app/assets/src/{css/components/benchmarks.scss => js/layout/settings-page/tips/tips.module.scss} (78%) create mode 100644 projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.tsx create mode 100644 projects/plugins/boost/app/assets/src/js/lib/stores/config-ds.ts create mode 100644 projects/plugins/boost/app/assets/src/js/lib/stores/getting-started.ts delete mode 100644 projects/plugins/boost/app/assets/src/js/lib/utils/enable-cloud-css.ts delete mode 100644 projects/plugins/boost/app/assets/src/js/lib/utils/navigate.ts delete mode 100644 projects/plugins/boost/app/assets/src/js/lib/utils/paid-plan.ts create mode 100644 projects/plugins/boost/app/assets/src/js/main.tsx delete mode 100644 projects/plugins/boost/app/assets/src/js/pages/index/Index.svelte create mode 100644 projects/plugins/boost/app/assets/src/js/pages/index/index.module.scss create mode 100644 projects/plugins/boost/app/assets/src/js/pages/index/index.tsx create mode 100644 projects/plugins/boost/app/assets/src/js/pages/index/lib/hooks.ts delete mode 100644 projects/plugins/boost/app/assets/src/js/svg/right-arrow.svg create mode 100644 projects/plugins/boost/app/assets/src/js/svg/right-arrow.tsx create mode 100644 projects/plugins/boost/app/data-sync/Getting_Started_Entry.php create mode 100644 projects/plugins/boost/changelog/boost-react-main create mode 100644 projects/plugins/boost/changelog/boost-react-module create mode 100644 projects/plugins/boost/changelog/migrate-settings-page-tips create mode 100644 projects/plugins/boost/changelog/renovate-storybook-monorepo create mode 100644 projects/plugins/boost/changelog/update-boost-react-settings-page rename projects/plugins/jetpack/changelog/{update-forms-lead-capture-atomic => add-contact-form-accessible-name} (100%) delete mode 100644 projects/plugins/jetpack/changelog/add-dont-email-to-subs-toggle rename projects/plugins/{boost/changelog/fix-z-index => jetpack/changelog/add-fix-typo} (64%) delete mode 100644 projects/plugins/jetpack/changelog/add-flag-for-expired-plans create mode 100644 projects/plugins/jetpack/changelog/add-stats-passing-utm-parameters create mode 100644 projects/plugins/jetpack/changelog/boost-fix-importmap-deferral create mode 100644 projects/plugins/jetpack/changelog/fix-admin-plan-icon-alt delete mode 100644 projects/plugins/jetpack/changelog/fix-correct-subs-count-with-paywall delete mode 100644 projects/plugins/jetpack/changelog/fix-like-block-disabled-case delete mode 100644 projects/plugins/jetpack/changelog/refactor-memberships-checkout-modal delete mode 100644 projects/plugins/jetpack/changelog/remove-like-block-special-treatment delete mode 100644 projects/plugins/jetpack/changelog/update-newsletter-post-publish-initially-closed rename projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/{class-token-subscription-service.php => class-abstract-token-subscription-service.php} (98%) delete mode 100644 projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription.php rename projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/{class-subscription-service.php => interface-subscription-service.php} (91%) delete mode 100644 projects/plugins/jetpack/modules/sharedaddy/images/smart-twitter.png delete mode 100644 projects/plugins/jetpack/modules/sharedaddy/images/smart-twitter@2x.png create mode 100644 projects/plugins/jetpack/modules/sharedaddy/images/smart-x.png create mode 100644 projects/plugins/jetpack/modules/sharedaddy/images/smart-x@2x.png create mode 100644 projects/plugins/migration/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint create mode 100644 projects/plugins/protect/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint create mode 100644 projects/plugins/search/changelog/add-stats-passing-utm-parameters create mode 100644 projects/plugins/search/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint create mode 100644 projects/plugins/social/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint create mode 100644 projects/plugins/social/changelog/renovate-major-js-unit-testing-packages create mode 100644 projects/plugins/starter-plugin/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint create mode 100644 projects/plugins/starter-plugin/changelog/renovate-major-js-unit-testing-packages create mode 100644 projects/plugins/videopress/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 89021351b1065..b8bc9a90aea12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -198,7 +198,7 @@ jobs: name: Create artifact for Jetpack Beta plugin runs-on: ubuntu-latest needs: build - if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'Automattic/jetpack' ) && needs.build.outputs.any_plugins == 'true' + if: needs.build.outputs.any_plugins == 'true' timeout-minutes: 10 # 2021-06-24: Successful runs should take just a few seconds now. But sometimes the upload is slow. steps: - uses: actions/checkout@v3 @@ -224,8 +224,7 @@ jobs: # Assume GH run IDs are monotonic. VERSUFFIX="${GITHUB_RUN_ID}-g${SHA:0:8}" - # Plugin data is passed as a JSON object. - PLUGIN_DATA="{}" + ANY_BUILT=false while IFS=$'\t' read -r SRC MIRROR SLUG; do echo "::group::$MIRROR (src=$SRC slug=$SLUG)" @@ -263,40 +262,24 @@ jobs: # Zip the plugin ( cd work && zip -9 -r "../zips/${SLUG}-dev.zip" "${SLUG}-dev" ) - # Record plugin data. - PLUGIN_DATA=$( jq -c --arg slug "$SLUG" --arg ver "$CURRENT_VERSION" '.[ $slug ] = { version: $ver }' <<<"$PLUGIN_DATA" ) + ANY_BUILT=true echo "::endgroup::" done < build/plugins.tsv - if [[ "$PLUGIN_DATA" == "{}" ]]; then + if ! $ANY_BUILT; then echo "No plugins were built" fi - echo "plugin-data=$PLUGIN_DATA" >> "$GITHUB_OUTPUT" + echo "any-built=$ANY_BUILT" >> "$GITHUB_OUTPUT" - name: Create plugins artifact uses: actions/upload-artifact@v3 - if: steps.prepare.outputs.plugin-data != '{}' + if: steps.prepare.outputs.any-built == 'true' with: name: plugins path: zips # Only need to retain for a day since the beta builder slurps it up to distribute. retention-days: 1 - - name: Inform Beta Download webhook - if: steps.prepare.outputs.plugin-data != '{}' - env: - SECRET: ${{ secrets.JPBETA_SECRET }} - PLUGIN_DATA: ${{ steps.prepare.outputs.plugin-data }} - PR: ${{ github.event.number }} - SHA: ${{ github.event.pull_request.head.sha || github.sha }} - run: | - curl -v --fail -L \ - --url "https://betadownload.jetpack.me/gh-action.php?run_id=$GITHUB_RUN_ID&pr=$PR&commit=$SHA" \ - --form-string "repo=$GITHUB_REPOSITORY" \ - --form-string "branch=${GITHUB_REF#refs/heads/}" \ - --form-string "plugins=$PLUGIN_DATA" \ - --form-string "secret=$SECRET" - update_mirrors: name: Push to mirror repos runs-on: ubuntu-latest diff --git a/docs/development-environment.md b/docs/development-environment.md index 3930888f39120..4ec862476f509 100644 --- a/docs/development-environment.md +++ b/docs/development-environment.md @@ -18,6 +18,7 @@ - [Composer](#composer) - [jetpack CLI](#jetpack-cli) - [Check if your environment is ready for Jetpack development](#check-if-your-environment-is-ready-for-jetpack-development) + - [Testing Jetpack cloud features](#testing-jetpack-cloud-features) - [Development workflow](#development-workflow) - [Building your project](#building-your-project) - [Syncing local changes with Unison](#syncing-local-changes-with-unison) @@ -165,6 +166,14 @@ Once you're all set here, you can continue developing. If you're setting up an l `jetpack build` will provide prompts to determine the project you need or you can pass it a complete command, like `jetpack build plugins/jetpack --with-deps` +### Testing Jetpack cloud features + +In order to test features that require a WordPress.com connection and other network related Jetpack features, you'll need a test site that can create local HTTP tunnels. + +If you're an Automattician, we recommend using [Jurassic Tube](./quick-start.md#setting-up-jurassic-tube). + +For other methods, check out [ngrok](../tools/docker/README.md#using-ngrok-with-jetpack) or [another similar service](https://alternativeto.net/software/ngrok/). + # Development workflow Once you have a local copy of Jetpack and all development tools installed, you can start developing. diff --git a/docs/quick-start.md b/docs/quick-start.md index 54e31671c82af..281da4710e742 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -4,19 +4,23 @@ This guide is designed to get you up and running working with the Jetpack Monorepo quickly following recommended and supported guidelines. -This guide assumes you are using MacOS or a Linux machine and are an Automattician. For more detailed information, including alternate local dev environments, running unit tests, best coding practices, and more, you can use the [full Development Environment guide here](development-environment.md#clone-the-repository). +**This guide assumes you are using MacOS or a Linux machine and are an Automattician**. For more detailed information, including setting up local dev environments for all contributors, running unit tests, best coding practices, and more, you can use the [full Development Environment guide here](development-environment.md#clone-the-repository). ## Installation ### Using the installation script To speed up the installation process, you may use our monorepo installation script. To do so: - - clone the Jetpack repo using one of these two methods: - - A public SSH key ([recommended](https://github.com/Automattic/jetpack/blob/trunk/docs/development-environment.md#clone-the-repository)): `git clone git@github.com:Automattic/jetpack.git` - - HTTPS: `git clone https://github.com/Automattic/jetpack.git` - - `cd` into the cloned `jetpack` folder. - - run `tools/install-monorepo.sh` from the monorepo root. - Once the installation is complete, continue onto the section [Running Jetpack locally](#running-jetpack-locally). + +- Clone the Jetpack Monorepo: + - Using a public SSH key ([recommended](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)): `git clone git@github.com:Automattic/jetpack.git` + - Or use HTTPS: `git clone https://github.com/Automattic/jetpack.git` + - Note that the monorepo should not be cloned into the WordPress plugins directory. If you plan on not using the provided Docker environment, read the [full Development Environment guide here](development-environment.md#clone-the-repository) to find out how to add symlinks. +- `cd` into the cloned `jetpack` folder. +- Run `tools/install-monorepo.sh` from the monorepo root. +- You can use the [environment checker script](#check-if-your-environment-is-ready-for-jetpack-development) to confirm that all required tools are installed. + +Once the installation is complete, continue onto the section [Running Jetpack locally](#running-jetpack-locally). ### Installing manually @@ -26,11 +30,11 @@ Prior to installation, we recommend using [`Homebrew`](https://brew.sh/) to mana - nvm: `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash` The Jetpack Monorepo requires various software to be installed on your machine. -- Start by cloning the GitHub repo using one of these two methods: - - A public SSH key ([recommended](https://github.com/Automattic/jetpack/blob/trunk/docs/development-environment.md#clone-the-repository)): `git clone git@github.com:Automattic/Jetpack.git` - - HTTPS: `git clone https://github.com/Automattic/jetpack.git` - - If you're not an Automattician, you can [fork the repo following the instructions here](https://docs.github.com/en/get-started/quickstart/contributing-to-projects). - - Note that the Monorepo should not be cloned into the WordPress plugins directory (you will see a warning on your plugins page in that case saying that the Jetpack Monorepo is not a plugin and shouldn't be installed as one). If you are not cloning into a Docker environment, read the [full Development Environment guide here](development-environment.md#clone-the-repository) to find out how to add symlinks. + +- Clone the Jetpack Monorepo: + - Using a public SSH key ([recommended](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)): `git clone git@github.com:Automattic/jetpack.git` + - Or use HTTPS: `git clone https://github.com/Automattic/jetpack.git` + - Note that the monorepo should not be cloned into the WordPress plugins directory. If you plan on not using the provided Docker environment, read the [full Development Environment guide here](development-environment.md#clone-the-repository) to find out how to add symlinks. - This software needs to be installed or updated system-wide: - Bash (will need to be updated from default Mac version): `brew install bash` - jq (JSON processor used in scripts): `brew install jq` @@ -42,6 +46,20 @@ The Jetpack Monorepo requires various software to be installed on your machine. - Jetpack CLI (an internal tool that assists with development): `pnpm install && pnpm jetpack cli link` - [You can read more about using the CLI here](https://github.com/Automattic/jetpack/blob/trunk/tools/cli/README.md). +### Check if your environment is ready for Jetpack development + +We provide a script to help you in assessing if everything's ready on your system to contribute to Jetpack. + +```sh +tools/check-development-environment.sh +``` + +Running the script will tell you if you have your environment already set up and what you need to do in order to get it ready for Jetpack development: + +- All green `YES` or `OK` messages mean you're ready to start +- Red `NO` messages mean something is wrong or missing, and a link will be provided to help you with a fix. +- Yellow messages indicate something optional is broken or missing. + ## Running Jetpack locally After everything is installed, you're ready to run Jetpack locally! While there are other supported methods of doing this, we recommend and support using Docker containers. @@ -60,9 +78,11 @@ To setup Docker: For more in depth Docker instructions, follow the [Docker environment for Jetpack Development guide](../tools/docker/README.md). -### Setting up Jurassic Tube +## Setting up Jurassic Tube -In order to test features that require a WordPress.com connection and other network related Jetpack features, you'll need a test site that can create local HTTP tunnels. If you're an Automattician, we recommend using Jurassic Tube: +In order to test features that require a WordPress.com connection and other network related Jetpack features, you'll need a test site that can create local HTTP tunnels. If you're an Automattician, we recommend using Jurassic Tube. + +Note: This is for Automattician use only. For other methods, check out [ngrok](../tools/docker/README.md#using-ngrok-with-jetpack) or [another similar service](https://alternativeto.net/software/ngrok/). **Warning: This creates a tunnel to your local machine which should not be trusted as secure. If it is compromised, so is your computer and everything it has access to. Only `jetpack docker jt-up` when needed for testing things that require the site to be publicly accessible, and `jetpack docker jt-down` when completed.** @@ -77,27 +97,7 @@ In order to test features that require a WordPress.com connection and other netw - Now, you can start your site with `jetpack docker jt-up` - Your site should be available at `https://custom-subdomain.jurassic.tube` -Note: This is for Automattician use only. For other methods, check out [ngrok](https://github.com/Automattic/jetpack/blob/trunk/tools/docker/README.md#using-ngrok-with-jetpack) or [another similar service](https://alternativeto.net/software/ngrok/). - -### Check if your environment is ready for Jetpack development - -We provide a script to help you in assessing if everything's ready on your system to contribute to Jetpack. - -```sh -tools/check-development-environment.sh -``` - -Running the script will tell you if you have your environment already set up and what you need to do in order to get it ready for Jetpack development: - -- All green `YES` or `OK` messages mean you're ready to start -- Red `NO` messages mean something is wrong or missing, and a link will be provided to help you with a fix. -- Yellow messages indicate something optional is broken or missing. - -#### Running Tests - -To run PHP and JS tests, you can use the Jetpack CLI: `jetpack test` and then choose the project and type of test you'd like to run. - -# Development Workflow +## Development Workflow Once you have a local copy of Jetpack and all development tools installed, you can start developing. @@ -110,6 +110,8 @@ By default the development build above will run once and if you change any of th ```sh jetpack watch ``` +### Running Tests -That's all! +To run PHP and JS tests, you can use the Jetpack CLI: `jetpack test` and then choose the project and type of test you'd like to run. +That's all! diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8623a70b77e8..c831fb14be29d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -151,14 +151,14 @@ importers: version: 18.2.0(react@18.2.0) devDependencies: '@storybook/addon-actions': - specifier: 7.4.6 - version: 7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@storybook/blocks': - specifier: 7.4.6 - version: 7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) '@storybook/react': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) jest: specifier: ^29.6.2 version: 29.7.0 @@ -266,7 +266,7 @@ importers: version: link:../boost-score-api '@babel/runtime': specifier: ^7 - version: 7.23.2 + version: 7.23.5 '@wordpress/browserslist-config': specifier: 5.30.0 version: 5.30.0 @@ -302,7 +302,7 @@ importers: version: 3.1.0(react@18.2.0) react-slider: specifier: 2.0.5 - version: 2.0.5(@babel/runtime@7.23.2)(react@18.2.0) + version: 2.0.5(@babel/runtime@7.23.5)(react@18.2.0) social-logos: specifier: 2.5.6 version: 2.5.6(react@18.2.0) @@ -326,23 +326,23 @@ importers: specifier: 29.4.3 version: 29.4.3 '@storybook/addon-actions': - specifier: 7.4.6 - version: 7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@storybook/blocks': - specifier: 7.4.6 - version: 7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) '@storybook/react': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) '@types/jest': specifier: 29.5.10 version: 29.5.10 @@ -462,17 +462,17 @@ importers: specifier: 7.23.3 version: 7.23.3(@babel/core@7.23.5) '@storybook/addon-actions': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) jest: specifier: 29.7.0 version: 29.7.0 @@ -696,14 +696,14 @@ importers: specifier: 7.23.3 version: 7.23.3(@babel/core@7.23.5) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) jest: specifier: 29.7.0 version: 29.7.0 @@ -751,14 +751,14 @@ importers: specifier: 7.23.3 version: 7.23.3(@babel/core@7.23.5) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) '@wordpress/base-styles': specifier: 4.38.0 version: 4.38.0 @@ -772,8 +772,8 @@ importers: specifier: 29.7.0 version: 29.7.0 jest-extended: - specifier: 2.0.0 - version: 2.0.0(jest@29.7.0) + specifier: 4.0.2 + version: 4.0.2(jest@29.7.0) react: specifier: 18.2.0 version: 18.2.0 @@ -881,14 +881,14 @@ importers: specifier: 7.23.5 version: 7.23.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) '@types/jest': specifier: 29.5.10 version: 29.5.10 @@ -1015,14 +1015,14 @@ importers: specifier: 7.23.3 version: 7.23.3(@babel/core@7.23.5) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) '@wordpress/babel-plugin-import-jsx-pragma': specifier: 4.30.0 version: 4.30.0(@babel/core@7.23.5) @@ -1070,44 +1070,44 @@ importers: specifier: 7.23.5 version: 7.23.5 '@storybook/addon-a11y': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@storybook/addon-docs': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/addon-essentials': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/addon-storysource': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@storybook/addons': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/api': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/blocks': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/components': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/manager-api': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@storybook/react': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) '@storybook/react-webpack5': - specifier: 7.4.6 - version: 7.4.6(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1) + specifier: 7.6.5 + version: 7.6.5(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1) '@storybook/source-loader': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@storybook/theming': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0) '@wordpress/babel-preset-default': specifier: 7.31.0 version: 7.31.0 @@ -1178,8 +1178,8 @@ importers: specifier: 12.4.0 version: 12.4.0(sass@1.64.1)(webpack@5.76.0) storybook: - specifier: 7.4.6 - version: 7.4.6 + specifier: 7.6.5 + version: 7.6.5 storybook-addon-mock: specifier: 4.3.0 version: 4.3.0(react-dom@18.2.0)(react@18.2.0) @@ -1455,14 +1455,14 @@ importers: specifier: 7.23.5 version: 7.23.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) '@wordpress/browserslist-config': specifier: 5.30.0 version: 5.30.0 @@ -1929,17 +1929,17 @@ importers: specifier: 7.23.5 version: 7.23.5(@babel/core@7.23.5) '@storybook/react': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) jest: specifier: 29.7.0 version: 29.7.0 @@ -2137,14 +2137,14 @@ importers: specifier: 8.2.6 version: 8.2.6(size-limit@8.2.6) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/preact': specifier: 3.2.3 version: 3.2.3(preact@10.12.1) '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@wordpress/babel-plugin-import-jsx-pragma': specifier: 4.30.0 version: 4.30.0(@babel/core@7.23.5) @@ -2225,8 +2225,8 @@ importers: specifier: workspace:* version: link:../../js-packages/shared-extension-utils '@storybook/addon-actions': - specifier: 7.4.6 - version: 7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5 '@wordpress/api-fetch': specifier: 6.44.0 version: 6.44.0 @@ -2313,20 +2313,20 @@ importers: specifier: 29.4.3 version: 29.4.3 '@storybook/blocks': - specifier: 7.4.6 - version: 7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + specifier: 7.6.5 + version: 7.6.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) '@storybook/client-api': - specifier: 7.4.6 - version: 7.4.6 + specifier: 7.6.5 + version: 7.6.5 '@storybook/react': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@types/jest': specifier: 29.5.10 version: 29.5.10 @@ -2491,14 +2491,14 @@ importers: specifier: 7.23.5 version: 7.23.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/preact': specifier: 3.2.3 version: 3.2.3(preact@10.12.1) '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@wordpress/babel-plugin-import-jsx-pragma': specifier: 4.30.0 version: 4.30.0(@babel/core@7.23.5) @@ -2646,6 +2646,9 @@ importers: prettier: specifier: npm:wp-prettier@3.0.3 version: /wp-prettier@3.0.3 + react-router-dom: + specifier: 6.21.0 + version: 6.21.0(react-dom@18.2.0)(react@18.2.0) svelte-navigator: specifier: 3.2.2 version: 3.2.2(svelte@3.58.0)(typescript@5.0.4) @@ -2696,8 +2699,8 @@ importers: specifier: 8.3.3 version: 8.3.3(rollup@2.79.1)(tslib@2.5.0)(typescript@5.0.4) '@storybook/react': - specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + specifier: 7.6.5 + version: 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) '@types/jquery': specifier: 3.5.25 version: 3.5.25 @@ -2841,11 +2844,11 @@ importers: specifier: 7.23.5 version: 7.23.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@types/jest': specifier: 29.5.10 version: 29.5.10 @@ -3192,14 +3195,14 @@ importers: specifier: 7.0.0 version: 7.0.0(typescript@5.0.4) '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@testing-library/user-event': specifier: 14.5.1 - version: 14.5.1(@testing-library/dom@8.20.1) + version: 14.5.1(@testing-library/dom@9.3.3) '@types/jest': specifier: 29.5.10 version: 29.5.10 @@ -3580,11 +3583,11 @@ importers: specifier: 7.23.5 version: 7.23.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@types/react': specifier: 18.2.33 version: 18.2.33 @@ -3689,11 +3692,11 @@ importers: specifier: 7.23.5 version: 7.23.5 '@testing-library/dom': - specifier: 8.20.1 - version: 8.20.1 + specifier: 9.3.3 + version: 9.3.3 '@testing-library/react': - specifier: 13.4.0 - version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) '@wordpress/browserslist-config': specifier: 5.30.0 version: 5.30.0 @@ -3915,8 +3918,8 @@ importers: specifier: 29.7.0 version: 29.7.0 jest-extended: - specifier: 2.0.0 - version: 2.0.0(jest@29.7.0) + specifier: 4.0.2 + version: 4.0.2(jest@29.7.0) tools/e2e-commons: devDependencies: @@ -3987,8 +3990,8 @@ importers: specifier: 1.3.3 version: 1.3.3 '@testing-library/jest-dom': - specifier: 5.17.0 - version: 5.17.0 + specifier: 6.1.5 + version: 6.1.5(jest@29.7.0) '@typescript-eslint/eslint-plugin': specifier: 6.7.5 version: 6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.0.4) @@ -4136,8 +4139,8 @@ packages: undici: 5.27.2 dev: false - /@adobe/css-tools@4.3.1: - resolution: {integrity: sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==} + /@adobe/css-tools@4.3.2: + resolution: {integrity: sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==} dev: true /@ampproject/remapping@2.2.1: @@ -4254,13 +4257,6 @@ packages: default-browser-id: 3.0.0 dev: true - /@babel/code-frame@7.22.13: - resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.20 - chalk: 2.4.2 - /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -4308,16 +4304,6 @@ packages: semver: 6.3.1 dev: true - /@babel/generator@7.23.3: - resolution: {integrity: sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.3 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 - jsesc: 2.5.2 - dev: true - /@babel/generator@7.23.6: resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} engines: {node: '>=6.9.0'} @@ -4337,14 +4323,14 @@ packages: resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-compilation-targets@7.22.15: resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} engines: {node: '>=6.9.0'} dependencies: '@babel/compat-data': 7.23.5 - '@babel/helper-validator-option': 7.22.15 + '@babel/helper-validator-option': 7.23.5 browserslist: 4.22.1 lru-cache: 5.1.1 semver: 6.3.1 @@ -4400,25 +4386,25 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.22.15 - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-hoist-variables@7.22.5: resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-member-expression-to-functions@7.23.0: resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-module-imports@7.22.15: resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} @@ -4437,7 +4423,7 @@ packages: resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-plugin-utils@7.22.5: resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} @@ -4475,17 +4461,13 @@ packages: resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.3 - - /@babel/helper-string-parser@7.22.5: - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} - engines: {node: '>=6.9.0'} + '@babel/types': 7.23.6 /@babel/helper-string-parser@7.23.4: resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} @@ -4495,10 +4477,6 @@ packages: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option@7.22.15: - resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} - engines: {node: '>=6.9.0'} - /@babel/helper-validator-option@7.23.5: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} @@ -4509,7 +4487,7 @@ packages: dependencies: '@babel/helper-function-name': 7.23.0 '@babel/template': 7.22.15 - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 /@babel/helpers@7.23.6: resolution: {integrity: sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==} @@ -4521,14 +4499,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/highlight@7.22.20: - resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - /@babel/highlight@7.23.4: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} @@ -4537,13 +4507,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.23.3: - resolution: {integrity: sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.23.3 - /@babel/parser@7.23.6: resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} engines: {node: '>=6.0.0'} @@ -4581,43 +4544,6 @@ packages: '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.23.5): - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.5) - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.23.5): - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.5) - dev: true - - /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.23.5): - resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.23.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.5) - dev: true - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.5): resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} @@ -5485,7 +5411,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 + '@babel/helper-validator-option': 7.23.5 '@babel/plugin-transform-flow-strip-types': 7.23.3(@babel/core@7.23.5) dev: true @@ -5496,7 +5422,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 esutils: 2.0.3 /@babel/preset-react@7.23.3(@babel/core@7.23.5): @@ -5507,7 +5433,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 + '@babel/helper-validator-option': 7.23.5 '@babel/plugin-transform-react-display-name': 7.23.3(@babel/core@7.23.5) '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.5) '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.5) @@ -5521,7 +5447,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 + '@babel/helper-validator-option': 7.23.5 '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5) '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.5) '@babel/plugin-transform-typescript': 7.23.3(@babel/core@7.23.5) @@ -5543,12 +5469,6 @@ packages: /@babel/regjsgen@0.8.0: resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - /@babel/runtime@7.23.2: - resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.0 - /@babel/runtime@7.23.5: resolution: {integrity: sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==} engines: {node: '>=6.9.0'} @@ -5559,27 +5479,9 @@ packages: resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 - - /@babel/traverse@7.23.3: - resolution: {integrity: sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.3 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true + '@babel/code-frame': 7.23.5 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 /@babel/traverse@7.23.6: resolution: {integrity: sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==} @@ -5598,14 +5500,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/types@7.23.3: - resolution: {integrity: sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - /@babel/types@7.23.6: resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} engines: {node: '>=6.9.0'} @@ -6635,6 +6529,7 @@ packages: /@juggle/resize-observer@3.4.0: resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} + dev: true /@mapbox/geojson-rewind@0.5.2: resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==} @@ -6963,7 +6858,7 @@ packages: playwright: 1.39.0 dev: true - /@pmmmwh/react-refresh-webpack-plugin@0.5.11(react-refresh@0.11.0)(webpack@5.76.0): + /@pmmmwh/react-refresh-webpack-plugin@0.5.11(react-refresh@0.14.0)(webpack@5.76.0): resolution: {integrity: sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==} engines: {node: '>= 10.13'} peerDependencies: @@ -6996,7 +6891,7 @@ packages: find-up: 5.0.0 html-entities: 2.4.0 loader-utils: 2.0.4 - react-refresh: 0.11.0 + react-refresh: 0.14.0 schema-utils: 3.3.0 source-map: 0.7.4 webpack: 5.76.0(webpack-cli@4.9.1) @@ -7020,6 +6915,7 @@ packages: resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==} dependencies: '@babel/runtime': 7.23.5 + dev: true /@radix-ui/primitive@1.0.0: resolution: {integrity: sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==} @@ -7030,6 +6926,7 @@ packages: resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} dependencies: '@babel/runtime': 7.23.5 + dev: true /@radix-ui/react-arrow@1.0.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA==} @@ -7061,6 +6958,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-arrow@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} @@ -7137,6 +7035,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-collection@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} @@ -7203,6 +7102,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-compose-refs@1.0.1(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} @@ -7237,6 +7137,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-context@1.0.1(react@18.2.0): resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} @@ -7323,6 +7224,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-direction@1.0.1(react@18.2.0): resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} @@ -7390,6 +7292,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-dismissable-layer@1.0.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==} @@ -7496,6 +7399,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-focus-guards@1.0.1(react@18.2.0): resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} @@ -7557,6 +7461,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-focus-scope@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==} @@ -7623,6 +7528,7 @@ packages: '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.33)(react@18.2.0) '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-id@1.0.1(react@18.2.0): resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} @@ -7770,6 +7676,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-popper@1.1.2(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==} @@ -7869,6 +7776,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-portal@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==} @@ -7962,6 +7870,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-primitive@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} @@ -8048,6 +7957,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-roving-focus@1.0.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} @@ -8143,6 +8053,7 @@ packages: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-remove-scroll: 2.5.5(@types/react@18.2.33)(react@18.2.0) + dev: true /@radix-ui/react-select@1.2.2(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==} @@ -8242,6 +8153,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-separator@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==} @@ -8313,6 +8225,7 @@ packages: '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.33)(react@18.2.0) '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-slot@1.0.2(react@18.2.0): resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} @@ -8353,6 +8266,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-toggle-group@1.0.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==} @@ -8426,6 +8340,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-toggle@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==} @@ -8495,6 +8410,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-toolbar@1.0.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-tBgmM/O7a07xbaEkYJWYTXkIdU/1pW4/KZORR43toC/4XWyBCURK0ei9kMUdp+gTPPKBgYLxXmRSH1EVcIDp8Q==} @@ -8567,6 +8483,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-callback-ref@1.0.1(react@18.2.0): resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} @@ -8603,6 +8520,7 @@ packages: '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.33)(react@18.2.0) '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-controllable-state@1.0.1(react@18.2.0): resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} @@ -8649,6 +8567,7 @@ packages: '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.33)(react@18.2.0) '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-escape-keydown@1.0.3(react@18.2.0): resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} @@ -8684,6 +8603,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-layout-effect@1.0.1(react@18.2.0): resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} @@ -8710,6 +8630,7 @@ packages: '@babel/runtime': 7.23.5 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-previous@1.0.1(react@18.2.0): resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==} @@ -8746,6 +8667,7 @@ packages: '@radix-ui/rect': 1.0.1 '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-rect@1.0.1(react@18.2.0): resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==} @@ -8783,6 +8705,7 @@ packages: '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.33)(react@18.2.0) '@types/react': 18.2.33 react: 18.2.0 + dev: true /@radix-ui/react-use-size@1.0.1(react@18.2.0): resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==} @@ -8817,6 +8740,7 @@ packages: '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /@radix-ui/react-visually-hidden@1.0.3(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} @@ -8866,6 +8790,7 @@ packages: resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} dependencies: '@babel/runtime': 7.23.5 + dev: true /@react-spring/animated@9.7.3(react@18.2.0): resolution: {integrity: sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==} @@ -8910,6 +8835,11 @@ packages: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + /@remix-run/router@1.14.0: + resolution: {integrity: sha512-WOHih+ClN7N8oHk9N4JUiMxQJmRVaOxcg8w7F/oHUXzJt920ekASLI/7cYX8XkntDWRhLZtsk6LbGrkgOAvi5A==} + engines: {node: '>=14.0.0'} + dev: false + /@remix-run/router@1.2.1: resolution: {integrity: sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ==} engines: {node: '>=14'} @@ -9241,219 +9171,67 @@ packages: transitivePeerDependencies: - debug - /@storybook/addon-a11y@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-RE8sXk9KEqgmjsFmG31eObgPMTOvvWnoNZIaZEHs88X30tNHtFwjc0jzvCR/xriKsBtQdYQTUSsB7pSjaJHNzQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-a11y@7.6.5: + resolution: {integrity: sha512-mbwjgdlNDcp0nL29s9FoF+HEFmWn0fMXfTcgMNjQWHs+sfmOy6w3llk0n0RJeDjc+x2Y8Oj2c+JwLU1hhJBnag==} dependencies: - '@storybook/addon-highlight': 7.4.6 - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/addon-highlight': 7.6.5 axe-core: 4.8.2 - lodash: 4.17.21 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-resize-detector: 7.1.2(react-dom@18.2.0)(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - dev: true - - /@storybook/addon-actions@7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-SsqZr3js5NinKPnC8AeNI7Ij+Q6fIl9tRdRmSulEgjksjOg7E5S1/Wsn5Bb2CCgj7MaX6VxGyC7s3XskQtDiIQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 - dequal: 2.0.3 - lodash: 4.17.21 - polished: 4.2.2 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-inspector: 6.0.2(react@18.2.0) - telejson: 7.2.0 - ts-dedent: 2.2.0 - uuid: 9.0.1 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - - /@storybook/addon-actions@7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-SsqZr3js5NinKPnC8AeNI7Ij+Q6fIl9tRdRmSulEgjksjOg7E5S1/Wsn5Bb2CCgj7MaX6VxGyC7s3XskQtDiIQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 - dequal: 2.0.3 - lodash: 4.17.21 - polished: 4.2.2 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-inspector: 6.0.2(react@18.2.0) - telejson: 7.2.0 - ts-dedent: 2.2.0 - uuid: 9.0.1 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' dev: true - /@storybook/addon-actions@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-SsqZr3js5NinKPnC8AeNI7Ij+Q6fIl9tRdRmSulEgjksjOg7E5S1/Wsn5Bb2CCgj7MaX6VxGyC7s3XskQtDiIQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-actions@7.6.5: + resolution: {integrity: sha512-lW/m9YcaNfBZk+TZLxyzHdd563mBWpsUIveOKYjcPdl/q0FblWWZrRsFHqwLK1ldZ4AZXs8J/47G8CBr6Ew2uQ==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 + '@storybook/core-events': 7.6.5 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@types/uuid': 9.0.7 dequal: 2.0.3 - lodash: 4.17.21 polished: 4.2.2 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-inspector: 6.0.2(react@18.2.0) - telejson: 7.2.0 - ts-dedent: 2.2.0 uuid: 9.0.1 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - dev: true - /@storybook/addon-backgrounds@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-+LHTZB/ZYMAzkyD5ZxSriBsqmsrvIaW/Nnd/BeuXGbkrVKKqM0qAKiFZAfjc2WchA1piVNy0/1Rsf+kuYCEiJw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-backgrounds@7.6.5: + resolution: {integrity: sha512-wZZOL19vg4TTRtOTl71XKqPe5hQx3XUh9Fle0wOi91FiFrBdqusrppnyS89wPS8RQG5lXEOFEUvYcMmdCcdZfw==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 memoizerific: 1.11.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' dev: true - /@storybook/addon-controls@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-4lq3sycEUIsK8SUWDYc60QgF4vV9FZZ3lDr6M7j2W9bOnvGw49d2fbdlnq+bX1ZprZZ9VgglQpBAorQB3BXZRw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-controls@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-EdSZ2pYf74mOXZGGJ22lrDvdvL0YKc95iWv9FFEhUFOloMy/0OZPB2ybYmd2KVCy3SeIE4Zfeiw8pDXdCUniOQ==} dependencies: - '@storybook/blocks': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-common': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/node-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/blocks': 7.6.5(react-dom@18.2.0)(react@18.2.0) lodash: 4.17.21 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@types/react-dom' - encoding + - react + - react-dom - supports-color dev: true - /@storybook/addon-docs@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-dLaub+XWFq4hChw+xfuF9yYg0Txp77FUawKoAigccfjWXx+OOhRV3XTuAcknpXkYq94GWynHgUFXosXT9kbDNA==} + /@storybook/addon-docs@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-D9tZyD41IujCHiPYdfS2bKtZRJPNwO4EydzyqODXppomluhFbY3uTEaf0H1UFnJLQxWNXZ7rr3aS0V3O6yu8pA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@jest/transform': 29.7.0 '@mdx-js/react': 2.3.0(react@18.2.0) - '@storybook/blocks': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/csf-plugin': 7.4.6 - '@storybook/csf-tools': 7.4.6 + '@storybook/blocks': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/client-logger': 7.6.5 + '@storybook/components': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/csf-plugin': 7.6.5 + '@storybook/csf-tools': 7.6.5 '@storybook/global': 5.0.0 '@storybook/mdx2-csf': 1.1.0 - '@storybook/node-logger': 7.4.6 - '@storybook/postinstall': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/react-dom-shim': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/node-logger': 7.6.5 + '@storybook/postinstall': 7.6.5 + '@storybook/preview-api': 7.6.5 + '@storybook/react-dom-shim': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 fs-extra: 11.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -9467,25 +9245,25 @@ packages: - supports-color dev: true - /@storybook/addon-essentials@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-dWodufrt71TK7ELkeIvVae/x4PzECUlbOm57Iqqt4yQCyR291CgvI4PjeB8un2HbpcXCGZ+N/Oj3YkytvzBi4A==} + /@storybook/addon-essentials@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-VCLj1JAEpGoqF5iFJOo1CZFFck/tg4m/98DLdQuNuXvxT6jqaF0NI9UUQuJLIGteDCR7NKRbTFc1hV3/Ev+Ziw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/addon-actions': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-backgrounds': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-controls': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-docs': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-highlight': 7.4.6 - '@storybook/addon-measure': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-outline': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-toolbars': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-viewport': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-common': 7.4.6 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/node-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 + '@storybook/addon-actions': 7.6.5 + '@storybook/addon-backgrounds': 7.6.5 + '@storybook/addon-controls': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-docs': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-highlight': 7.6.5 + '@storybook/addon-measure': 7.6.5 + '@storybook/addon-outline': 7.6.5 + '@storybook/addon-toolbars': 7.6.5 + '@storybook/addon-viewport': 7.6.5 + '@storybook/core-common': 7.6.5 + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/node-logger': 7.6.5 + '@storybook/preview-api': 7.6.5 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 @@ -9496,192 +9274,82 @@ packages: - supports-color dev: true - /@storybook/addon-highlight@7.4.6: - resolution: {integrity: sha512-zCufxxD2KS5VwczxfkcBxe1oR/juTTn2H1Qm8kYvWCJQx3UxzX0+G9cwafbpV7eivqaufLweEwROkH+0KjAtkQ==} + /@storybook/addon-highlight@7.6.5: + resolution: {integrity: sha512-CxzmIb30F9nLPQwT0lCPYhOAwGlGF4IkgkO8hYA7VfGCGUkJZEyyN/YkP/ZCUSdCIRChDBouR3KiFFd4mDFKzg==} dependencies: - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.4.6 dev: true - /@storybook/addon-measure@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-nCymMLaHnxv8TE3yEM1A9Tulb1NuRXRNmtsdHTkjv7P1aWCxZo8A/GZaottKe/GLT8jSRjZ+dnpYWrbAhw6wTQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-measure@7.6.5: + resolution: {integrity: sha512-tlUudVQSrA+bwI4dhO8J7nYHtYdylcBZ86ybnqMmdTthsnyc7jnaFVQwbb6bbQJpPxvEvoNds5bVGUFocuvymQ==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) tiny-invariant: 1.3.1 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' dev: true - /@storybook/addon-outline@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-errNUblRVDLpuEaHQPr/nsrnsUkD2ARmXawkRvizgDWLIDMDJYjTON3MUCaVx3x+hlZ3I6X//G5TVcma8tCc8A==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-outline@7.6.5: + resolution: {integrity: sha512-P7X4+Z9L/l/RZW9UvvM+iuK2SUHD22KPc+dbYOifRXDovUqhfmcKVh1CUqTDMyZrg2ZAbropehMz1eI9BlQfxg==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' dev: true - /@storybook/addon-storysource@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-qkfwvh/pgVBReuWqO25WyaD7jd6LVqhoIJ6rBWnmx+NBpTds+h3Yt3UJCHgvweIrfSF8J3IqzaTxmmNjnkcrRw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-storysource@7.6.5: + resolution: {integrity: sha512-mlGReftuGxfyfLXsnw4GF03G79w3rKKRclNasOVPuAR2vlSTRyltoglZ8TcXfxNQ+RzywtEZkjD7SeJZsuvBbQ==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/router': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/source-loader': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) + '@storybook/source-loader': 7.6.5 estraverse: 5.3.0 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-syntax-highlighter: 15.5.0(react@18.2.0) tiny-invariant: 1.3.1 - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' dev: true - /@storybook/addon-toolbars@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-L9m2FBcKeteGq7qIYsMJr0LEfiH7Wdrv5IDcldZTn68eZUJTh1p4GdJZcOmzX1P5IFRr76hpu03iWsNlWQjpbQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' + /@storybook/addon-toolbars@7.6.5: + resolution: {integrity: sha512-/zqWbVNE/SHc8I5Prnd2Q8U57RGEIYvHfeXjfkuLcE2Quc4Iss4x/9eU7SKu4jm+IOO2s0wlN6HcqI3XEf2XxA==} dev: true - /@storybook/addon-viewport@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-INDtk54j7bi7NgxMfd2ATmbA0J7nAd6X8itMkLIyPuPJtx8bYHPDORyemDOd0AojgmAdTOAyUtDYdI/PFeo4Cw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/addon-viewport@7.6.5: + resolution: {integrity: sha512-9ghKTaduIUvQ6oShmWLuwMeTjtMR4RgKeKHrTJ7THMqvE/ydDPCYeL7ugF65ocXZSEz/QmxdK7uL686ZMKsqNA==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) memoizerific: 1.11.3 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' dev: true - /@storybook/addons@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-c+4awrtwNlJayFdgLkEXa5H2Gj+KNlxuN+Z5oDAdZBLqXI8g0gn7eYO2F/eCSIDWdd/+zcU2uq57XPFKc8veHQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + /@storybook/addons@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-v+d8io1MsgTd7rruYInfKXY0c1uXn+ADLxAppUI0PUwPFYwg9tLn3cvwgt5SVum9E5IkVQwXoW6JNkDC5fC8XQ==} dependencies: - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.6.5 + '@storybook/types': 7.6.5 + transitivePeerDependencies: + - react + - react-dom dev: true - /@storybook/api@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-mnkHs2WI3/7vEUk+Bo1ZlQDp5vJDtoFSCFP5iae3YyVBbnjiI6oYlMZ14KgeizFULk3VaDv6/BdiynG1RkdO4Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + /@storybook/api@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-o1RH47iIgG4ie4hjJP1HgsCiuTKlGW0egaAy6E6Np3bDmujy5udWEf8vnXbcaBerc5ZSrQs45kfSWugHy2a4FA==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@storybook/client-logger': 7.6.5 + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + transitivePeerDependencies: + - react + - react-dom dev: true - /@storybook/blocks@7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-HxBSAeOiTZW2jbHQlo1upRWFgoMsaAyKijUFf5MwwMNIesXCuuTGZDJ3xTABwAVLK2qC9Ektfbo0CZCiPVuDRQ==} + /@storybook/blocks@7.6.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/NjuYkPks5w9lKn47KLgVC5cBkwfc+ERAp0CY0Xe//BQJkP+bcI8lE8d9Qc9IXFbOTvYEULeQrFgCkesk5BmLg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 - '@storybook/docs-tools': 7.4.6 + '@storybook/channels': 7.6.5 + '@storybook/client-logger': 7.6.5 + '@storybook/components': 7.6.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.6.5 + '@storybook/csf': 0.1.2 + '@storybook/docs-tools': 7.6.5 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.6.5 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 '@types/lodash': 4.14.201 color-convert: 2.0.1 dequal: 2.0.3 @@ -9703,23 +9371,23 @@ packages: - supports-color dev: true - /@storybook/blocks@7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-HxBSAeOiTZW2jbHQlo1upRWFgoMsaAyKijUFf5MwwMNIesXCuuTGZDJ3xTABwAVLK2qC9Ektfbo0CZCiPVuDRQ==} + /@storybook/blocks@7.6.5(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/NjuYkPks5w9lKn47KLgVC5cBkwfc+ERAp0CY0Xe//BQJkP+bcI8lE8d9Qc9IXFbOTvYEULeQrFgCkesk5BmLg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 - '@storybook/docs-tools': 7.4.6 + '@storybook/channels': 7.6.5 + '@storybook/client-logger': 7.6.5 + '@storybook/components': 7.6.5(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.6.5 + '@storybook/csf': 0.1.2 + '@storybook/docs-tools': 7.6.5 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.6.5 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 '@types/lodash': 4.14.201 color-convert: 2.0.1 dequal: 2.0.3 @@ -9741,23 +9409,23 @@ packages: - supports-color dev: true - /@storybook/blocks@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-HxBSAeOiTZW2jbHQlo1upRWFgoMsaAyKijUFf5MwwMNIesXCuuTGZDJ3xTABwAVLK2qC9Ektfbo0CZCiPVuDRQ==} + /@storybook/blocks@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/NjuYkPks5w9lKn47KLgVC5cBkwfc+ERAp0CY0Xe//BQJkP+bcI8lE8d9Qc9IXFbOTvYEULeQrFgCkesk5BmLg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 - '@storybook/docs-tools': 7.4.6 + '@storybook/channels': 7.6.5 + '@storybook/client-logger': 7.6.5 + '@storybook/components': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.6.5 + '@storybook/csf': 0.1.2 + '@storybook/docs-tools': 7.6.5 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.6.5 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 '@types/lodash': 4.14.201 color-convert: 2.0.1 dequal: 2.0.3 @@ -9779,13 +9447,13 @@ packages: - supports-color dev: true - /@storybook/builder-manager@7.4.6: - resolution: {integrity: sha512-zylZCD2rmyLOOFBFmUgtJg6UNUKmRNgXiig1XApzS2TkIbTZP827DsVEUl0ey/lskCe0uArkrEBR6ICba8p/Rw==} + /@storybook/builder-manager@7.6.5: + resolution: {integrity: sha512-FQyI+tfzMam2XKXq7k921YVafIJs9Vqvos5qx8vyRnRffo55UU8tgunwjGn0PswtbMm6sThVqE0C0ZzVr7RG8A==} dependencies: '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@storybook/core-common': 7.4.6 - '@storybook/manager': 7.4.6 - '@storybook/node-logger': 7.4.6 + '@storybook/core-common': 7.6.5 + '@storybook/manager': 7.6.5 + '@storybook/node-logger': 7.6.5 '@types/ejs': 3.1.5 '@types/find-cache-dir': 3.2.1 '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.18.20) @@ -9803,50 +9471,39 @@ packages: - supports-color dev: true - /@storybook/builder-webpack5@7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1): - resolution: {integrity: sha512-j7AyDPlUuO2GiH6riB8iGbT7blQpyVGB+rMHXPSm7v6/U7IITbNzxFwe+sSMLoFr8K1e2VXpgqQ9p3rHFey+nw==} + /@storybook/builder-webpack5@7.6.5(typescript@5.0.4)(webpack-cli@4.9.1): + resolution: {integrity: sha512-Lf4jVHGTQRSLIcgXHG2webiFlNwEV8uo2CmDucU2IDV9p3NdloyOmCou40G6Du1hobBTflx8Zj2j9n3A5/+0GA==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@babel/core': 7.23.5 - '@storybook/addons': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/channels': 7.4.6 - '@storybook/client-api': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-common': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/core-webpack': 7.4.6 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/node-logger': 7.4.6 - '@storybook/preview': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/router': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/store': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) + '@storybook/channels': 7.6.5 + '@storybook/client-logger': 7.6.5 + '@storybook/core-common': 7.6.5 + '@storybook/core-events': 7.6.5 + '@storybook/core-webpack': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/preview': 7.6.5 + '@storybook/preview-api': 7.6.5 '@swc/core': 1.3.96 - '@types/node': 16.18.61 + '@types/node': 18.19.3 '@types/semver': 7.5.5 babel-loader: 9.1.2(@babel/core@7.23.5)(webpack@5.76.0) - babel-plugin-named-exports-order: 0.0.2 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 constants-browserify: 1.0.0 css-loader: 6.8.1(webpack@5.76.0) + es-module-lexer: 1.4.1 express: 4.18.2 fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.0.4)(webpack@5.76.0) fs-extra: 11.1.1 html-webpack-plugin: 5.5.3(webpack@5.76.0) + magic-string: 0.30.5 path-browserify: 1.0.1 process: 0.11.10 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) semver: 7.5.2 style-loader: 3.3.3(webpack@5.76.0) swc-loader: 0.2.3(@swc/core@1.3.96)(webpack@5.76.0) @@ -9862,8 +9519,6 @@ packages: webpack-virtual-modules: 0.5.0 transitivePeerDependencies: - '@swc/helpers' - - '@types/react' - - '@types/react-dom' - encoding - esbuild - supports-color @@ -9871,43 +9526,33 @@ packages: - webpack-cli dev: true - /@storybook/channels@7.4.6: - resolution: {integrity: sha512-yPv/sfo2c18fM3fvG0i1xse63vG8l33Al/OU0k/dtovltPu001/HVa1QgBgsb/QrEfZtvGjGhmtdVeYb39fv3A==} - dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/global': 5.0.0 - qs: 6.11.2 - telejson: 7.2.0 - tiny-invariant: 1.3.1 - - /@storybook/channels@7.5.3: - resolution: {integrity: sha512-dhWuV2o2lmxH0RKuzND8jxYzvSQTSmpE13P0IT/k8+I1up/rSNYOBQJT6SalakcNWXFAMXguo/8E7ApmnKKcEw==} + /@storybook/channels@7.6.5: + resolution: {integrity: sha512-FIlNkyfQy9uHoJfAFL2/wO3ASGJELFvBzURBE2rcEF/TS7GcUiqWnBfiDxAbwSEjSOm2F0eEq3UXhaZEjpJHDw==} dependencies: - '@storybook/client-logger': 7.5.3 - '@storybook/core-events': 7.5.3 + '@storybook/client-logger': 7.6.5 + '@storybook/core-events': 7.6.5 '@storybook/global': 5.0.0 qs: 6.11.2 telejson: 7.2.0 tiny-invariant: 1.3.1 dev: true - /@storybook/cli@7.4.6: - resolution: {integrity: sha512-rRwaH8pOL+FHz/pJMEkNpMH2xvZvWsrl7obBYw26NQiHmiVSAkfHJicndSN1mwc+p5w+9iXthrgzbLtSAOSvkA==} + /@storybook/cli@7.6.5: + resolution: {integrity: sha512-w+Y8dx5oCLQVESOVmpsQuFksr/ewARKrnSKl9kwnVMN4sMgjOgoZ3zmV66J7SKexvwyuwlOjf840pmEglGdPPg==} hasBin: true dependencies: '@babel/core': 7.23.5 '@babel/preset-env': 7.23.5(@babel/core@7.23.5) - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 '@ndelangen/get-tarball': 3.0.9 - '@storybook/codemod': 7.4.6 - '@storybook/core-common': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/core-server': 7.4.6 - '@storybook/csf-tools': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/telemetry': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/codemod': 7.6.5 + '@storybook/core-common': 7.6.5 + '@storybook/core-events': 7.6.5 + '@storybook/core-server': 7.6.5 + '@storybook/csf-tools': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/telemetry': 7.6.5 + '@storybook/types': 7.6.5 '@types/semver': 7.5.5 '@yarnpkg/fslib': 2.10.3 '@yarnpkg/libzip': 2.3.0 @@ -9924,7 +9569,7 @@ packages: get-port: 5.1.1 giget: 1.1.3 globby: 11.1.0 - jscodeshift: 0.14.0(@babel/preset-env@7.23.5) + jscodeshift: 0.15.1(@babel/preset-env@7.23.5) leven: 3.1.0 ora: 5.4.1 prettier: 2.8.8 @@ -9944,38 +9589,33 @@ packages: - utf-8-validate dev: true - /@storybook/client-api@7.4.6: - resolution: {integrity: sha512-O8yA/xEzPW9Oe3s5VJAFor2d2KwXHjUZ1gvou3o14zu/TJLgXwol0qBBr+YLRO2rcNNJ51pAIGwAT5bgmpUaeg==} + /@storybook/client-api@7.6.5: + resolution: {integrity: sha512-bvBqqRz5VzbTAwoHLfIkPioZoOgKfBZu4dLJ/dRbqffxnp+dMuG8jvexrSblXnuDRQeQG/bfwlFbh0z7hp2KqQ==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 + '@storybook/client-logger': 7.6.5 + '@storybook/preview-api': 7.6.5 dev: true - /@storybook/client-logger@7.4.6: - resolution: {integrity: sha512-XDw31ZziU//86PKuMRnmc+L/G0VopaGKENQOGEpvAXCU9IZASwGKlKAtcyosjrpi+ZiUXlMgUXCpXM7x3b1Ehw==} - dependencies: - '@storybook/global': 5.0.0 - - /@storybook/client-logger@7.5.3: - resolution: {integrity: sha512-vUFYALypjix5FoJ5M/XUP6KmyTnQJNW1poHdW7WXUVSg+lBM6E5eAtjTm0hdxNNDH8KSrdy24nCLra5h0X0BWg==} + /@storybook/client-logger@7.6.5: + resolution: {integrity: sha512-S5aROWgssqg7tcs9lgW5wmCAz4SxMAtioiyVj5oFecmPCbQtFVIAREYzeoxE4GfJL+plrfRkum4BzziANn8EhQ==} dependencies: '@storybook/global': 5.0.0 dev: true - /@storybook/codemod@7.4.6: - resolution: {integrity: sha512-lxmwEpwksCaAq96APN2YlooSDfKjJ1vKzN5Ni2EqQzf2TEXl7XQjLacHd7OOaII1kfsy+D5gNG4N5wBo7Ub30g==} + /@storybook/codemod@7.6.5: + resolution: {integrity: sha512-K5C9ltBClZ0aSyujGt3RJFtRicrUZy8nzhHrcADUj27rrQD26jH/p+Y05jWKj9JcI8SyMg978GN5X/1aw2Y31A==} dependencies: '@babel/core': 7.23.5 '@babel/preset-env': 7.23.5(@babel/core@7.23.5) - '@babel/types': 7.23.3 - '@storybook/csf': 0.1.1 - '@storybook/csf-tools': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/types': 7.4.6 + '@babel/types': 7.23.6 + '@storybook/csf': 0.1.2 + '@storybook/csf-tools': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/types': 7.6.5 '@types/cross-spawn': 6.0.5 cross-spawn: 7.0.3 globby: 11.1.0 - jscodeshift: 0.14.0(@babel/preset-env@7.23.5) + jscodeshift: 0.15.1(@babel/preset-env@7.23.5) lodash: 4.17.21 prettier: 2.8.8 recast: 0.23.4 @@ -9983,19 +9623,19 @@ packages: - supports-color dev: true - /@storybook/components@7.4.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-nIRBhewAgrJJVafyCzuaLx1l+YOfvvD5dOZ0JxZsxJsefOdw1jFpUqUZ5fIpQ2moyvrR0mAUFw378rBfMdHz5Q==} + /@storybook/components@7.6.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-w4ZucbBBZ+NKMWlJKVj2I/bMBBq7gzDp9lzc4+8QaQ3vUPXKqc1ilIPYo/7UR5oxwDVMZocmMSgl9L8lvf7+Mw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@radix-ui/react-select': 1.2.2(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-toolbar': 1.0.4(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/client-logger': 7.6.5 + '@storybook/csf': 0.1.2 '@storybook/global': 5.0.0 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -10004,20 +9644,21 @@ packages: transitivePeerDependencies: - '@types/react' - '@types/react-dom' + dev: true - /@storybook/components@7.4.6(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-nIRBhewAgrJJVafyCzuaLx1l+YOfvvD5dOZ0JxZsxJsefOdw1jFpUqUZ5fIpQ2moyvrR0mAUFw378rBfMdHz5Q==} + /@storybook/components@7.6.5(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-w4ZucbBBZ+NKMWlJKVj2I/bMBBq7gzDp9lzc4+8QaQ3vUPXKqc1ilIPYo/7UR5oxwDVMZocmMSgl9L8lvf7+Mw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@radix-ui/react-select': 1.2.2(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-toolbar': 1.0.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/client-logger': 7.6.5 + '@storybook/csf': 0.1.2 '@storybook/global': 5.0.0 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -10028,19 +9669,19 @@ packages: - '@types/react-dom' dev: true - /@storybook/components@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-nIRBhewAgrJJVafyCzuaLx1l+YOfvvD5dOZ0JxZsxJsefOdw1jFpUqUZ5fIpQ2moyvrR0mAUFw378rBfMdHz5Q==} + /@storybook/components@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-w4ZucbBBZ+NKMWlJKVj2I/bMBBq7gzDp9lzc4+8QaQ3vUPXKqc1ilIPYo/7UR5oxwDVMZocmMSgl9L8lvf7+Mw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@radix-ui/react-select': 1.2.2(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-toolbar': 1.0.4(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/client-logger': 7.6.5 + '@storybook/csf': 0.1.2 '@storybook/global': 5.0.0 - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -10051,21 +9692,21 @@ packages: - '@types/react-dom' dev: true - /@storybook/core-client@7.4.6: - resolution: {integrity: sha512-tfgxAHeCvMcs6DsVgtb4hQSDaCHeAPJOsoyhb47eDQfk4OmxzriM0qWucJV5DePSMi+KutX/rN2u0JxfOuN68g==} + /@storybook/core-client@7.6.5: + resolution: {integrity: sha512-6FtyJcz8MSl+JYwNJZ53FM6rkT27pFHWcJPdtw/9229Ec8as9RpkNeZ/NBZjRTeDkn9Ki0VOiVAefNie9tZ/8Q==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 + '@storybook/client-logger': 7.6.5 + '@storybook/preview-api': 7.6.5 dev: true - /@storybook/core-common@7.4.6: - resolution: {integrity: sha512-05MJFmOM86qvTLtgDskokIFz9txe0Lbhq4L3by1FtF0GwgH+p+W6I94KI7c6ANER+kVZkXQZhiRzwBFnVTW+Cg==} + /@storybook/core-common@7.6.5: + resolution: {integrity: sha512-z4EgzZSIVbID6Ib0jhh3jimKeaDWU8OOhoZYfn3galFmgQWowWOv1oMgipWiXfRLWw9DaLFQiCHIdLANH+VO2g==} dependencies: - '@storybook/core-events': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/core-events': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/types': 7.6.5 '@types/find-cache-dir': 3.2.1 - '@types/node': 16.18.61 + '@types/node': 18.19.3 '@types/node-fetch': 2.6.9 '@types/pretty-hrtime': 1.0.3 chalk: 4.1.2 @@ -10089,37 +9730,31 @@ packages: - supports-color dev: true - /@storybook/core-events@7.4.6: - resolution: {integrity: sha512-r5vrE+32lwrJh1NGFr1a0mWjvxo7q8FXYShylcwRWpacmL5NTtLkrXOoJSeGvJ4yKNYkvxQFtOPId4lzDxa32w==} + /@storybook/core-events@7.6.5: + resolution: {integrity: sha512-zk2q/qicYXAzHA4oV3GDbIql+Kd4TOHUgDE8e4jPCOPp856z2ScqEKUAbiJizs6eEJOH4nW9Db1kuzgrBVEykQ==} dependencies: ts-dedent: 2.2.0 - /@storybook/core-events@7.5.3: - resolution: {integrity: sha512-DFOpyQ22JD5C1oeOFzL8wlqSWZzrqgDfDbUGP8xdO4wJu+FVTxnnWN6ZYLdTPB1u27DOhd7TzjQMfLDHLu7kbQ==} - dependencies: - ts-dedent: 2.2.0 - dev: true - - /@storybook/core-server@7.4.6: - resolution: {integrity: sha512-jqmRTGCJ1W0WReImivkisPVaLFT5sjtLnFoAk0feHp6QS5j7EYOPN7CYzliyQmARWTLUEXOVaFf3VD6nJZQhJQ==} + /@storybook/core-server@7.6.5: + resolution: {integrity: sha512-BfKzK/ObTjUcPvE5/r1pogCifM/4nLRhOUYJl7XekwHkOQwn19e6H3/ku1W3jDoYXBu642Dc9X7l/ERjKTqxFg==} dependencies: '@aw-web-design/x-default-browser': 1.4.126 '@discoveryjs/json-ext': 0.5.7 - '@storybook/builder-manager': 7.4.6 - '@storybook/channels': 7.4.6 - '@storybook/core-common': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 - '@storybook/csf-tools': 7.4.6 + '@storybook/builder-manager': 7.6.5 + '@storybook/channels': 7.6.5 + '@storybook/core-common': 7.6.5 + '@storybook/core-events': 7.6.5 + '@storybook/csf': 0.1.2 + '@storybook/csf-tools': 7.6.5 '@storybook/docs-mdx': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/manager': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/telemetry': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/manager': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/preview-api': 7.6.5 + '@storybook/telemetry': 7.6.5 + '@storybook/types': 7.6.5 '@types/detect-port': 1.3.5 - '@types/node': 16.18.61 + '@types/node': 18.19.3 '@types/pretty-hrtime': 1.0.3 '@types/semver': 7.5.5 better-opn: 3.0.2 @@ -10151,37 +9786,37 @@ packages: - utf-8-validate dev: true - /@storybook/core-webpack@7.4.6: - resolution: {integrity: sha512-EqQDmd+vKAWOAjoe539LsfP8WvQG9V9i1priMA53u1FOEged8o0NBtRiRy2+JDdUSiGUdpe/X5+V/TyyQw/KWw==} + /@storybook/core-webpack@7.6.5: + resolution: {integrity: sha512-if5ixN2W3e8vwYvgFHq+k0FOSVwgolbPRLDeOToPXHAJjH/TmgGEANZLFAVVwEzsS4KOfRGJQ48KzF0knTsqzA==} dependencies: - '@storybook/core-common': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/types': 7.4.6 - '@types/node': 16.18.61 + '@storybook/core-common': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/types': 7.6.5 + '@types/node': 18.19.3 ts-dedent: 2.2.0 transitivePeerDependencies: - encoding - supports-color dev: true - /@storybook/csf-plugin@7.4.6: - resolution: {integrity: sha512-yi7Qa4NSqKOyiJTWCxlB0ih2ijXq6oY5qZKW6MuMMBP14xJNRGLbH5KabpfXgN2T7YECcOWG1uWaGj2veJb1KA==} + /@storybook/csf-plugin@7.6.5: + resolution: {integrity: sha512-iQ8Y/Qq1IUhHRddjDVicWJA2sM7OZA1FR97OvWUT2240WjCuQSCfy32JD8TQlYjqXgEolJeLPv3zW4qH5om4LQ==} dependencies: - '@storybook/csf-tools': 7.4.6 + '@storybook/csf-tools': 7.6.5 unplugin: 1.5.0 transitivePeerDependencies: - supports-color dev: true - /@storybook/csf-tools@7.4.6: - resolution: {integrity: sha512-ocKpcIUtTBy6hlLY34RUFQyX403cWpB2gGfqvkHbpGe2BQj7EyV0zpWnjsfVxvw+M9OWlCdxHWDOPUgXM33ELw==} + /@storybook/csf-tools@7.6.5: + resolution: {integrity: sha512-1iaCh7nt+WE7Q5UwRhLLc5flMNoAV/vBr0tvDSCKiHaO+D3dZzlZOe/U+S6wegdyN2QNcvT2xs179CcrX6Qp6w==} dependencies: - '@babel/generator': 7.23.3 - '@babel/parser': 7.23.3 - '@babel/traverse': 7.23.3 - '@babel/types': 7.23.3 - '@storybook/csf': 0.1.1 - '@storybook/types': 7.4.6 + '@babel/generator': 7.23.6 + '@babel/parser': 7.23.6 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + '@storybook/csf': 0.1.2 + '@storybook/types': 7.6.5 fs-extra: 11.1.1 recast: 0.23.4 ts-dedent: 2.2.0 @@ -10189,22 +9824,24 @@ packages: - supports-color dev: true - /@storybook/csf@0.1.1: - resolution: {integrity: sha512-4hE3AlNVxR60Wc5KSC68ASYzUobjPqtSKyhV6G+ge0FIXU55N5nTY7dXGRZHQGDBPq+XqchMkIdlkHPRs8nTHg==} + /@storybook/csf@0.1.2: + resolution: {integrity: sha512-ePrvE/pS1vsKR9Xr+o+YwdqNgHUyXvg+1Xjx0h9LrVx7Zq4zNe06pd63F5EvzTbCbJsHj7GHr9tkiaqm7U8WRA==} dependencies: type-fest: 2.19.0 + dev: true /@storybook/docs-mdx@0.1.0: resolution: {integrity: sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==} dev: true - /@storybook/docs-tools@7.4.6: - resolution: {integrity: sha512-nZj1L/8WwKWWJ41FW4MaKGajZUtrhnr9UwflRCkQJaWhAKmDfOb5M5TqI93uCOULpFPOm5wpoMBz2IHInQ2Lrg==} + /@storybook/docs-tools@7.6.5: + resolution: {integrity: sha512-UyHkHu5Af6jMpYsR4lZ69D32GQGeA0pLAn7jaBbQndgAjBdK1ykZcifiUC7Wz1hG7+YpuYspEGuDEddOh+X8FQ==} dependencies: - '@storybook/core-common': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/core-common': 7.6.5 + '@storybook/preview-api': 7.6.5 + '@storybook/types': 7.6.5 '@types/doctrine': 0.0.3 + assert: 2.1.0 doctrine: 3.0.0 lodash: 4.17.21 transitivePeerDependencies: @@ -10215,48 +9852,47 @@ packages: /@storybook/global@5.0.0: resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} - /@storybook/manager-api@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-inrm3DIbCp8wjXSN/wK6e6i2ysQ/IEmtC7IN0OJ7vdrp+USCooPT448SQTUmVctUGCFmOU3fxXByq8g77oIi7w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + /@storybook/manager-api@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-tE3OShOcs6A3XtI3NJd6hYQOZLaP++Fn0dCtowBwYh/vS1EN/AyroVmL97tsxn1DZTyoRt0GidwbB6dvLMBOwA==} dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/channels': 7.6.5 + '@storybook/client-logger': 7.6.5 + '@storybook/core-events': 7.6.5 + '@storybook/csf': 0.1.2 '@storybook/global': 5.0.0 - '@storybook/router': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/router': 7.6.5 + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) semver: 7.5.2 store2: 2.14.2 telejson: 7.2.0 ts-dedent: 2.2.0 + transitivePeerDependencies: + - react + - react-dom + dev: true - /@storybook/manager@7.4.6: - resolution: {integrity: sha512-kA1hUDxpn1i2SO9OinvLvVXDeL4xgJkModp+pbE8IXv4NJWReNq1ecMeQCzPLS3Sil2gnrullQ9uYXsnZ9bxxA==} + /@storybook/manager@7.6.5: + resolution: {integrity: sha512-y1KLH0O1PGPyMxGMvOhppzFSO7r4ibjTve5iqsI0JZwxUjNuBKRLYbrhXdAyC2iacvxYNrHgevae1k9XdD+FQw==} dev: true /@storybook/mdx2-csf@1.1.0: resolution: {integrity: sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==} dev: true - /@storybook/node-logger@7.4.6: - resolution: {integrity: sha512-djZb310Q27GviDug1XBv0jOEDLCiwr4hhDE0aifCEKZpfNCi/EaP31nbWimFzZwxu4hE/YAPWExzScruR1zw9Q==} + /@storybook/node-logger@7.6.5: + resolution: {integrity: sha512-xKw6IH1wLkIssekdBv3bd13xYKUF1t8EwqDR8BYcN8AVjZlqJMTifssqG4bYV+G/B7J3tz4ugJ5nmtWg6RQ0Qw==} dev: true - /@storybook/postinstall@7.4.6: - resolution: {integrity: sha512-TqI5BucPAGRWrkh55BYiG2/gHLFtC0In4cuu0GsUzB/1jc4i51npLRorCwhmT7r7YliGl5F7JaP0Bni/qHN3Lg==} + /@storybook/postinstall@7.6.5: + resolution: {integrity: sha512-12WxfpqGKsk7GQ3KWiZSbamsYK8vtRmhOTkavZ9IQkcJ/zuVfmqK80/Mds+njJMudUPzuREuSFGWACczo17EDA==} dev: true - /@storybook/preset-react-webpack@7.4.6(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1): - resolution: {integrity: sha512-FfJvlk3bJfg66t06YLiyu+1o/DZN3uNfFP37zv5cJux7TpdmJRV/4m9LKQPJOvcnWBQYem8xX8k5cRS29vdW5g==} + /@storybook/preset-react-webpack@7.6.5(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1): + resolution: {integrity: sha512-Lf9bYUkH1DoWjgptkNgMtA0IkRqGhWE/EnmOvq4otV+Cr/BaVQw3/sfKQ76qdpTQZ4Qg4dG+nBWrwaDkfqxKDA==} engines: {node: '>=16.0.0'} peerDependencies: '@babel/core': ^7.22.0 @@ -10272,20 +9908,21 @@ packages: '@babel/core': 7.23.5 '@babel/preset-flow': 7.23.3(@babel/core@7.23.5) '@babel/preset-react': 7.23.3(@babel/core@7.23.5) - '@pmmmwh/react-refresh-webpack-plugin': 0.5.11(react-refresh@0.11.0)(webpack@5.76.0) - '@storybook/core-webpack': 7.4.6 - '@storybook/docs-tools': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/react': 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.11(react-refresh@0.14.0)(webpack@5.76.0) + '@storybook/core-webpack': 7.6.5 + '@storybook/docs-tools': 7.6.5 + '@storybook/node-logger': 7.6.5 + '@storybook/react': 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.0.4)(webpack@5.76.0) - '@types/node': 16.18.61 + '@types/node': 18.19.3 '@types/semver': 7.5.5 babel-plugin-add-react-displayname: 0.0.5 - babel-plugin-react-docgen: 4.2.1 fs-extra: 11.1.1 + magic-string: 0.30.5 react: 18.2.0 + react-docgen: 7.0.1 react-dom: 18.2.0(react@18.2.0) - react-refresh: 0.11.0 + react-refresh: 0.14.0 semver: 7.5.2 typescript: 5.0.4 webpack: 5.76.0(webpack-cli@4.9.1) @@ -10304,15 +9941,15 @@ packages: - webpack-plugin-serve dev: true - /@storybook/preview-api@7.4.6: - resolution: {integrity: sha512-byUS/Opt3ytWD4cWz3sNEKw5Yks8MkQgRN+GDSyIomaEAQkLAM0rchPC0MYjwCeUSecV7IIQweNX5RbV4a34BA==} + /@storybook/preview-api@7.6.5: + resolution: {integrity: sha512-9XzuDXXgNuA6dDZ3DXsUwEG6ElxeTbzLuYuzcjtS1FusSICZ2iYmxfS0GfSud9MjPPYOJYoSOvMdIHjorjgByA==} dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/channels': 7.6.5 + '@storybook/client-logger': 7.6.5 + '@storybook/core-events': 7.6.5 + '@storybook/csf': 0.1.2 '@storybook/global': 5.0.0 - '@storybook/types': 7.4.6 + '@storybook/types': 7.6.5 '@types/qs': 6.9.10 dequal: 2.0.3 lodash: 4.17.21 @@ -10321,9 +9958,10 @@ packages: synchronous-promise: 2.0.17 ts-dedent: 2.2.0 util-deprecate: 1.0.2 + dev: true - /@storybook/preview@7.4.6: - resolution: {integrity: sha512-2RPXusJ4CTDrIipIKKvbotD7fP0+8VzoFjImunflIrzN9rni+2rq5eMjqlXAaB+77w064zIR4uDUzI9fxsMDeQ==} + /@storybook/preview@7.6.5: + resolution: {integrity: sha512-zmLa7C7yFGTYhgGZXoecdww9rx0Z5HpNi/GDBRWoNSK+FEdE8Jj2jF5NJ2ncldtYIyegz9ku29JFMKbhMj9K5Q==} dev: true /@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.0.4)(webpack@5.76.0): @@ -10345,8 +9983,8 @@ packages: - supports-color dev: true - /@storybook/react-dom-shim@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-DSq8l9FDocUF1ooVI+TF83pddj1LynE/Hv0/y8XZhc3IgJ/HkuOQuUmfz29ezgfAi9gFYUR8raTIBi3/xdoRmw==} + /@storybook/react-dom-shim@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Qp3N3zENdvx20ikHmz5yI03z+mAWF8bUAwUofqXarVtZUkBNtvfTfUwgAezOAF0eClClH+ktIziIKd976tLSPw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -10355,8 +9993,8 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/react-webpack5@7.4.6(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1): - resolution: {integrity: sha512-OSwf+E2tRcfBmzCH+WwM7JlfEYjg5Womi1yrtotfcjVXAU6ubHOk2G87zsrKLp/TeCOFM2aHohHBTyWUCejQKQ==} + /@storybook/react-webpack5@7.6.5(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1): + resolution: {integrity: sha512-tEegTwgn+An2StQ5FixwsIHx7f+ayzpjhnenxOqhiyvOnCg5qleLxCpZGXjq6AH2eeNyBLGr/5bRzwsPgSa3WQ==} engines: {node: '>=16.0.0'} peerDependencies: '@babel/core': ^7.22.0 @@ -10370,18 +10008,16 @@ packages: optional: true dependencies: '@babel/core': 7.23.5 - '@storybook/builder-webpack5': 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1) - '@storybook/preset-react-webpack': 7.4.6(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1) - '@storybook/react': 7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) - '@types/node': 16.18.61 + '@storybook/builder-webpack5': 7.6.5(typescript@5.0.4)(webpack-cli@4.9.1) + '@storybook/preset-react-webpack': 7.6.5(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)(webpack-cli@4.9.1) + '@storybook/react': 7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4) + '@types/node': 18.19.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) typescript: 5.0.4 transitivePeerDependencies: - '@swc/core' - '@swc/helpers' - - '@types/react' - - '@types/react-dom' - '@types/webpack' - encoding - esbuild @@ -10395,8 +10031,8 @@ packages: - webpack-plugin-serve dev: true - /@storybook/react@7.4.6(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4): - resolution: {integrity: sha512-w0dVo64baFFPTGpUOWFqkKsu6pQincoymegSNgqaBd5DxEyMDRiRoTWSJHMKE9BwgE8SyWhRkP1ak1mkccSOhQ==} + /@storybook/react@7.6.5(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4): + resolution: {integrity: sha512-z0l5T+gL//VekMXnHi+lW5qr7OQ8X7WoeIRMk38e62ppSpGUZRfoxRmmhU/9YcIFAlCgMaoLSYmhOceKGRZuVw==} engines: {node: '>=16.0.0'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -10406,16 +10042,16 @@ packages: typescript: optional: true dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-client': 7.4.6 - '@storybook/docs-tools': 7.4.6 + '@storybook/client-logger': 7.6.5 + '@storybook/core-client': 7.6.5 + '@storybook/docs-tools': 7.6.5 '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.4.6 - '@storybook/react-dom-shim': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/preview-api': 7.6.5 + '@storybook/react-dom-shim': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.6.5 '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 - '@types/node': 16.18.61 + '@types/node': 18.19.3 acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) acorn-walk: 7.2.0 @@ -10435,46 +10071,30 @@ packages: - supports-color dev: true - /@storybook/router@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Vl1esrHkcHxDKqc+HY7+6JQpBPW3zYvGk0cQ2rxVMhWdLZTAz1hss9DqzN9tFnPyfn0a1Q77EpMySkUrvWKKNQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + /@storybook/router@7.6.5: + resolution: {integrity: sha512-QiTC86gRuoepzzmS6HNJZTwfz/n27NcqtaVEIxJi1Yvsx2/kLa9NkRhylNkfTuZ1gEry9stAlKWanMsB2aKyjQ==} dependencies: - '@storybook/client-logger': 7.4.6 + '@storybook/client-logger': 7.6.5 memoizerific: 1.11.3 qs: 6.11.2 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + dev: true - /@storybook/source-loader@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-tBso55luaKIsZmIsgYyT7HJcjbgjxf0pdzbYqdThZhY3oSl3d56xbcFDCWW+yWjFONuFY8RGPCT7iGywwmaBdQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + /@storybook/source-loader@7.6.5: + resolution: {integrity: sha512-3GpXJY9GUOOl3Uq/xcsJ12XWLBNZJwUWzwkBm4Eev1xl5eg/ygeyJflwM5egsA1NfkV77hNxtjQcbfw4cBtqdg==} dependencies: - '@storybook/csf': 0.1.1 - '@storybook/types': 7.4.6 + '@storybook/csf': 0.1.2 + '@storybook/types': 7.6.5 estraverse: 5.3.0 lodash: 4.17.21 prettier: 2.8.8 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: true - - /@storybook/store@7.4.6: - resolution: {integrity: sha512-tlm9rQ+djkYjEyCuEjaUv+c+jVgwnMEF9mZxnOoA6zrzU2g0S/1oE9/MdVLByGbH67U0NuuP0FcvsWLhAOQzjQ==} - dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 dev: true - /@storybook/telemetry@7.4.6: - resolution: {integrity: sha512-c8p/C1NIH8EMBviZkBCx8MMDk6rrITJ+b29DEp5MaWSRlklIVyhGiC4RPIRv6sxJwlD41PnqWVFtfu2j2eXLdQ==} + /@storybook/telemetry@7.6.5: + resolution: {integrity: sha512-FiLRh9k9LoGphqgBqPYySWdGqplihiZyDwqdo+Qs19RcQ/eiKg0W7fdA09nStcdcsHmDl/1cMfRhz9KUiMtwOw==} dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-common': 7.4.6 - '@storybook/csf-tools': 7.4.6 + '@storybook/client-logger': 7.6.5 + '@storybook/core-common': 7.6.5 + '@storybook/csf-tools': 7.6.5 chalk: 4.1.2 detect-package-manager: 2.0.1 fetch-retry: 5.0.6 @@ -10485,26 +10105,28 @@ packages: - supports-color dev: true - /@storybook/theming@7.4.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-HW77iJ9ptCMqhoBOYFjRQw7VBap+38fkJGHP5KylEJCyYCgIAm2dEcQmtWpMVYFssSGcb6djfbtAMhYU4TL4Iw==} + /@storybook/theming@7.6.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-RpcWT0YEgiobO41McVPDfQQHHFnjyr1sJnNTPJIvOUgSfURdgSj17mQVxtD5xcXcPWUdle5UhIOrCixHbL/NNw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) - '@storybook/client-logger': 7.4.6 + '@storybook/client-logger': 7.6.5 '@storybook/global': 5.0.0 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true - /@storybook/types@7.4.6: - resolution: {integrity: sha512-6QLXtMVsFZFpzPkdGWsu/iuc8na9dnS67AMOBKm5qCLPwtUJOYkwhMdFRSSeJthLRpzV7JLAL8Kwvl7MFP3QSw==} + /@storybook/types@7.6.5: + resolution: {integrity: sha512-Q757v+fYZZSaEpks/zDL5YgXRozxkgKakXFc+BoQHK5q5sVhJ+0jvpLJiAQAniIIaMIkqY/G24Kd6Uo6UdKBCg==} dependencies: - '@storybook/channels': 7.4.6 + '@storybook/channels': 7.6.5 '@types/babel__core': 7.20.4 '@types/express': 4.17.21 file-system-cache: 2.3.0 + dev: true /@svgr/babel-plugin-add-jsx-attribute@7.0.0(@babel/core@7.23.5): resolution: {integrity: sha512-khWbXesWIP9v8HuKCl2NU2HNAyqpSQ/vkIl36Nbn4HIwEYSRWL0H7Gs6idJdha2DkpFDWlsqMELvoCE8lfFY6Q==} @@ -10715,7 +10337,7 @@ packages: resolution: {integrity: sha512-42Ej9sDDEmsJKjrfQ1PHmiDiHagh/u9AHO9QWbeNx4KmD9yS5d1XHmXUNINfUcykAU+4431Cn+k6Vn5mWBYimQ==} engines: {node: '>=14'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 entities: 4.5.0 dev: true @@ -10723,7 +10345,7 @@ packages: resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==} engines: {node: '>=14'} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 entities: 4.5.0 dev: false @@ -11004,7 +10626,7 @@ packages: resolution: {integrity: sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==} engines: {node: '>=12'} dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 '@babel/runtime': 7.23.5 '@types/aria-query': 5.0.4 aria-query: 5.1.3 @@ -11014,17 +10636,45 @@ packages: pretty-format: 27.5.1 dev: true - /@testing-library/jest-dom@5.17.0: - resolution: {integrity: sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==} - engines: {node: '>=8', npm: '>=6', yarn: '>=1'} + /@testing-library/dom@9.3.3: + resolution: {integrity: sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==} + engines: {node: '>=14'} dependencies: - '@adobe/css-tools': 4.3.1 + '@babel/code-frame': 7.23.5 + '@babel/runtime': 7.23.5 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: true + + /@testing-library/jest-dom@6.1.5(jest@29.7.0): + resolution: {integrity: sha512-3y04JLW+EceVPy2Em3VwNr95dOKqA8DhR0RJHhHKDZNYXcVXnEK7WIrpj4eYU8SVt/qYZ2aRWt/WgQ+grNES8g==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + dependencies: + '@adobe/css-tools': 4.3.2 '@babel/runtime': 7.23.5 - '@types/testing-library__jest-dom': 5.14.9 aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.5.16 + jest: 29.7.0 lodash: 4.17.21 redent: 3.0.0 dev: true @@ -11039,27 +10689,27 @@ packages: preact: 10.12.1 dev: true - /@testing-library/react@13.4.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==} - engines: {node: '>=12'} + /@testing-library/react@14.1.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==} + engines: {node: '>=14'} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 dependencies: - '@babel/runtime': 7.23.2 - '@testing-library/dom': 8.20.1 + '@babel/runtime': 7.23.5 + '@testing-library/dom': 9.3.3 '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@testing-library/user-event@14.5.1(@testing-library/dom@8.20.1): + /@testing-library/user-event@14.5.1(@testing-library/dom@9.3.3): resolution: {integrity: sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==} engines: {node: '>=12', npm: '>=6'} peerDependencies: '@testing-library/dom': '>=7.21.4' dependencies: - '@testing-library/dom': 8.20.1 + '@testing-library/dom': 9.3.3 dev: true /@tootallnate/once@2.0.0: @@ -11077,38 +10727,44 @@ packages: /@types/babel__core@7.20.4: resolution: {integrity: sha512-mLnSC22IC4vcWiuObSRjrLd9XcBTGf59vUSoq2jkQDJ/QQ8PMI9rSuzE+aEV8karUMbskw07bKYoUJCKTUaygg==} dependencies: - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 '@types/babel__generator': 7.6.7 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.4 + dev: true /@types/babel__generator@7.6.7: resolution: {integrity: sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 + dev: true /@types/babel__template@7.4.4: resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} dependencies: - '@babel/parser': 7.23.3 - '@babel/types': 7.23.3 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + dev: true /@types/babel__traverse@7.20.4: resolution: {integrity: sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==} dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 + dev: true /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 '@types/node': 20.9.0 + dev: true /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: '@types/node': 20.9.0 + dev: true /@types/cross-spawn@6.0.5: resolution: {integrity: sha512-wsIMP68FvGXk+RaWhraz6Xp4v7sl4qwzHAmtPaJEN2NRTXXI9LtFawUpeTsBNL/pd6QoLStdytCaAyiK7AEd/Q==} @@ -11130,6 +10786,10 @@ packages: resolution: {integrity: sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==} dev: true + /@types/doctrine@0.0.9: + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} + dev: true + /@types/ejs@3.1.5: resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==} dev: true @@ -11171,6 +10831,7 @@ packages: '@types/qs': 6.9.10 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 + dev: true /@types/express@4.17.21: resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -11179,6 +10840,7 @@ packages: '@types/express-serve-static-core': 4.17.41 '@types/qs': 6.9.10 '@types/serve-static': 1.15.5 + dev: true /@types/find-cache-dir@3.2.1: resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==} @@ -11206,12 +10868,6 @@ packages: /@types/gradient-parser@0.1.3: resolution: {integrity: sha512-XDbrTSBlQV9nxE1GiDL3FaOPy4G/KaJkhDutBX48Kg8CYZMBARyyDFGCWfWJn4pobmInmwud1xxH7VJMAr0CKQ==} - /@types/hast@2.3.8: - resolution: {integrity: sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==} - dependencies: - '@types/unist': 2.0.10 - dev: true - /@types/highlight-words-core@1.2.1: resolution: {integrity: sha512-9VZUA5omXBfn+hDxFjUDu1FOJTBM3LmvqfDey+Z6Aa8B8/JmF5SMj6FBrjfgJ/Q3YXOZd3qyTDfJyMZSs/wCUA==} @@ -11228,6 +10884,7 @@ packages: /@types/http-errors@2.0.4: resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + dev: true /@types/is-stream@1.1.0: resolution: {integrity: sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==} @@ -11295,9 +10952,11 @@ packages: /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + dev: true /@types/mime@3.0.4: resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} + dev: true /@types/minimatch@5.1.2: resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} @@ -11317,8 +10976,10 @@ packages: form-data: 4.0.0 dev: true - /@types/node@16.18.61: - resolution: {integrity: sha512-k0N7BqGhJoJzdh6MuQg1V1ragJiXTh8VUBAZTWjJ9cUq23SG0F0xavOwZbhiP4J3y20xd6jxKx+xNUhkMAi76Q==} + /@types/node@18.19.3: + resolution: {integrity: sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==} + dependencies: + undici-types: 5.26.5 dev: true /@types/node@20.9.0: @@ -11352,9 +11013,11 @@ packages: /@types/qs@6.9.10: resolution: {integrity: sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==} + dev: true /@types/range-parser@1.2.7: resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: true /@types/react-dom@18.2.14: resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==} @@ -11395,6 +11058,10 @@ packages: '@types/node': 20.9.0 dev: true + /@types/resolve@1.20.6: + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + dev: true + /@types/retry@0.12.0: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} @@ -11410,6 +11077,7 @@ packages: dependencies: '@types/mime': 1.3.5 '@types/node': 20.9.0 + dev: true /@types/serve-static@1.15.5: resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} @@ -11417,6 +11085,7 @@ packages: '@types/http-errors': 2.0.4 '@types/mime': 3.0.4 '@types/node': 20.9.0 + dev: true /@types/simple-peer@9.11.8: resolution: {integrity: sha512-rvqefdp2rvIA6wiomMgKWd2UZNPe6LM2EV5AuY3CPQJF+8TbdrL5TjYdMf0VAjGczzlkH4l1NjDkihwbj3Xodw==} @@ -11453,6 +11122,9 @@ packages: resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} dev: true + /@types/uuid@9.0.7: + resolution: {integrity: sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==} + /@types/wordpress__block-editor@11.5.6(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-e21dIN68/2/YFaqlmXye1XkATfv3dA9aX+m9amfJOzuY5y8v1EL/p92Kym0W7jde0NmNeSg31XwKRd9C0sE2lw==} dependencies: @@ -13726,6 +13398,7 @@ packages: /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -14107,20 +13780,6 @@ packages: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} dev: true - /ast-types@0.14.2: - resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} - engines: {node: '>=4'} - dependencies: - tslib: 2.5.0 - dev: true - - /ast-types@0.15.2: - resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==} - engines: {node: '>=4'} - dependencies: - tslib: 2.5.0 - dev: true - /ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} @@ -14301,7 +13960,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/template': 7.22.15 - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 '@types/babel__core': 7.20.4 '@types/babel__traverse': 7.20.4 dev: true @@ -14314,10 +13973,6 @@ packages: cosmiconfig: 7.1.0 resolve: 1.22.8 - /babel-plugin-named-exports-order@0.0.2: - resolution: {integrity: sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw==} - dev: true - /babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.23.5): resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==} peerDependencies: @@ -14351,16 +14006,6 @@ packages: transitivePeerDependencies: - supports-color - /babel-plugin-react-docgen@4.2.1: - resolution: {integrity: sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ==} - dependencies: - ast-types: 0.14.2 - lodash: 4.17.21 - react-docgen: 5.4.3 - transitivePeerDependencies: - - supports-color - dev: true - /babel-plugin-tester@11.0.4(@babel/core@7.23.5): resolution: {integrity: sha512-cqswtpSPo0e++rZB0l/54EG17LL25l9gLgh59yXfnmNxX+2lZTIOpx2zt4YI9QIClVXc8xf63J6yWwKkzy0jNg==} engines: {node: ^14.20.0 || ^16.16.0 || >=18.5.0} @@ -14588,31 +14233,13 @@ packages: engines: {node: '>= 0.8'} dev: true - /c8@7.14.0: - resolution: {integrity: sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw==} - engines: {node: '>=10.12.0'} - hasBin: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@istanbuljs/schema': 0.1.3 - find-up: 5.0.0 - foreground-child: 2.0.0 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-report: 3.0.1 - istanbul-reports: 3.1.6 - rimraf: 3.0.2 - test-exclude: 6.0.0 - v8-to-istanbul: 9.1.3 - yargs: 16.2.0 - yargs-parser: 20.2.9 - dev: true - /call-bind@1.0.5: resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} dependencies: function-bind: 1.1.2 get-intrinsic: 1.2.2 set-function-length: 1.1.1 + dev: true /callsite@1.0.0: resolution: {integrity: sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==} @@ -14726,22 +14353,10 @@ packages: engines: {node: '>=10'} dev: true - /character-entities-legacy@1.1.4: - resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} - dev: true - - /character-entities@1.2.4: - resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} - dev: true - /character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} dev: true - /character-reference-invalid@1.1.4: - resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} - dev: true - /chart.js@3.7.1: resolution: {integrity: sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==} dev: false @@ -14877,14 +14492,6 @@ packages: strip-ansi: 5.2.0 wrap-ansi: 5.1.0 - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -15012,10 +14619,6 @@ packages: dependencies: delayed-stream: 1.0.0 - /comma-separated-tokens@1.0.8: - resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} - dev: true - /command-score@0.1.2: resolution: {integrity: sha512-VtDvQpIJBvBatnONUsPzXYFVKQQAhuf3XTNOAsdBxCNO/QCtUUd8LSgjn0GVarBkCad6aJCZfXgrjYbl/KRr7w==} @@ -15672,6 +15275,7 @@ packages: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.1 + dev: true /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} @@ -15768,11 +15372,6 @@ packages: resolution: {integrity: sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==} dev: true - /diff-sequences@27.5.1: - resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -15853,6 +15452,7 @@ packages: /domexception@4.0.0: resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead dependencies: webidl-conversions: 7.0.0 @@ -16151,6 +15751,10 @@ packages: /es-module-lexer@0.9.3: resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + /es-module-lexer@1.4.1: + resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} + dev: true + /es-set-tostringtag@2.0.2: resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} engines: {node: '>= 0.4'} @@ -16743,17 +16347,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - /estree-to-babel@3.2.1: - resolution: {integrity: sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==} - engines: {node: '>=8.3.0'} - dependencies: - '@babel/traverse': 7.23.3 - '@babel/types': 7.23.3 - c8: 7.14.0 - transitivePeerDependencies: - - supports-color - dev: true - /estree-walker@0.2.1: resolution: {integrity: sha512-6/I1dwNKk0N9iGOU3ydzAAurz4NPo/ttxZNCqgIVbWFvWyzWBSNonRrJ5CpjDuyBfmM7ENN7WCzUi9aT/UPXXQ==} dev: true @@ -16976,12 +16569,6 @@ packages: dependencies: reusify: 1.0.4 - /fault@1.0.4: - resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} - dependencies: - format: 0.2.2 - dev: true - /fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} dependencies: @@ -17029,6 +16616,7 @@ packages: dependencies: fs-extra: 11.1.1 ramda: 0.29.0 + dev: true /filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -17166,14 +16754,6 @@ packages: is-callable: 1.2.7 dev: true - /foreground-child@2.0.0: - resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} - engines: {node: '>=8.0.0'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 3.0.7 - dev: true - /foreground-child@3.1.1: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} @@ -17189,7 +16769,7 @@ packages: typescript: '>3.6.0' webpack: ^5.11.0 dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 chalk: 4.1.2 chokidar: 3.5.3 cosmiconfig: 7.1.0 @@ -17221,11 +16801,6 @@ packages: combined-stream: 1.0.8 mime-types: 2.1.35 - /format@0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - dev: true - /forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -17277,6 +16852,7 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 + dev: true /fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} @@ -17365,6 +16941,7 @@ packages: has-proto: 1.0.1 has-symbols: 1.0.3 hasown: 2.0.0 + dev: true /get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} @@ -17579,6 +17156,7 @@ packages: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.2 + dev: true /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -17652,14 +17230,17 @@ packages: resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} dependencies: get-intrinsic: 1.2.2 + dev: true /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} + dev: true /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} + dev: true /has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} @@ -17679,20 +17260,6 @@ packages: dependencies: function-bind: 1.1.2 - /hast-util-parse-selector@2.2.5: - resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} - dev: true - - /hastscript@6.0.0: - resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} - dependencies: - '@types/hast': 2.3.8 - comma-separated-tokens: 1.0.8 - hast-util-parse-selector: 2.2.5 - property-information: 5.6.0 - space-separated-tokens: 1.1.5 - dev: true - /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true @@ -17707,10 +17274,6 @@ packages: /highlight-words-core@1.2.2: resolution: {integrity: sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg==} - /highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - dev: true - /history@4.10.1: resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} dependencies: @@ -18008,17 +17571,6 @@ packages: engines: {node: '>=8'} dev: true - /is-alphabetical@1.0.4: - resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} - dev: true - - /is-alphanumerical@1.0.4: - resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} - dependencies: - is-alphabetical: 1.0.4 - is-decimal: 1.0.4 - dev: true - /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -18098,10 +17650,6 @@ packages: has-tostringtag: 1.0.0 dev: true - /is-decimal@1.0.4: - resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} - dev: true - /is-deflate@1.0.0: resolution: {integrity: sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==} dev: true @@ -18169,10 +17717,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /is-hexadecimal@1.0.4: - resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} - dev: true - /is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -18397,7 +17941,7 @@ packages: engines: {node: '>=8'} dependencies: '@babel/core': 7.23.5 - '@babel/parser': 7.23.3 + '@babel/parser': 7.23.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -18410,7 +17954,7 @@ packages: engines: {node: '>=10'} dependencies: '@babel/core': 7.23.5 - '@babel/parser': 7.23.3 + '@babel/parser': 7.23.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.5.4 @@ -18621,16 +18165,6 @@ packages: - supports-color dev: true - /jest-diff@27.5.1: - resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 27.5.1 - jest-get-type: 27.5.1 - pretty-format: 27.5.1 - dev: true - /jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -18694,20 +18228,18 @@ packages: jest-util: 29.7.0 dev: true - /jest-extended@2.0.0(jest@29.7.0): - resolution: {integrity: sha512-6AgjJQVaBEKGSK3FH90kOiRUWJsbzn9NWtW0pjGkAFIdH0oPilfkV/gHPJdVvJeBiqT3jMHw8TUg9pUGC1azDg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + /jest-extended@4.0.2(jest@29.7.0): + resolution: {integrity: sha512-FH7aaPgtGYHc9mRjriS0ZEHYM5/W69tLrFTIdzm+yJgeoCmmrSB/luSfMSqWP9O29QWHPEmJ4qmU6EwsZideog==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: jest: '>=27.2.5' + peerDependenciesMeta: + jest: + optional: true dependencies: jest: 29.7.0 - jest-diff: 27.5.1 - jest-get-type: 27.5.1 - dev: true - - /jest-get-type@27.5.1: - resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + jest-diff: 29.7.0 + jest-get-type: 29.6.3 dev: true /jest-get-type@29.6.3: @@ -18756,7 +18288,7 @@ packages: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -18882,10 +18414,10 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/core': 7.23.5 - '@babel/generator': 7.23.3 + '@babel/generator': 7.23.6 '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5) '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.5) - '@babel/types': 7.23.3 + '@babel/types': 7.23.6 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 @@ -19005,18 +18537,22 @@ packages: dependencies: argparse: 2.0.1 - /jscodeshift@0.14.0(@babel/preset-env@7.23.5): - resolution: {integrity: sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==} + /jscodeshift@0.15.1(@babel/preset-env@7.23.5): + resolution: {integrity: sha512-hIJfxUy8Rt4HkJn/zZPU9ChKfKZM1342waJ1QC2e2YsPcWhM+3BJ4dcfQCzArTrk1jJeNLB341H+qOcEHRxJZg==} hasBin: true peerDependencies: '@babel/preset-env': ^7.1.6 + peerDependenciesMeta: + '@babel/preset-env': + optional: true dependencies: '@babel/core': 7.23.5 - '@babel/parser': 7.23.3 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.23.5) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.23.5) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.23.5) + '@babel/parser': 7.23.6 + '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.23.5) '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.5) + '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.23.5) + '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.5) + '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.23.5) '@babel/preset-env': 7.23.5(@babel/core@7.23.5) '@babel/preset-flow': 7.23.3(@babel/core@7.23.5) '@babel/preset-typescript': 7.23.3(@babel/core@7.23.5) @@ -19028,7 +18564,7 @@ packages: micromatch: 4.0.5 neo-async: 2.6.2 node-dir: 0.1.17 - recast: 0.21.5 + recast: 0.23.4 temp: 0.8.4 write-file-atomic: 2.4.3 transitivePeerDependencies: @@ -19141,6 +18677,7 @@ packages: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 + dev: true /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} @@ -19501,13 +19038,6 @@ packages: dependencies: tslib: 2.5.0 - /lowlight@1.20.0: - resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} - dependencies: - fault: 1.0.4 - highlight.js: 10.7.3 - dev: true - /lru-cache@10.0.2: resolution: {integrity: sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==} engines: {node: 14 || >=16.14} @@ -19544,6 +19074,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + /make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -19577,6 +19114,7 @@ packages: /map-or-similar@1.5.0: resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} + dev: true /mapbox-gl@1.13.0: resolution: {integrity: sha512-g8zlzuJxYJqbOPXT19/UBYpVrcefBQ06F/Cbj0fyEfFnFesDcU3cFTxd75/FZ6Upx2ZEjCsD61CHxrcxZidVpA==} @@ -19789,6 +19327,7 @@ packages: resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} dependencies: map-or-similar: 1.5.0 + dev: true /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} @@ -20414,6 +19953,7 @@ packages: /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true /object-is@1.1.5: resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} @@ -20677,22 +20217,11 @@ packages: /parse-diff@0.8.1: resolution: {integrity: sha512-0QG0HqwXCC/zMohOlaxkQmV1igZq1LQ6xsv/ziex6TDbY0GFxr3TDJN+/aHjWH3s2WTysSW3Bhs9Yfh6DOelFA==} - /parse-entities@2.0.0: - resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} - dependencies: - character-entities: 1.2.4 - character-entities-legacy: 1.1.4 - character-reference-invalid: 1.1.4 - is-alphanumerical: 1.0.4 - is-decimal: 1.0.4 - is-hexadecimal: 1.0.4 - dev: true - /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -21344,16 +20873,6 @@ packages: engines: {node: '>= 0.8'} dev: true - /prismjs@1.27.0: - resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==} - engines: {node: '>=6'} - dev: true - - /prismjs@1.29.0: - resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} - engines: {node: '>=6'} - dev: true - /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true @@ -21413,12 +20932,6 @@ packages: engines: {node: '>=0.10'} dev: true - /property-information@5.6.0: - resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} - dependencies: - xtend: 4.0.2 - dev: true - /protocol-buffers-schema@3.6.0: resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} dev: false @@ -21541,6 +21054,7 @@ packages: engines: {node: '>=0.6'} dependencies: side-channel: 1.0.4 + dev: true /qss@2.0.3: resolution: {integrity: sha512-j48ZBT5IZbSqJiSU8EX4XrN8nXiflHvmMvv2XpFc31gh7n6EpSs75bNr6+oj3FOLWyT8m09pTmqLNl34L7/uPQ==} @@ -21559,6 +21073,7 @@ packages: /ramda@0.29.0: resolution: {integrity: sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==} + dev: true /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} @@ -21618,21 +21133,20 @@ packages: typescript: 5.0.4 dev: true - /react-docgen@5.4.3: - resolution: {integrity: sha512-xlLJyOlnfr8lLEEeaDZ+X2J/KJoe6Nr9AzxnkdQWush5hz2ZSu66w6iLMOScMmxoSHWpWMn+k3v5ZiyCfcWsOA==} - engines: {node: '>=8.10.0'} - hasBin: true + /react-docgen@7.0.1: + resolution: {integrity: sha512-rCz0HBIT0LWbIM+///LfRrJoTKftIzzwsYDf0ns5KwaEjejMHQRtphcns+IXFHDNY9pnz6G8l/JbbI6pD4EAIA==} + engines: {node: '>=16.14.0'} dependencies: '@babel/core': 7.23.5 - '@babel/generator': 7.23.3 - '@babel/runtime': 7.23.5 - ast-types: 0.14.2 - commander: 2.20.3 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + '@types/babel__core': 7.20.4 + '@types/babel__traverse': 7.20.4 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 doctrine: 3.0.0 - estree-to-babel: 3.2.1 - neo-async: 2.6.2 - node-dir: 0.1.17 - strip-indent: 3.0.0 + resolve: 1.22.8 + strip-indent: 4.0.0 transitivePeerDependencies: - supports-color dev: true @@ -21670,13 +21184,6 @@ packages: react-is: 18.1.0 dev: true - /react-inspector@6.0.2(react@18.2.0): - resolution: {integrity: sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==} - peerDependencies: - react: ^16.8.4 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.2.0 - /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -21723,8 +21230,8 @@ packages: react-is: 17.0.2 dev: false - /react-refresh@0.11.0: - resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} + /react-refresh@0.14.0: + resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} engines: {node: '>=0.10.0'} dev: true @@ -21827,17 +21334,6 @@ packages: use-callback-ref: 1.3.0(react@18.2.0) use-sidecar: 1.1.2(react@18.2.0) - /react-resize-detector@7.1.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw==} - peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - lodash: 4.17.21 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: true - /react-router-dom@5.3.4(react@18.2.0): resolution: {integrity: sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==} peerDependencies: @@ -21891,6 +21387,19 @@ packages: react-router: 6.2.2(react@18.2.0) dev: false + /react-router-dom@6.21.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1dUdVj3cwc1npzJaf23gulB562ESNvxf7E4x8upNJycqyUm5BRRZ6dd3LrlzhtLaMrwOCO8R0zoiYxdaJx4LlQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + '@remix-run/router': 1.14.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-router: 6.21.0(react@18.2.0) + dev: false + /react-router-dom@6.6.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-6SCDXxRQqW5af8ImOqKza7icmQ47/EMbz572uFjzvcArg3lZ+04PxSPp8qGs+p2Y+q+b+S/AjXv8m8dyLndIIA==} engines: {node: '>=14'} @@ -21950,6 +21459,16 @@ packages: react: 18.2.0 dev: false + /react-router@6.21.0(react@18.2.0): + resolution: {integrity: sha512-hGZ0HXbwz3zw52pLZV3j3+ec+m/PQ9cTpBvqjFQmy2XVUWGn5MD+31oXHb6dVTxYzmAeaiUBYjkoNz66n3RGCg==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + dependencies: + '@remix-run/router': 1.14.0 + react: 18.2.0 + dev: false + /react-router@6.6.2(react@18.2.0): resolution: {integrity: sha512-uJPG55Pek3orClbURDvfljhqFvMgJRo59Pktywkk8hUUkTY2aRfza8Yhl/vZQXs+TNQyr6tu+uqz/fLxPICOGQ==} engines: {node: '>=14'} @@ -21970,13 +21489,13 @@ packages: react-is: 18.2.0 dev: true - /react-slider@2.0.5(@babel/runtime@7.23.2)(react@18.2.0): + /react-slider@2.0.5(@babel/runtime@7.23.5)(react@18.2.0): resolution: {integrity: sha512-MU5gaK1yYCKnbDDN3CMiVcgkKZwMvdqK2xUEW7fFU37NAzRgS1FZbF9N7vP08E3XXNVhiuZnwVzUa3PYQAZIMg==} peerDependencies: '@babel/runtime': ^7 react: ^16 || ^17 || ^18 dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.5 prop-types: 15.8.1 react: 18.2.0 dev: false @@ -22012,19 +21531,6 @@ packages: react: 18.2.0 tslib: 2.5.0 - /react-syntax-highlighter@15.5.0(react@18.2.0): - resolution: {integrity: sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==} - peerDependencies: - react: '>= 0.14.0' - dependencies: - '@babel/runtime': 7.23.5 - highlight.js: 10.7.3 - lowlight: 1.20.0 - prismjs: 1.29.0 - react: 18.2.0 - refractor: 3.6.0 - dev: true - /react-test-renderer@18.2.0(react@18.2.0): resolution: {integrity: sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==} peerDependencies: @@ -22151,16 +21657,6 @@ packages: reakit-utils: 0.15.2(react-dom@18.2.0)(react@18.2.0) reakit-warning: 0.6.2(react-dom@18.2.0)(react@18.2.0) - /recast@0.21.5: - resolution: {integrity: sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==} - engines: {node: '>= 4'} - dependencies: - ast-types: 0.15.2 - esprima: 4.0.1 - source-map: 0.6.1 - tslib: 2.5.0 - dev: true - /recast@0.23.4: resolution: {integrity: sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==} engines: {node: '>= 4'} @@ -22224,14 +21720,6 @@ packages: which-builtin-type: 1.1.3 dev: true - /refractor@3.6.0: - resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==} - dependencies: - hastscript: 6.0.0 - parse-entities: 2.0.0 - prismjs: 1.27.0 - dev: true - /refx@3.1.1: resolution: {integrity: sha512-lwN27W5iYyagpCxxYDYDl0IIiKh0Vgi3wvafqfthbzTfBgLOYAstcftp+G2X612xVaB8rhn5wDxd4er4KEeb8A==} dev: false @@ -22814,6 +22302,7 @@ packages: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.1 + dev: true /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} @@ -22864,6 +22353,7 @@ packages: call-bind: 1.0.5 get-intrinsic: 1.2.2 object-inspect: 1.13.1 + dev: true /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -23096,6 +22586,7 @@ packages: /store2@2.14.2: resolution: {integrity: sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==} + dev: true /storybook-addon-mock@4.3.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-N4Yepagkom0t5jk6ur3wrtGVeOYTlGx9LX6jg8iRhFbhrpfcbr+6XhmAQSE/3FiNQXwHiwdo1Az8MvlzwymcUA==} @@ -23108,20 +22599,20 @@ packages: react-dom: optional: true dependencies: - '@storybook/addons': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/blocks': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/channels': 7.5.3 - '@storybook/components': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.5.3 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0) + '@storybook/addons': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/blocks': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/channels': 7.6.5 + '@storybook/components': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.6.5 + '@storybook/manager-api': 7.6.5(react-dom@18.2.0)(react@18.2.0) + '@storybook/theming': 7.6.5(react-dom@18.2.0)(react@18.2.0) mock-xmlhttprequest: 8.2.0 path-to-regexp: 6.2.1 polished: 4.2.2 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - storybook: 7.4.6 + storybook: 7.6.5 whatwg-fetch: 3.6.19 transitivePeerDependencies: - '@types/react' @@ -23132,11 +22623,11 @@ packages: - utf-8-validate dev: true - /storybook@7.4.6: - resolution: {integrity: sha512-YkFSpnR47j5zz7yElA+2axLjXN7K7TxDGJRHHlqXmG5iQ0PXzmjrj2RxMDKFz4Ybp/QjEUoJ4rx//ESEY0Nb5A==} + /storybook@7.6.5: + resolution: {integrity: sha512-uHPrL+g/0v6iIVtDA8J0uWd3jDZcdr51lCR/vPXTkrCY1uVaFjswzl8EMy5PR05I7jMpKUzkJWZtFbgbh9e1Bw==} hasBin: true dependencies: - '@storybook/cli': 7.4.6 + '@storybook/cli': 7.6.5 transitivePeerDependencies: - bufferutil - encoding @@ -23310,6 +22801,13 @@ packages: min-indent: 1.0.1 dev: true + /strip-indent@4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} + dependencies: + min-indent: 1.0.1 + dev: true + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -23509,6 +23007,7 @@ packages: /synchronous-promise@2.0.17: resolution: {integrity: sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==} + dev: true /synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} @@ -23567,6 +23066,7 @@ packages: resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} dependencies: memoizerific: 1.11.3 + dev: true /temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} @@ -23942,6 +23442,7 @@ packages: /type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} + dev: true /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} @@ -24140,6 +23641,7 @@ packages: /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + dev: true /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} @@ -24289,6 +23791,7 @@ packages: '@juggle/resize-observer': 3.4.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + dev: true /use-sidecar@1.1.2(@types/react@18.2.33)(react@18.2.0): resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} @@ -24918,7 +24421,6 @@ packages: lib0: 0.2.87 simple-peer: 9.11.1 y-protocols: 1.0.6(yjs@13.6.8) - yjs: 13.6.8 optionalDependencies: ws: 7.5.9 transitivePeerDependencies: @@ -24955,11 +24457,6 @@ packages: camelcase: 5.3.1 decamelize: 1.2.0 - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true - /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -24979,19 +24476,6 @@ packages: y18n: 4.0.3 yargs-parser: 15.0.3 - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: true - /yargs@17.6.2: resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} engines: {node: '>=12'} @@ -25037,7 +24521,6 @@ packages: resolution: {tarball: https://codeload.github.com/automattic/jetpack-boost-critical-css-gen/tar.gz/56adf5a550475fd30962cd4e8f8bfcaf71f84177} name: jetpack-boost-critical-css-gen version: 0.0.11 - prepare: true requiresBuild: true dependencies: clean-css: 5.3.2 diff --git a/projects/js-packages/ai-client/CHANGELOG.md b/projects/js-packages/ai-client/CHANGELOG.md index 397156ea60e3f..1c63c502652b8 100644 --- a/projects/js-packages/ai-client/CHANGELOG.md +++ b/projects/js-packages/ai-client/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.0] - 2023-12-20 +### Changed +- AI Client: improved usability with new block positioning, prompt and suggestion action buttons. [#34383] +- Updated package dependencies. [#34696] + ## [0.2.1] - 2023-12-03 ### Changed - Updated the prompt shadow for a better sense of depth. [#34362] @@ -171,6 +176,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated package dependencies. [#31659] - Updated package dependencies. [#31785] +[0.3.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/Automattic/jetpack-ai-client/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.1.16...v0.2.0 [0.1.16]: https://github.com/Automattic/jetpack-ai-client/compare/v0.1.15...v0.1.16 diff --git a/projects/js-packages/ai-client/package.json b/projects/js-packages/ai-client/package.json index 5fa557b5bb0f4..9658f26fd5b31 100644 --- a/projects/js-packages/ai-client/package.json +++ b/projects/js-packages/ai-client/package.json @@ -1,7 +1,7 @@ { "private": false, "name": "@automattic/jetpack-ai-client", - "version": "0.2.1", + "version": "0.3.0", "description": "A JS client for consuming Jetpack AI services", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/ai-client/#readme", "bugs": { @@ -22,9 +22,9 @@ }, "type": "module", "devDependencies": { - "@storybook/addon-actions": "7.4.6", - "@storybook/blocks": "7.4.6", - "@storybook/react": "7.4.6", + "@storybook/addon-actions": "7.6.5", + "@storybook/blocks": "7.6.5", + "@storybook/react": "7.6.5", "jest": "^29.6.2", "jest-environment-jsdom": "29.7.0", "typescript": "5.0.4" diff --git a/projects/js-packages/ai-client/src/components/ai-control/Readme.md b/projects/js-packages/ai-client/src/components/ai-control/Readme.md index e4d9c300d6065..00f4897812c39 100644 --- a/projects/js-packages/ai-client/src/components/ai-control/Readme.md +++ b/projects/js-packages/ai-client/src/components/ai-control/Readme.md @@ -11,6 +11,8 @@ - `isTransparent` (**boolean**) (Optional): Controls the opacity of the component. Default value is `false`. - `state` (**RequestingStateProp**) (Optional): Determines the state of the component. Default value is `'init'`. - `showClearButton` (**boolean**) (Optional): Determines if the clear button is shown when the input has a value. Default value is `true`. +- `showGuideLine`: (**boolean**) (Optional): Whether to show the usual AI guidelines at the bottom of the input. +- `customFooter`: (**ReactElement**) (Optional): if provided together with `showGuideLine` it will be rendered at the bottom of the input. - `onChange` (**Function**) (Optional): Handler for input change. Default action is no operation. - `onSend` (**Function**) (Optional): Handler to send a request. Default action is no operation. - `onStop` (**Function**) (Optional): Handler to stop a request. Default action is no operation. @@ -19,6 +21,8 @@ #### Example Usage ```jsx +import { AIControl, FooterMessage } from '@automattic/jetpack-ai-client'; + Remember AI suggestions can be inaccurate } /> -``` \ No newline at end of file +``` diff --git a/projects/js-packages/ai-client/src/components/ai-control/index.tsx b/projects/js-packages/ai-client/src/components/ai-control/index.tsx index 46bf70fc916af..4d8abb26d6199 100644 --- a/projects/js-packages/ai-client/src/components/ai-control/index.tsx +++ b/projects/js-packages/ai-client/src/components/ai-control/index.tsx @@ -2,11 +2,17 @@ * External dependencies */ import { PlainText } from '@wordpress/block-editor'; -import { Button } from '@wordpress/components'; +import { Button, ButtonGroup } from '@wordpress/components'; import { useKeyboardShortcut } from '@wordpress/compose'; -import { forwardRef, useImperativeHandle, useRef } from '@wordpress/element'; +import { + forwardRef, + useImperativeHandle, + useRef, + useEffect, + useCallback, +} from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { Icon, closeSmall, check, arrowUp } from '@wordpress/icons'; +import { Icon, closeSmall, check, arrowUp, trash, reusableBlock } from '@wordpress/icons'; import classNames from 'classnames'; import React from 'react'; /** @@ -19,7 +25,7 @@ import { GuidelineMessage } from './message'; * Types */ import type { RequestingStateProp } from '../../types'; -type AIControlProps = { +type AiControlProps = { disabled?: boolean; value: string; placeholder?: string; @@ -28,12 +34,14 @@ type AIControlProps = { showButtonLabels?: boolean; isTransparent?: boolean; state?: RequestingStateProp; - showClearButton?: boolean; showGuideLine?: boolean; + customFooter?: React.ReactElement; onChange?: ( newValue: string ) => void; onSend?: ( currentValue: string ) => void; onStop?: () => void; onAccept?: () => void; + onDiscard?: () => void; + showRemove?: boolean; }; // eslint-disable-next-line @typescript-eslint/no-empty-function @@ -42,7 +50,7 @@ const noop = () => {}; /** * AI Control component. * - * @param {AIControlProps} props - Component props. + * @param {AiControlProps} props - Component props. * @param {React.MutableRefObject} ref - Ref to the component. * @returns {React.ReactElement} Rendered component. */ @@ -56,32 +64,65 @@ export function AIControl( showButtonLabels = true, isTransparent = false, state = 'init', - showClearButton = true, showGuideLine = false, + customFooter = null, onChange = noop, onSend = noop, onStop = noop, onAccept = noop, - }: { - disabled?: boolean; - value: string; - placeholder?: string; - showAccept?: boolean; - acceptLabel?: string; - showButtonLabels?: boolean; - isTransparent?: boolean; - state?: RequestingStateProp; - showClearButton?: boolean; - showGuideLine?: boolean; - onChange?: ( newValue: string ) => void; - onSend?: ( currentValue: string ) => void; - onStop?: () => void; - onAccept?: () => void; - }, + onDiscard = null, + showRemove = false, + }: AiControlProps, ref: React.MutableRefObject< null > // eslint-disable-line @typescript-eslint/ban-types ): React.ReactElement { const promptUserInputRef = useRef( null ); const loading = state === 'requesting' || state === 'suggesting'; + const [ editRequest, setEditRequest ] = React.useState( false ); + const [ lastValue, setLastValue ] = React.useState( value || null ); + + useEffect( () => { + if ( editRequest ) { + promptUserInputRef?.current?.focus(); + } + + if ( ! editRequest && lastValue !== null && value !== lastValue ) { + onChange?.( lastValue ); + } + }, [ editRequest, lastValue, value ] ); + + const sendRequest = useCallback( () => { + setLastValue( value ); + setEditRequest( false ); + onSend?.( value ); + }, [ value ] ); + + const changeHandler = useCallback( + ( newValue: string ) => { + onChange?.( newValue ); + if ( state === 'init' ) { + return; + } + + if ( ! lastValue ) { + // here we're coming from a one-click action + setEditRequest( newValue.length > 0 ); + } else { + // here we're coming from an edit action + setEditRequest( newValue !== lastValue ); + } + }, + [ lastValue, state ] + ); + + const discardHandler = useCallback( () => { + onDiscard?.(); + onAccept?.(); + }, [] ); + + const cancelEdit = useCallback( () => { + onChange( lastValue || '' ); + setEditRequest( false ); + }, [ lastValue ] ); // Pass the ref to forwardRef. useImperativeHandle( ref, () => promptUserInputRef.current ); @@ -102,85 +143,137 @@ export function AIControl( 'enter', e => { e.preventDefault(); - onSend?.( value ); + sendRequest(); }, { target: promptUserInputRef, } ); - const actionButtonClasses = classNames( 'jetpack-components-ai-control__controls-prompt_button', { - 'has-label': showButtonLabels, - } ); - return ( -
-
- - -
- - </div> + <div className="jetpack-components-ai-control__container-wrapper"> + <div className="jetpack-components-ai-control__container"> + <div + className={ classNames( 'jetpack-components-ai-control__wrapper', { + 'is-transparent': isTransparent, + } ) } + > + <AiStatusIndicator state={ state } /> + + <div className="jetpack-components-ai-control__input-wrapper"> + <PlainText + value={ value } + onChange={ changeHandler } + placeholder={ placeholder } + className="jetpack-components-ai-control__input" + disabled={ loading || disabled } + ref={ promptUserInputRef } + /> + </div> + + { ( ! showAccept || editRequest ) && ( + <div className="jetpack-components-ai-control__controls-prompt_button_wrapper"> + { ! loading ? ( + <> + { editRequest && ( + <Button + className="jetpack-components-ai-control__controls-prompt_button" + onClick={ cancelEdit } + variant="secondary" + label={ __( 'Cancel', 'jetpack-ai-client' ) } + > + { showButtonLabels ? ( + __( 'Cancel', 'jetpack-ai-client' ) + ) : ( + <Icon icon={ closeSmall } /> + ) } + </Button> + ) } - { value?.length > 0 && showClearButton && ( - <Button - icon={ closeSmall } - className="jetpack-components-ai-control__clear" - onClick={ () => onChange( '' ) } - /> - ) } - - <div className="jetpack-components-ai-control__controls-prompt_button_wrapper"> - { ! loading ? ( - <Button - className={ actionButtonClasses } - onClick={ () => onSend?.( value ) } - isSmall={ true } - disabled={ ! value?.length || disabled } - label={ __( 'Send request', 'jetpack-ai-client' ) } - > - <Icon icon={ arrowUp } /> - { showButtonLabels && __( 'Send', 'jetpack-ai-client' ) } - </Button> - ) : ( - <Button - className={ actionButtonClasses } - onClick={ onStop } - isSmall={ true } - label={ __( 'Stop request', 'jetpack-ai-client' ) } - > - <Icon icon={ closeSmall } /> - { showButtonLabels && __( 'Stop (ESC)', 'jetpack-ai-client' ) } - </Button> + { showRemove && ! editRequest && ! value?.length && onDiscard && ( + <Button + className="jetpack-components-ai-control__controls-prompt_button" + onClick={ discardHandler } + variant="secondary" + label={ __( 'Cancel', 'jetpack-ai-client' ) } + > + { showButtonLabels ? ( + __( 'Cancel', 'jetpack-ai-client' ) + ) : ( + <Icon icon={ closeSmall } /> + ) } + </Button> + ) } + + { value?.length > 0 && ( + <Button + className="jetpack-components-ai-control__controls-prompt_button" + onClick={ sendRequest } + variant="primary" + disabled={ ! value?.length || disabled } + label={ __( 'Send request', 'jetpack-ai-client' ) } + > + { showButtonLabels ? ( + __( 'Generate', 'jetpack-ai-client' ) + ) : ( + <Icon icon={ arrowUp } /> + ) } + </Button> + ) } + </> + ) : ( + <Button + className="jetpack-components-ai-control__controls-prompt_button" + onClick={ onStop } + variant="secondary" + label={ __( 'Stop request', 'jetpack-ai-client' ) } + > + { showButtonLabels ? ( + __( 'Stop', 'jetpack-ai-client' ) + ) : ( + <Icon icon={ closeSmall } /> + ) } + </Button> + ) } + </div> ) } - </div> - { showAccept && ( - <div className="jetpack-components-ai-control__controls-prompt_button_wrapper"> - <Button - className={ actionButtonClasses } - onClick={ onAccept } - isSmall={ true } - label={ acceptLabel } - > - <Icon icon={ check } /> - { showButtonLabels && acceptLabel } - </Button> - </div> - ) } + { showAccept && ! editRequest && ( + <div className="jetpack-components-ai-control__controls-prompt_button_wrapper"> + { ( value?.length > 0 || lastValue === null ) && ( + <ButtonGroup> + <Button + className="jetpack-components-ai-control__controls-prompt_button" + label={ __( 'Discard', 'jetpack-ai-client' ) } + onClick={ discardHandler } + tooltipPosition="top" + > + <Icon icon={ trash } /> + </Button> + <Button + className="jetpack-components-ai-control__controls-prompt_button" + label={ __( 'Regenerate', 'jetpack-ai-client' ) } + onClick={ () => onSend?.( value ) } + tooltipPosition="top" + disabled={ ! value?.length || value === null || disabled } + > + <Icon icon={ reusableBlock } /> + </Button> + </ButtonGroup> + ) } + <Button + className="jetpack-components-ai-control__controls-prompt_button" + onClick={ onAccept } + variant="primary" + label={ acceptLabel } + > + { showButtonLabels ? acceptLabel : <Icon icon={ check } /> } + </Button> + </div> + ) } + </div> + { showGuideLine && ! loading && ! editRequest && ( customFooter || <GuidelineMessage /> ) } </div> - { showGuideLine && <GuidelineMessage /> } </div> ); } diff --git a/projects/js-packages/ai-client/src/components/ai-control/style.scss b/projects/js-packages/ai-client/src/components/ai-control/style.scss index 4d458bba62faa..0bbc0fb42edeb 100644 --- a/projects/js-packages/ai-client/src/components/ai-control/style.scss +++ b/projects/js-packages/ai-client/src/components/ai-control/style.scss @@ -2,20 +2,27 @@ // AI CONTROL +.jetpack-components-ai-control__container-wrapper { + position: sticky; + bottom: 16px; +} + .jetpack-components-ai-control__container { color: var( --jp-gray-80 ); background-color: var( --jp-white ); box-shadow: 0px 12px 15px 0px rgba(0, 0, 0, 0.12), 0px 3px 9px 0px rgba(0, 0, 0, 0.12), 0px 1px 3px 0px rgba(0, 0, 0, 0.15); font-family: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; - width: 100%; + border-radius: 6px; + border: 1px solid var(--gutenberg-gray-400, #CCC); } .jetpack-components-ai-control__wrapper { display: flex; - padding: 12px 14px; - gap: 8px; - align-items: center; + padding: 8px 8px 8px var(--grid-unit-15, 12px); + align-items: flex-end; box-sizing: border-box; + border-radius: 6px 6px 0 0; + gap: 6px; &.is-transparent { opacity: 0.4; @@ -23,10 +30,11 @@ } .jetpack-components-ai-control__input-wrapper { - position: relative; display: flex; flex-grow: 1; - width: 100%; + align-self: center; + min-height: 36px; // need compat height with buttons wrapper + align-items: center; textarea.jetpack-components-ai-control__input { background-color: var( --jp-white ); @@ -63,67 +71,28 @@ } } -.jetpack-components-ai-control__clear.components-button.has-icon { - width: 24px; - min-width: 24px; - height: 24px; - padding: 0; - border-radius: 50%; - background-color: black; - opacity: 0.2; - color: white; - - &:hover { - opacity: 0.4; - } -} - -.jetpack-components-ai-controlton__icon { - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - - .input-icon { - // Brand green regardless of theme - color: var( --jp-green-40 ); - } - - .input-spinner { - margin: 0; - width: 24px; - height: 24px; - - path { - color: var( --jp-green-40 ); - } - } -} - .jetpack-components-ai-control__controls-prompt_button_wrapper { text-transform: uppercase; font-size: 11px; font-weight: 600; - line-height: 16px; + line-height: 1em; user-select: none; white-space: nowrap; display: flex; align-items: center; + gap: 8px; .components-button.is-small:not(.has-label) { padding: 0; } -} -.jetpack-components-ai-control__controls-prompt_button { - color: var( --jp-gray-80 ); - text-transform: uppercase; - - &:hover, - &:active { - color: var( --wp-components-color-accent, var( --wp-admin-theme-color ) ); + .components-button-group .components-button { + box-shadow: none; + padding: 6px 8px; } +} +.jetpack-components-ai-control__controls-prompt_button { &:disabled { opacity: 0.6; cursor: not-allowed; @@ -134,24 +103,26 @@ .jetpack-ai-assistant__message { display: flex; - line-height: 28px; - font-size: 12px; - align-self: center; - align-items: center; - background-color: var( --jp-white-off ); - padding: 0 12px; - - > svg { - fill: var( --jp-gray-40 ); - } - - .jetpack-ai-assistant__message-content { - flex-grow: 2; - margin: 0 8px; - color: var( --jp-gray-70 ); - - .components-external-link { - color: var( --jp-gray-50 ); - } - } + line-height: 28px; + font-size: 12px; + align-self: center; + align-items: center; + background-color: var( --jp-white-off ); + padding: 0 12px; + border-radius: 0 0 6px 6px; + + > svg { + fill: var( --jp-gray-40 ); + } + + .jetpack-ai-assistant__message-content { + flex-grow: 2; + margin: 0 8px; + color: var( --jp-gray-50 ); + line-height: 1.4em; + + .components-external-link { + color: var( --jp-gray-50 ); + } + } } diff --git a/projects/js-packages/ai-client/src/components/ai-status-indicator/index.tsx b/projects/js-packages/ai-client/src/components/ai-status-indicator/index.tsx index a6a35723b1ae7..cb01773a7d947 100644 --- a/projects/js-packages/ai-client/src/components/ai-status-indicator/index.tsx +++ b/projects/js-packages/ai-client/src/components/ai-status-indicator/index.tsx @@ -1,12 +1,8 @@ /** * External dependencies */ -import { Icon } from '@wordpress/components'; +import { Spinner } from '@wordpress/components'; import classNames from 'classnames'; -/* - * Internal dependencies - */ -import { aiAssistantIcon } from '../../icons'; /* * Types */ @@ -27,17 +23,14 @@ export type AiStatusIndicatorProps = { * @param {AiStatusIndicatorProps} props - component props. * @returns {React.ReactElement} - rendered component. */ -export default function AiStatusIndicator( { - state, - size = 24, -}: AiStatusIndicatorProps ): React.ReactElement { +export default function AiStatusIndicator( { state }: AiStatusIndicatorProps ): React.ReactElement { return ( <div className={ classNames( 'jetpack-ai-status-indicator__icon-wrapper', { [ `is-${ state }` ]: true, } ) } > - <Icon icon={ aiAssistantIcon } size={ size } /> + <Spinner /> </div> ); } diff --git a/projects/js-packages/ai-client/src/components/ai-status-indicator/style.scss b/projects/js-packages/ai-client/src/components/ai-status-indicator/style.scss index f744a8ce7863b..c947e8ee484a2 100644 --- a/projects/js-packages/ai-client/src/components/ai-status-indicator/style.scss +++ b/projects/js-packages/ai-client/src/components/ai-status-indicator/style.scss @@ -1,52 +1,19 @@ @import '@automattic/jetpack-base-styles/style'; .jetpack-ai-status-indicator__icon-wrapper { - color: var( --jp-green-60 ); - height: 24px; - - &.is-init { - color: var( --jp-green-60 ); - } - - &.is-requesting { - color: var( --jp-green-40 ); - animation: fade 800ms linear infinite; - } - - &.is-suggesting { - color: var( --jp-green-30 ); - .ai-assistant-icon > path { - animation: fadingSpark 300ms ease-in-out alternate infinite; - - &.spark-first { - animation-delay: 0.2s; - } - - &.spark-second { - animation-delay: 0.6s; - } - } - } - - &.is-done { - color: var( --jp-green-40 ); - } - - &.is-error { - color: var( --jp-yellow-30 ); + transition: opacity 0.25s ease-in-out, width 0.25s; + width: 0; + opacity: 0; + align-self: baseline; + + > svg { + height: 24px; + width: 24px; + margin: 6px 0 0; } -} - -@keyframes fadingSpark { - to { - opacity: 0.3; + &.is-requesting, &.is-suggesting { + opacity: 1; + width: 24px; } } - -@keyframes fade { - 0% { opacity: 1; } - 50% { opacity: 0.4; } - 100% { opacity: 1; } - } - diff --git a/projects/js-packages/ai-client/src/components/index.ts b/projects/js-packages/ai-client/src/components/index.ts index cdf31ed2ccf3c..34b3f6a59210d 100644 --- a/projects/js-packages/ai-client/src/components/index.ts +++ b/projects/js-packages/ai-client/src/components/index.ts @@ -1,4 +1,4 @@ export { default as AIControl } from './ai-control'; export { default as AiStatusIndicator } from './ai-status-indicator'; export { default as AudioDurationDisplay } from './audio-duration-display'; -export { GuidelineMessage } from './ai-control/message'; +export { GuidelineMessage, default as FooterMessage } from './ai-control/message'; diff --git a/projects/js-packages/components/CHANGELOG.md b/projects/js-packages/components/CHANGELOG.md index fb875b3568fc1..d07f3fbaa5eb1 100644 --- a/projects/js-packages/components/CHANGELOG.md +++ b/projects/js-packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ### This is a list detailing changes for the Jetpack RNA Components package releases. +## [0.45.8] - 2023-12-19 +### Changed +- Updated package dependencies. [#34694, #34696] + ## [0.45.7] - 2023-12-13 ### Added - Added `className` prop to RecordMeterBar component [#34182] @@ -902,6 +906,7 @@ ### Changed - Update node version requirement to 14.16.1 +[0.45.8]: https://github.com/Automattic/jetpack-components/compare/0.45.7...0.45.8 [0.45.7]: https://github.com/Automattic/jetpack-components/compare/0.45.6...0.45.7 [0.45.6]: https://github.com/Automattic/jetpack-components/compare/0.45.5...0.45.6 [0.45.5]: https://github.com/Automattic/jetpack-components/compare/0.45.4...0.45.5 diff --git a/projects/js-packages/components/components/toggle-control/index.tsx b/projects/js-packages/components/components/toggle-control/index.tsx index 9372f19011d94..7f598cd79a164 100644 --- a/projects/js-packages/components/components/toggle-control/index.tsx +++ b/projects/js-packages/components/components/toggle-control/index.tsx @@ -22,6 +22,9 @@ interface ToggleControlProps { /** The label for the toggle. */ label?: React.ReactNode; + /** The size of the toggle. */ + size?: 'small' | 'normal'; + /** A callback function invoked when the toggle is clicked. */ onChange: ( value: boolean ) => void; } @@ -33,6 +36,7 @@ const ToggleControl: React.FC< ToggleControlProps > = ( { help, toggling, label, + size = 'normal', onChange, } ) => { const showChecked = @@ -55,6 +59,8 @@ const ToggleControl: React.FC< ToggleControlProps > = ( { checked={ showChecked } className={ classNames( styles.toggle, className, { [ styles[ 'is-toggling' ] ]: toggling, + [ styles[ 'is-small' ] ]: size === 'small', + [ styles[ 'no-label' ] ]: ! label, } ) } disabled={ disabled } help={ help } diff --git a/projects/js-packages/components/components/toggle-control/stories/index.stories.tsx b/projects/js-packages/components/components/toggle-control/stories/index.stories.tsx index 6c71e10162873..f5743935165e8 100644 --- a/projects/js-packages/components/components/toggle-control/stories/index.stories.tsx +++ b/projects/js-packages/components/components/toggle-control/stories/index.stories.tsx @@ -64,6 +64,26 @@ export const Disabled = args => { ); }; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const Small = args => { + const [ checked, setChecked ] = useState( false ); + + const handleChecked = useCallback( () => { + setChecked( ! checked ); + }, [ checked ] ); + + return ( + <> + <ToggleControl + checked={ checked } + size="small" + label="Code is poetry." + onChange={ handleChecked } + /> + </> + ); +}; + // eslint-disable-next-line @typescript-eslint/no-unused-vars export const HelpText = args => { const [ checked, setChecked ] = useState( false ); diff --git a/projects/js-packages/components/components/toggle-control/styles.module.scss b/projects/js-packages/components/components/toggle-control/styles.module.scss index 9432290914b54..fd5cab657e6b9 100644 --- a/projects/js-packages/components/components/toggle-control/styles.module.scss +++ b/projects/js-packages/components/components/toggle-control/styles.module.scss @@ -3,30 +3,41 @@ /// Overrides the @wordpress/components ToggleControl component. /// @link https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src/form-toggle .toggle { + --base-width: 8px; + + &.is-small { + --base-width: 6px; + } + + &.no-label :global(.components-toggle-control__label) { + display: none; + } + :global { .components-form-toggle { --wp-admin-theme-color: var( --jp-green-40 ); + &__input:focus + .components-form-toggle__track { box-shadow: 0 0 0 2px var( --jp-white ), 0 0 0 4px var( --jp-green-50 ); } .components-form-toggle__track { - width: 48px; - height: 24px; + width: calc( var(--base-width) * 6 ); + height: calc( var(--base-width) * 3 ); border-radius: 12px; border-width: 2px; } .components-form-toggle__thumb { - width: 16px; - height: 16px; - top: 4px; - left: 4px; + width: calc(var(--base-width) * 2); + height: calc(var(--base-width) * 2); + top: calc(var(--base-width) / 2); + left: calc(var(--base-width) / 2); } &.is-checked .components-form-toggle__thumb { - transform: translateX( 24px ); + transform: translateX( calc( var(--base-width) * 3 ) ); } } } diff --git a/projects/js-packages/components/package.json b/projects/js-packages/components/package.json index ec48ab20974ad..14ea9aff02f6a 100644 --- a/projects/js-packages/components/package.json +++ b/projects/js-packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-components", - "version": "0.45.7", + "version": "0.45.8", "description": "Jetpack Components Package", "author": "Automattic", "license": "GPL-2.0-or-later", @@ -38,11 +38,11 @@ "@babel/core": "7.23.5", "@babel/preset-react": "7.23.3", "@jest/globals": "29.4.3", - "@storybook/addon-actions": "7.4.6", - "@storybook/blocks": "7.4.6", - "@storybook/react": "7.4.6", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@storybook/addon-actions": "7.6.5", + "@storybook/blocks": "7.6.5", + "@storybook/react": "7.6.5", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "@types/jest": "29.5.10", "@types/qrcode.react": "1.0.4", diff --git a/projects/js-packages/connection/CHANGELOG.md b/projects/js-packages/connection/CHANGELOG.md index 9c1e45e268bac..0e6d57bd4b5f7 100644 --- a/projects/js-packages/connection/CHANGELOG.md +++ b/projects/js-packages/connection/CHANGELOG.md @@ -2,6 +2,10 @@ ### This is a list detailing changes for the Jetpack RNA Connection Component releases. +## [0.30.11] - 2023-12-19 +### Changed +- Updated package dependencies. [#34694, #34696] + ## [0.30.10] - 2023-12-06 ### Changed - Updated package dependencies. [#34416] @@ -672,6 +676,7 @@ - `Main` and `ConnectUser` components added. - `JetpackRestApiClient` API client added. +[0.30.11]: https://github.com/Automattic/jetpack-connection-js/compare/v0.30.10...v0.30.11 [0.30.10]: https://github.com/Automattic/jetpack-connection-js/compare/v0.30.9...v0.30.10 [0.30.9]: https://github.com/Automattic/jetpack-connection-js/compare/v0.30.8...v0.30.9 [0.30.8]: https://github.com/Automattic/jetpack-connection-js/compare/v0.30.7...v0.30.8 diff --git a/projects/js-packages/connection/package.json b/projects/js-packages/connection/package.json index 60f6f934e5352..130e9ff1eae1d 100644 --- a/projects/js-packages/connection/package.json +++ b/projects/js-packages/connection/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-connection", - "version": "0.30.10", + "version": "0.30.11", "description": "Jetpack Connection Component", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/connection/#readme", "bugs": { @@ -33,9 +33,9 @@ "@automattic/jetpack-base-styles": "workspace:*", "@babel/core": "7.23.5", "@babel/preset-react": "7.23.3", - "@storybook/addon-actions": "7.4.6", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@storybook/addon-actions": "7.6.5", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", diff --git a/projects/js-packages/licensing/CHANGELOG.md b/projects/js-packages/licensing/CHANGELOG.md index db32e72d3e317..36aae859e1f15 100644 --- a/projects/js-packages/licensing/CHANGELOG.md +++ b/projects/js-packages/licensing/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.11.16 - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + ## 0.11.15 - 2023-12-06 ### Changed - Updated package dependencies. [#34416] diff --git a/projects/js-packages/licensing/package.json b/projects/js-packages/licensing/package.json index f9732bf36820d..fee0dfcc7bf9d 100644 --- a/projects/js-packages/licensing/package.json +++ b/projects/js-packages/licensing/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-licensing", - "version": "0.11.15", + "version": "0.11.16", "description": "Jetpack licensing flow", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/licensing/#readme", "bugs": { @@ -33,8 +33,8 @@ "@automattic/jetpack-base-styles": "workspace:*", "@babel/core": "7.23.5", "@babel/preset-react": "7.23.3", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", diff --git a/projects/js-packages/partner-coupon/CHANGELOG.md b/projects/js-packages/partner-coupon/CHANGELOG.md index cfc4cd57a8fe4..1e13f196255ab 100644 --- a/projects/js-packages/partner-coupon/CHANGELOG.md +++ b/projects/js-packages/partner-coupon/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.64 - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + ## 0.2.63 - 2023-12-11 ### Changed - Updated package dependencies. [#34416] diff --git a/projects/js-packages/partner-coupon/package.json b/projects/js-packages/partner-coupon/package.json index b6c43590188fa..5b4448f58d6d1 100644 --- a/projects/js-packages/partner-coupon/package.json +++ b/projects/js-packages/partner-coupon/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-partner-coupon", - "version": "0.2.63", + "version": "0.2.64", "description": "This package aims to add components to make it easier to redeem partner coupons", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/partner-coupon/#readme", "bugs": { @@ -23,14 +23,14 @@ "@automattic/jetpack-base-styles": "workspace:*", "@babel/core": "7.23.5", "@babel/preset-react": "7.23.3", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "@wordpress/base-styles": "4.38.0", "@wordpress/data": "9.17.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "jest-extended": "2.0.0", + "jest-extended": "4.0.2", "react": "18.2.0", "react-dom": "18.2.0", "react-test-renderer": "18.2.0" diff --git a/projects/js-packages/publicize-components/CHANGELOG.md b/projects/js-packages/publicize-components/CHANGELOG.md index aefec20327e8f..aa2e8a01765a1 100644 --- a/projects/js-packages/publicize-components/CHANGELOG.md +++ b/projects/js-packages/publicize-components/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.44.0] - 2023-12-20 +### Changed +- Hide conversion notice on Simple sites. [#34733] +- Updated package dependencies. [#34694] + +### Fixed +- Fixed the media validation notice shown even when auto conversion is enabled. [#34730] + ## [0.43.0] - 2023-12-14 ### Changed - Moved `usePostMeta` hook to `/hooks/` directory. [#34611] @@ -544,6 +552,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Updated package dependencies. [#24470] +[0.44.0]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.43.0...v0.44.0 [0.43.0]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.42.0...v0.43.0 [0.42.0]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.41.9...v0.42.0 [0.41.9]: https://github.com/Automattic/jetpack-publicize-components/compare/v0.41.8...v0.41.9 diff --git a/projects/js-packages/publicize-components/package.json b/projects/js-packages/publicize-components/package.json index 78a4c2b629f07..002dfd9dbf612 100644 --- a/projects/js-packages/publicize-components/package.json +++ b/projects/js-packages/publicize-components/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-publicize-components", - "version": "0.43.0", + "version": "0.44.0", "description": "A library of JS components required by the Publicize editor plugin", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/publicize-components/#readme", "bugs": { @@ -51,8 +51,8 @@ "@babel/plugin-transform-react-jsx": "7.23.4", "@babel/preset-react": "7.23.3", "@babel/runtime": "7.23.5", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "@types/jest": "29.5.10", "@types/react": "18.2.33", diff --git a/projects/js-packages/publicize-components/src/components/form/auto-conversion-notice.tsx b/projects/js-packages/publicize-components/src/components/form/auto-conversion-notice.tsx index f6d97104930fc..aebe887a8e3c1 100644 --- a/projects/js-packages/publicize-components/src/components/form/auto-conversion-notice.tsx +++ b/projects/js-packages/publicize-components/src/components/form/auto-conversion-notice.tsx @@ -1,3 +1,4 @@ +import { isSimpleSite } from '@automattic/jetpack-shared-extension-utils'; import { Button } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; @@ -16,6 +17,7 @@ export const AutoConversionNotice: React.FC = () => { const { adminUrl, jetpackSharingSettingsUrl } = usePublicizeConfig(); return ( + ! isSimpleSite() && shouldShowNotice( NOTICES.autoConversion ) && ( <Notice type={ 'warning' } diff --git a/projects/js-packages/publicize-components/src/components/form/index.js b/projects/js-packages/publicize-components/src/components/form/index.js index 5a034bbdcf1ba..05785d79164e6 100644 --- a/projects/js-packages/publicize-components/src/components/form/index.js +++ b/projects/js-packages/publicize-components/src/components/form/index.js @@ -118,6 +118,7 @@ export default function PublicizeForm() { <ValidationNotice connectionsCount={ connections.length } invalidConnectionIdsCount={ invalidIds.length } + shouldAutoConvert={ shouldAutoConvert } /> ) ) } </> diff --git a/projects/js-packages/publicize-components/src/components/form/validation-notice.tsx b/projects/js-packages/publicize-components/src/components/form/validation-notice.tsx index 5a6db2d6cd797..47871f62de7c3 100644 --- a/projects/js-packages/publicize-components/src/components/form/validation-notice.tsx +++ b/projects/js-packages/publicize-components/src/components/form/validation-notice.tsx @@ -6,13 +6,15 @@ import Notice from '../notice'; export type ValidationNoticeProps = { connectionsCount: number; invalidConnectionIdsCount: number; + shouldAutoConvert: boolean; }; export const ValidationNotice: React.FC< ValidationNoticeProps > = ( { connectionsCount, invalidConnectionIdsCount, + shouldAutoConvert, } ) => { - return ( + return shouldAutoConvert ? null : ( <Notice type={ 'warning' }> <p> { connectionsCount === invalidConnectionIdsCount diff --git a/projects/js-packages/publicize-components/src/social-store/selectors/auto-conversion-settings.js b/projects/js-packages/publicize-components/src/social-store/selectors/auto-conversion-settings.js index 7d77e567023b7..4fffb19e2f333 100644 --- a/projects/js-packages/publicize-components/src/social-store/selectors/auto-conversion-settings.js +++ b/projects/js-packages/publicize-components/src/social-store/selectors/auto-conversion-settings.js @@ -1,7 +1,8 @@ const autoConversionSettingsSelectors = { getAutoConversionSettings: state => state.autoConversionSettings, isAutoConversionAvailable: state => state.autoConversionSettings.available, - isAutoConversionEnabled: state => state.autoConversionSettings.enabled, + isAutoConversionEnabled: state => + state.autoConversionSettings.available && state.autoConversionSettings.enabled, isAutoConversionSettingsUpdating: state => state.autoConversionSettings.isUpdating, }; diff --git a/projects/js-packages/shared-extension-utils/CHANGELOG.md b/projects/js-packages/shared-extension-utils/CHANGELOG.md index d83fbb00bed29..4c2b029f12617 100644 --- a/projects/js-packages/shared-extension-utils/CHANGELOG.md +++ b/projects/js-packages/shared-extension-utils/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.13.5] - 2023-12-19 +### Changed +- Updated package dependencies. [#34694] + ## [0.13.4] - 2023-12-06 ### Changed - Updated package dependencies. [#34416] @@ -298,6 +302,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Core: prepare utility for release +[0.13.5]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.13.4...0.13.5 [0.13.4]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.13.3...0.13.4 [0.13.3]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/Automattic/jetpack-shared-extension-utils/compare/0.13.1...0.13.2 diff --git a/projects/js-packages/shared-extension-utils/package.json b/projects/js-packages/shared-extension-utils/package.json index f9e44ea1a569f..fa036c3db44b1 100644 --- a/projects/js-packages/shared-extension-utils/package.json +++ b/projects/js-packages/shared-extension-utils/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-shared-extension-utils", - "version": "0.13.4", + "version": "0.13.5", "description": "Utility functions used by the block editor extensions", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/shared-extension-utils/#readme", "bugs": { @@ -39,8 +39,8 @@ "react-dom": "18.2.0", "jetpack-js-tools": "workspace:*", "@automattic/jetpack-webpack-config": "workspace:*", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "@babel/plugin-transform-react-jsx": "7.23.4", "@wordpress/babel-plugin-import-jsx-pragma": "4.30.0" diff --git a/projects/plugins/boost/changelog/init-release-cycle b/projects/js-packages/storybook/changelog/renovate-storybook-monorepo#4 similarity index 53% rename from projects/plugins/boost/changelog/init-release-cycle rename to projects/js-packages/storybook/changelog/renovate-storybook-monorepo#4 index 9ca19ba708b31..c47cb18e82997 100644 --- a/projects/plugins/boost/changelog/init-release-cycle +++ b/projects/js-packages/storybook/changelog/renovate-storybook-monorepo#4 @@ -1,5 +1,4 @@ Significance: patch Type: changed -Comment: Init 2.2.1-alpha - +Updated package dependencies. diff --git a/projects/js-packages/storybook/package.json b/projects/js-packages/storybook/package.json index e14d1b1c31fb6..7c089f9ff8d4b 100644 --- a/projects/js-packages/storybook/package.json +++ b/projects/js-packages/storybook/package.json @@ -26,19 +26,19 @@ "@babel/plugin-syntax-jsx": "7.23.3", "@babel/preset-react": "7.23.3", "@babel/runtime": "7.23.5", - "@storybook/addon-a11y": "7.4.6", - "@storybook/addon-docs": "7.4.6", - "@storybook/addon-essentials": "7.4.6", - "@storybook/addon-storysource": "7.4.6", - "@storybook/addons": "7.4.6", - "@storybook/api": "7.4.6", - "@storybook/blocks": "7.4.6", - "@storybook/components": "7.4.6", - "@storybook/manager-api": "7.4.6", - "@storybook/react": "7.4.6", - "@storybook/react-webpack5": "7.4.6", - "@storybook/source-loader": "7.4.6", - "@storybook/theming": "7.4.6", + "@storybook/addon-a11y": "7.6.5", + "@storybook/addon-docs": "7.6.5", + "@storybook/addon-essentials": "7.6.5", + "@storybook/addon-storysource": "7.6.5", + "@storybook/addons": "7.6.5", + "@storybook/api": "7.6.5", + "@storybook/blocks": "7.6.5", + "@storybook/components": "7.6.5", + "@storybook/manager-api": "7.6.5", + "@storybook/react": "7.6.5", + "@storybook/react-webpack5": "7.6.5", + "@storybook/source-loader": "7.6.5", + "@storybook/theming": "7.6.5", "@wordpress/babel-preset-default": "7.31.0", "@wordpress/base-styles": "4.38.0", "@wordpress/block-editor": "12.15.0", @@ -62,7 +62,7 @@ "require-from-string": "2.0.2", "sass": "1.64.1", "sass-loader": "12.4.0", - "storybook": "7.4.6", + "storybook": "7.6.5", "storybook-addon-mock": "4.3.0", "style-loader": "2.0.0", "ts-dedent": "2.2.0", diff --git a/projects/packages/backup/CHANGELOG.md b/projects/packages/backup/CHANGELOG.md index 6edbea2214c2b..fd61e94284acb 100644 --- a/projects/packages/backup/CHANGELOG.md +++ b/projects/packages/backup/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.4] - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + ## [2.0.3] - 2023-12-13 ### Fixed - Backup: Bug fixes in helper script installation class. [#34297] @@ -526,6 +530,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add API endpoints and Jetpack Backup package for managing Help… +[2.0.4]: https://github.com/Automattic/jetpack-backup/compare/v2.0.3...v2.0.4 [2.0.3]: https://github.com/Automattic/jetpack-backup/compare/v2.0.2...v2.0.3 [2.0.2]: https://github.com/Automattic/jetpack-backup/compare/v2.0.1...v2.0.2 [2.0.1]: https://github.com/Automattic/jetpack-backup/compare/v2.0.0...v2.0.1 diff --git a/projects/packages/backup/package.json b/projects/packages/backup/package.json index 2af94297aae76..cc7704ff5c90e 100644 --- a/projects/packages/backup/package.json +++ b/projects/packages/backup/package.json @@ -45,8 +45,8 @@ "@babel/core": "7.23.5", "@babel/preset-env": "7.23.5", "@babel/runtime": "7.23.5", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "@wordpress/browserslist-config": "5.30.0", "concurrently": "7.6.0", diff --git a/projects/packages/backup/src/class-package-version.php b/projects/packages/backup/src/class-package-version.php index a9b06521174cf..918acd964ae09 100644 --- a/projects/packages/backup/src/class-package-version.php +++ b/projects/packages/backup/src/class-package-version.php @@ -12,7 +12,7 @@ */ class Package_Version { - const PACKAGE_VERSION = '2.0.3'; + const PACKAGE_VERSION = '2.0.4'; const PACKAGE_SLUG = 'backup'; diff --git a/projects/packages/forms/CHANGELOG.md b/projects/packages/forms/CHANGELOG.md index 321ab1269b0c6..f3ac5dc341cb4 100644 --- a/projects/packages/forms/CHANGELOG.md +++ b/projects/packages/forms/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.28.0] - 2023-12-20 +### Added +- Contact Form: add extra field settings to base field. [#34704] + +### Changed +- Contact Form: minify stylesheets in prod. [#34672] + +## [0.27.0] - 2023-12-15 +### Added +- Contact Form: improve form error message [#34629] + +### Changed +- Form block: hide 'lead capture' variation for WP.com Atomic sites [#34615] + +### Fixed +- Contact Form: add missing Required toolbar button to Checkbox field [#34630] +- Contact Form: align half-width fields on same row [#34632] + ## [0.26.0] - 2023-12-14 ### Added - Contact Form: build JS assets [#34622] @@ -423,6 +441,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a new jetpack/forms package [#28409] - Added a public load_contact_form method for initializing the contact form module. [#28416] +[0.28.0]: https://github.com/automattic/jetpack-forms/compare/v0.27.0...v0.28.0 +[0.27.0]: https://github.com/automattic/jetpack-forms/compare/v0.26.0...v0.27.0 [0.26.0]: https://github.com/automattic/jetpack-forms/compare/v0.25.0...v0.26.0 [0.25.0]: https://github.com/automattic/jetpack-forms/compare/v0.24.2...v0.25.0 [0.24.2]: https://github.com/automattic/jetpack-forms/compare/v0.24.1...v0.24.2 diff --git a/projects/packages/forms/changelog/add-contact-form-accessible-name b/projects/packages/forms/changelog/add-contact-form-accessible-name new file mode 100644 index 0000000000000..ebc2da4b08f39 --- /dev/null +++ b/projects/packages/forms/changelog/add-contact-form-accessible-name @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Contact Form: add accessible name to form diff --git a/projects/packages/forms/changelog/boost-fix-importmap-deferral b/projects/packages/forms/changelog/boost-fix-importmap-deferral new file mode 100644 index 0000000000000..2baeef46cf170 --- /dev/null +++ b/projects/packages/forms/changelog/boost-fix-importmap-deferral @@ -0,0 +1,5 @@ +Significance: patch +Type: fixed +Comment: Bumped version numbers + + diff --git a/projects/packages/forms/changelog/fix-contact-form-input-stacking b/projects/packages/forms/changelog/fix-contact-form-input-stacking deleted file mode 100644 index 923721036f672..0000000000000 --- a/projects/packages/forms/changelog/fix-contact-form-input-stacking +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Contact Form: align half-width fields on same row diff --git a/projects/packages/forms/changelog/fix-contact-form-required-checkbox b/projects/packages/forms/changelog/fix-contact-form-required-checkbox deleted file mode 100644 index 3bbb2d15c2d51..0000000000000 --- a/projects/packages/forms/changelog/fix-contact-form-required-checkbox +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Contact Form: add missing Required toolbar button to Checkbox field diff --git a/projects/packages/forms/changelog/update-contact-form-error-message b/projects/packages/forms/changelog/update-contact-form-error-message deleted file mode 100644 index 8f004a7a1d487..0000000000000 --- a/projects/packages/forms/changelog/update-contact-form-error-message +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: added - -Contact Form: improve form error message diff --git a/projects/packages/forms/changelog/update-forms-lead-capture-atomic b/projects/packages/forms/changelog/update-forms-lead-capture-atomic deleted file mode 100644 index 07395a08595e0..0000000000000 --- a/projects/packages/forms/changelog/update-forms-lead-capture-atomic +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: changed - -Form block: hide 'lead capture' variation for WP.com Atomic sites diff --git a/projects/packages/forms/composer.json b/projects/packages/forms/composer.json index a0b6f17d23937..15952fa544511 100644 --- a/projects/packages/forms/composer.json +++ b/projects/packages/forms/composer.json @@ -62,7 +62,7 @@ "link-template": "https://github.com/automattic/jetpack-forms/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "0.27.x-dev" + "dev-trunk": "0.29.x-dev" }, "textdomain": "jetpack-forms", "version-constants": { diff --git a/projects/packages/forms/package.json b/projects/packages/forms/package.json index 7b0c0f99f9740..79cac3bfaef49 100644 --- a/projects/packages/forms/package.json +++ b/projects/packages/forms/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-forms", - "version": "0.27.0-alpha", + "version": "0.29.0-alpha", "description": "Jetpack Forms", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/forms/#readme", "bugs": { diff --git a/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-controls.js b/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-controls.js index 4fe8431504e22..59482070b4351 100644 --- a/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-controls.js +++ b/projects/packages/forms/src/blocks/contact-form/components/jetpack-field-controls.js @@ -13,6 +13,7 @@ import { ToggleControl, RangeControl, } from '@wordpress/components'; +import { isValidElement } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { useFormStyle, FORM_STYLE, getBlockStyle } from '../util/form'; import ToolbarRequiredGroup from './block-controls/toolbar-required-group'; @@ -31,6 +32,7 @@ const JetpackFieldControls = ( { setAttributes, type, width, + extraFieldSettings = [], } ) => { const formStyle = useFormStyle( clientId ); const blockStyle = getBlockStyle( blockClassNames ); @@ -103,6 +105,50 @@ const JetpackFieldControls = ( { setAttributes( { id: newValue } ); }; + let fieldSettings = [ + <ToggleControl + label={ __( 'Field is required', 'jetpack-forms' ) } + className="jetpack-field-label__required" + checked={ required } + onChange={ value => setAttributes( { required: value } ) } + help={ __( 'You can edit the "required" label in the editor', 'jetpack-forms' ) } + />, + ! hidePlaceholder && ( + <TextControl + label={ __( 'Placeholder text', 'jetpack-forms' ) } + value={ placeholder || '' } + onChange={ value => setAttributes( { [ placeholderField ]: value } ) } + help={ __( + 'Show visitors an example of the type of content expected. Otherwise, leave blank.', + 'jetpack-forms' + ) } + /> + ), + <JetpackFieldWidth setAttributes={ setAttributes } width={ width } />, + <ToggleControl + label={ __( 'Sync fields style', 'jetpack-forms' ) } + checked={ attributes.shareFieldAttributes } + onChange={ value => setAttributes( { shareFieldAttributes: value } ) } + help={ __( 'Deactivate for individual styling of this block', 'jetpack-forms' ) } + />, + ]; + + extraFieldSettings.forEach( ( { element, index } ) => { + if ( ! isValidElement( element ) ) { + return; + } + + if ( index >= 0 && index < fieldSettings.length ) { + fieldSettings = [ + ...fieldSettings.slice( 0, index ), + element, + ...fieldSettings.slice( index ), + ]; + } else { + fieldSettings.push( element ); + } + } ); + return ( <> <BlockControls> @@ -117,31 +163,9 @@ const JetpackFieldControls = ( { <JetpackManageResponsesSettings isChildBlock /> </PanelBody> <PanelBody title={ __( 'Field Settings', 'jetpack-forms' ) }> - <ToggleControl - label={ __( 'Field is required', 'jetpack-forms' ) } - className="jetpack-field-label__required" - checked={ required } - onChange={ value => setAttributes( { required: value } ) } - help={ __( 'You can edit the "required" label in the editor', 'jetpack-forms' ) } - /> - { ! hidePlaceholder && ( - <TextControl - label={ __( 'Placeholder text', 'jetpack-forms' ) } - value={ placeholder || '' } - onChange={ value => setAttributes( { [ placeholderField ]: value } ) } - help={ __( - 'Show visitors an example of the type of content expected. Otherwise, leave blank.', - 'jetpack-forms' - ) } - /> - ) } - <JetpackFieldWidth setAttributes={ setAttributes } width={ width } /> - <ToggleControl - label={ __( 'Sync fields style', 'jetpack-forms' ) } - checked={ attributes.shareFieldAttributes } - onChange={ value => setAttributes( { shareFieldAttributes: value } ) } - help={ __( 'Deactivate for individual styling of this block', 'jetpack-forms' ) } - /> + { fieldSettings.filter( Boolean ).map( ( elt, index ) => ( + <div key={ index }>{ elt }</div> + ) ) } </PanelBody> <PanelColorSettings title={ __( 'Color', 'jetpack-forms' ) } diff --git a/projects/packages/forms/src/blocks/contact-form/components/jetpack-manage-responses-settings.js b/projects/packages/forms/src/blocks/contact-form/components/jetpack-manage-responses-settings.js index 025ea15209588..9639fc7e0d561 100644 --- a/projects/packages/forms/src/blocks/contact-form/components/jetpack-manage-responses-settings.js +++ b/projects/packages/forms/src/blocks/contact-form/components/jetpack-manage-responses-settings.js @@ -1,5 +1,5 @@ import { getJetpackData } from '@automattic/jetpack-shared-extension-utils'; -import { Button, TextControl } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { get } from 'lodash'; import React from 'react'; @@ -7,11 +7,7 @@ import InspectorHint from '../components/inspector-hint'; const RESPONSES_PATH = `${ get( getJetpackData(), 'adminUrl', false ) }edit.php?post_type=feedback`; -const JetpackManageResponsesSettings = ( { - formTitle = '', - isChildBlock = false, - setAttributes, -} ) => { +const JetpackManageResponsesSettings = () => { return ( <> <InspectorHint> @@ -23,15 +19,6 @@ const JetpackManageResponsesSettings = ( { { __( '(opens in a new tab)', 'jetpack-forms' ) } </span> </Button> - { /* Temporarily hiding the Form Title */ } - { false && ! isChildBlock && ( - <TextControl - label={ __( 'Title of the Form', 'jetpack-forms' ) } - value={ formTitle } - onChange={ value => setAttributes( { formTitle: value } ) } - help={ __( 'Optional - not visible to viewers', 'jetpack-forms' ) } - /> - ) } </> ); }; diff --git a/projects/packages/forms/src/blocks/contact-form/edit.js b/projects/packages/forms/src/blocks/contact-form/edit.js index f80c72f2cdf81..19b76b1bd5add 100644 --- a/projects/packages/forms/src/blocks/contact-form/edit.js +++ b/projects/packages/forms/src/blocks/contact-form/edit.js @@ -20,6 +20,7 @@ import { SelectControl, TextareaControl, TextControl, + Notice, } from '@wordpress/components'; import { compose, withInstanceId } from '@wordpress/compose'; import { withDispatch, withSelect } from '@wordpress/data'; @@ -36,6 +37,7 @@ import JetpackEmailConnectionSettings from './components/jetpack-email-connectio import JetpackManageResponsesSettings from './components/jetpack-manage-responses-settings'; import NewsletterIntegrationSettings from './components/jetpack-newsletter-integration-settings'; import SalesforceLeadFormSettings from './components/jetpack-salesforce-lead-form/jetpack-salesforce-lead-form-settings'; +import useFormAccessibleName from './hooks/use-form-accessible-name'; import { withStyleVariables } from './util/with-style-variables'; import defaultVariations from './variations'; @@ -159,6 +161,8 @@ export const JetpackContactFormEdit = forwardRef( // eslint-disable-next-line react-hooks/exhaustive-deps }, [] ); + useFormAccessibleName( formTitle, clientId, setAttributes ); + useEffect( () => { if ( to === undefined && postAuthorEmail ) { setAttributes( { to: postAuthorEmail } ); @@ -305,11 +309,18 @@ export const JetpackContactFormEdit = forwardRef( return ( <> <InspectorControls> + { ! attributes.formTitle && ( + <PanelBody> + <Notice status="warning" isDismissible={ false }> + { __( + 'Add a heading inside the form or before it to help everybody identify it.', + 'jetpack-forms' + ) } + </Notice>{ ' ' } + </PanelBody> + ) } <PanelBody title={ __( 'Manage Responses', 'jetpack-forms' ) }> - <JetpackManageResponsesSettings - formTitle={ formTitle } - setAttributes={ setAttributes } - /> + <JetpackManageResponsesSettings setAttributes={ setAttributes } /> </PanelBody> <PanelBody title={ __( 'Submission Settings', 'jetpack-forms' ) } initialOpen={ false }> { renderSubmissionSettings() } diff --git a/projects/packages/forms/src/blocks/contact-form/hooks/use-form-accessible-name.js b/projects/packages/forms/src/blocks/contact-form/hooks/use-form-accessible-name.js new file mode 100644 index 0000000000000..500b858e8e9ec --- /dev/null +++ b/projects/packages/forms/src/blocks/contact-form/hooks/use-form-accessible-name.js @@ -0,0 +1,53 @@ +import { useSelect } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; + +const getNameFromBlockHeading = block => { + const innerHeading = block.innerBlocks?.find( b => b.name === 'core/heading' ); + + return innerHeading?.attributes?.content; +}; + +const getNameFromBlockPreviousHeadings = ( block, pageBlocks ) => { + const blockIndex = pageBlocks.findIndex( b => b.clientId === block.clientId ); + const previousBlocks = pageBlocks.slice( 0, blockIndex ); + const closestHeading = previousBlocks.findLast( b => b.name === 'core/heading' ); + + return closestHeading?.attributes?.content; +}; + +/** + * Update the form accessible stored in the `formTitle` attribute as the block or page + * content changes. The heuristic is as follows: + * 1. Look for a heading inside the form + * 2. Look for a heading in the previous siblings + * 3. Use the post title (in Contact_Form::parse, server side) + * + * @param {string} formTitle - The form title + * @param {string} clientId - The block unique identifier + * @param {Function} setAttributes - Function to call to update one or more attributes + */ +export default function useFormAccessibleName( formTitle, clientId, setAttributes ) { + const { pageBlocks } = useSelect( select => ( { + pageBlocks: select( 'core/block-editor' ).getBlocks(), + } ) ); + + useEffect( () => { + const currentBlock = pageBlocks.find( block => block.clientId === clientId ); + + let name = ''; + + if ( currentBlock ) { + // #1 + name = getNameFromBlockHeading( currentBlock ); + + if ( ! name ) { + // #2 + name = getNameFromBlockPreviousHeadings( currentBlock, pageBlocks ); + } + } + + if ( formTitle !== name ) { + setAttributes( { formTitle: name } ); + } + }, [ clientId, formTitle, setAttributes, pageBlocks ] ); +} diff --git a/projects/packages/forms/src/class-jetpack-forms.php b/projects/packages/forms/src/class-jetpack-forms.php index f9538d8116611..7c8b18a7cba42 100644 --- a/projects/packages/forms/src/class-jetpack-forms.php +++ b/projects/packages/forms/src/class-jetpack-forms.php @@ -15,7 +15,7 @@ */ class Jetpack_Forms { - const PACKAGE_VERSION = '0.27.0-alpha'; + const PACKAGE_VERSION = '0.29.0-alpha'; /** * Load the contact form module. diff --git a/projects/packages/forms/src/contact-form/class-admin.php b/projects/packages/forms/src/contact-form/class-admin.php index a60d5df668365..615d4df39dedb 100644 --- a/projects/packages/forms/src/contact-form/class-admin.php +++ b/projects/packages/forms/src/contact-form/class-admin.php @@ -458,7 +458,7 @@ public function grunion_admin_css() { wp_enqueue_script( 'wp-lists' ); - wp_register_style( 'grunion-admin.css', plugin_dir_url( __FILE__ ) . 'css/grunion-admin.css', array(), \JETPACK__VERSION ); + wp_register_style( 'grunion-admin.css', plugin_dir_url( __FILE__ ) . '/../../../dist/contact-form/css/grunion-admin.css', array(), \JETPACK__VERSION ); wp_style_add_data( 'grunion-admin.css', 'rtl', 'replace' ); wp_enqueue_style( 'grunion-admin.css' ); diff --git a/projects/packages/forms/src/contact-form/class-contact-form-field.php b/projects/packages/forms/src/contact-form/class-contact-form-field.php index f5b9943b4166d..891163d068dd0 100644 --- a/projects/packages/forms/src/contact-form/class-contact-form-field.php +++ b/projects/packages/forms/src/contact-form/class-contact-form-field.php @@ -844,7 +844,7 @@ public function render_date_field( $id, $label, $value, $class, $required, $requ ) ); - wp_enqueue_style( 'jp-jquery-ui-datepicker', plugins_url( 'css/jquery-ui-datepicker.css', __FILE__ ), array( 'dashicons' ), '1.0' ); + wp_enqueue_style( 'jp-jquery-ui-datepicker', plugins_url( '../../dist/contact-form/css/jquery-ui-datepicker.css', __FILE__ ), array( 'dashicons' ), '1.0' ); // Using Core's built-in datepicker localization routine wp_localize_jquery_ui_datepicker(); diff --git a/projects/packages/forms/src/contact-form/class-contact-form-plugin.php b/projects/packages/forms/src/contact-form/class-contact-form-plugin.php index 885e1deb24c08..d9128915eb37d 100644 --- a/projects/packages/forms/src/contact-form/class-contact-form-plugin.php +++ b/projects/packages/forms/src/contact-form/class-contact-form-plugin.php @@ -251,7 +251,7 @@ protected function __construct() { * } * add_action('wp_print_styles', 'remove_grunion_style'); */ - wp_register_style( 'grunion.css', Jetpack_Forms::plugin_url() . 'contact-form/css/grunion.css', array(), \JETPACK__VERSION ); + wp_register_style( 'grunion.css', Jetpack_Forms::plugin_url() . '../dist/contact-form/css/grunion.css', array(), \JETPACK__VERSION ); wp_style_add_data( 'grunion.css', 'rtl', 'replace' ); Assets::register_script( diff --git a/projects/packages/forms/src/contact-form/class-contact-form.php b/projects/packages/forms/src/contact-form/class-contact-form.php index 9465890f2d664..bbe862548d5f9 100644 --- a/projects/packages/forms/src/contact-form/class-contact-form.php +++ b/projects/packages/forms/src/contact-form/class-contact-form.php @@ -240,6 +240,8 @@ public static function style_on() { * @return string HTML for the concat form. */ public static function parse( $attributes, $content ) { + global $post; + if ( Settings::is_syncing() ) { return ''; } @@ -352,12 +354,14 @@ public static function parse( $attributes, $content ) { $url = apply_filters( 'grunion_contact_form_form_action', "{$url}#contact-form-{$id}", $GLOBALS['post'], $id ); $has_submit_button_block = str_contains( $content, 'wp-block-jetpack-button' ); $form_classes = 'contact-form commentsblock'; + $form_accessible_name = $attributes['formTitle'] ? $attributes['formTitle'] : $post->post_title; + $form_aria_label = isset( $form_accessible_name ) && ! empty( $form_accessible_name ) ? 'aria-label="' . esc_attr( $form_accessible_name ) . '"' : ''; if ( $has_submit_button_block ) { $form_classes .= ' wp-block-jetpack-contact-form'; } - $r .= "<form role='form' action='" . esc_url( $url ) . "' method='post' class='" . esc_attr( $form_classes ) . "' novalidate>\n"; + $r .= "<form action='" . esc_url( $url ) . "' method='post' class='" . esc_attr( $form_classes ) . "' $form_aria_label novalidate>\n"; $r .= $form->body; // In new versions of the contact form block the button is an inner block diff --git a/projects/packages/forms/src/contact-form/class-editor-view.php b/projects/packages/forms/src/contact-form/class-editor-view.php index 5c2c654df427d..417694696b4d1 100644 --- a/projects/packages/forms/src/contact-form/class-editor-view.php +++ b/projects/packages/forms/src/contact-form/class-editor-view.php @@ -92,7 +92,7 @@ public static function handle_editor_view_js() { add_filter( 'mce_external_plugins', array( __CLASS__, 'mce_external_plugins' ) ); add_filter( 'mce_buttons', array( __CLASS__, 'mce_buttons' ) ); - wp_enqueue_style( 'grunion-editor-ui', plugins_url( 'css/editor-ui.css', __FILE__ ), array(), \JETPACK__VERSION ); + wp_enqueue_style( 'grunion-editor-ui', plugins_url( '../../dist/contact-form/css/editor-ui.css', __FILE__ ), array(), \JETPACK__VERSION ); wp_style_add_data( 'grunion-editor-ui', 'rtl', 'replace' ); Assets::register_script( @@ -111,8 +111,8 @@ public static function handle_editor_view_js() { 'grunion-editor-view', 'grunionEditorView', array( - 'inline_editing_style' => plugins_url( 'css/editor-inline-editing-style.css', __FILE__ ), - 'inline_editing_style_rtl' => plugins_url( 'css/editor-inline-editing-style.rtl.css', __FILE__ ), + 'inline_editing_style' => plugins_url( '../../dist/contact-form/css/editor-inline-editing-style.css', __FILE__ ), + 'inline_editing_style_rtl' => plugins_url( '../../dist/contact-form/css/editor-inline-editing-style.rtl.css', __FILE__ ), 'dashicons_css_url' => includes_url( 'css/dashicons.css' ), 'default_form' => '[contact-field label="' . __( 'Name', 'jetpack-forms' ) . '" type="name" required="true" /]' . '[contact-field label="' . __( 'Email', 'jetpack-forms' ) . '" type="email" required="true" /]' . @@ -129,7 +129,7 @@ public static function handle_editor_view_js() { ) ); - add_editor_style( plugin_dir_url( __FILE__ ) . 'css/editor-style.css' ); + add_editor_style( plugin_dir_url( __FILE__ ) . '../../dist/contact-form/css/editor-style.css' ); } /** diff --git a/projects/packages/forms/tools/webpack.config.contact-form.js b/projects/packages/forms/tools/webpack.config.contact-form.js index 6a0b288aedc27..e7e81b2d452d6 100644 --- a/projects/packages/forms/tools/webpack.config.contact-form.js +++ b/projects/packages/forms/tools/webpack.config.contact-form.js @@ -1,7 +1,5 @@ /** - * This takes care of minifying CSS for the legacy contact-form bundle which leads its own life. - * - * This config is based on plugins/jetpack/tools/webpack.config.css.js, at the time of the migration to a separate package. + * This takes care of minifying CSS and JS. */ const path = require( 'path' ); @@ -10,13 +8,14 @@ const RemoveAssetWebpackPlugin = require( '@automattic/remove-asset-webpack-plug const glob = require( 'glob' ); const scriptSrcDir = path.join( __dirname, '../src/contact-form/js' ); +const styleSrcDir = path.join( __dirname, '../src/contact-form/css' ); const sharedWebpackConfig = { mode: jetpackWebpackConfig.mode, devtool: jetpackWebpackConfig.devtool, output: { ...jetpackWebpackConfig.output, - path: path.join( __dirname, '..' ), + path: path.join( __dirname, '../dist/contact-form' ), }, optimization: { ...jetpackWebpackConfig.optimization, @@ -86,74 +85,24 @@ const sharedWebpackConfig = { // Delete the dummy JS files Webpack would otherwise create. new RemoveAssetWebpackPlugin( { assets: name => - name.startsWith( 'src/contact-form/css' ) && - ( name.endsWith( '.js' ) || name.endsWith( 'map' ) ), + name.startsWith( 'css' ) && ( name.endsWith( '.js' ) || name.endsWith( 'map' ) ), } ), ], }; -// Entries to minify -const entries = {}; - -// Entries to not minify -const nominEntries = {}; - -// Admin CSS files to insert into weirdRtlNominEntries and weirdRtlEntries. -for ( const name of [ - 'src/contact-form/css/editor-inline-editing-style', - 'src/contact-form/css/editor-style', - 'src/contact-form/css/editor-ui', -] ) { - entries[ name ] = path.join( __dirname, '..', name + '.css' ); - nominEntries[ name + '.min' ] = path.join( __dirname, '..', name + '.css' ); -} - -// Weird frontend CSS files, only a minified rtl is built (and without the ".min" extension). -// The ltr version is apparently used unminified. -for ( const name of [ 'src/contact-form/css/grunion' ] ) { - entries[ name ] = path.join( __dirname, '..', name + '.css' ); -} - module.exports = [ { ...sharedWebpackConfig, - entry: entries, - plugins: [ - ...sharedWebpackConfig.plugins, - // In some cases an output filename is the same as the input. Don't overwrite in that case. - new RemoveAssetWebpackPlugin( { - assets: Object.values( entries ) - .filter( n => typeof n === 'string' ) - .map( n => path.relative( path.dirname( __dirname ), n ) ), - } ), - ], - }, - { - ...sharedWebpackConfig, - entry: nominEntries, - optimization: { - ...sharedWebpackConfig.optimization, - minimize: false, - }, - plugins: [ - ...sharedWebpackConfig.plugins, - // In some cases an output filename is the same as the input. Don't overwrite in that case. - new RemoveAssetWebpackPlugin( { - assets: Object.values( nominEntries ) - .filter( n => typeof n === 'string' ) - .map( n => path.relative( path.dirname( __dirname ), n ) ), - } ), - ], + entry: glob.sync( path.join( scriptSrcDir, '*.js' ) ).reduce( ( acc, filepath ) => { + acc[ 'js/' + path.parse( filepath ).name ] = filepath; + return acc; + }, {} ), }, { ...sharedWebpackConfig, - entry: glob.sync( path.join( scriptSrcDir, '*.js' ) ).reduce( ( acc, filepath ) => { - acc[ 'js/' + path.parse( filepath ).name ] = filepath; + entry: glob.sync( path.join( styleSrcDir, '*.css' ) ).reduce( ( acc, filepath ) => { + acc[ 'css/' + path.parse( filepath ).name ] = filepath; return acc; }, {} ), - output: { - ...jetpackWebpackConfig.output, - path: path.join( __dirname, '../dist/contact-form' ), - }, }, ]; diff --git a/projects/packages/jetpack-mu-wpcom/CHANGELOG.md b/projects/packages/jetpack-mu-wpcom/CHANGELOG.md index 4b6f537c6abc9..3015f1182c44b 100644 --- a/projects/packages/jetpack-mu-wpcom/CHANGELOG.md +++ b/projects/packages/jetpack-mu-wpcom/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.5.0] - 2023-12-15 +### Changed +- Updates the WC visibility check to use the `is_plugin_active` function. [#34648] + ## [5.4.0] - 2023-12-14 ### Added - Add the Sensei and WooCommerce Setup Task, to allow us to retire the old checklist card. [#34551] [#34564] @@ -483,6 +487,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Testing initial package release. +[5.5.0]: https://github.com/Automattic/jetpack-mu-wpcom/compare/v5.4.0...v5.5.0 [5.4.0]: https://github.com/Automattic/jetpack-mu-wpcom/compare/v5.3.0...v5.4.0 [5.3.0]: https://github.com/Automattic/jetpack-mu-wpcom/compare/v5.2.0...v5.3.0 [5.2.0]: https://github.com/Automattic/jetpack-mu-wpcom/compare/v5.1.1...v5.2.0 diff --git a/projects/packages/jetpack-mu-wpcom/composer.json b/projects/packages/jetpack-mu-wpcom/composer.json index d644d6e847113..5296c9675a06b 100644 --- a/projects/packages/jetpack-mu-wpcom/composer.json +++ b/projects/packages/jetpack-mu-wpcom/composer.json @@ -49,7 +49,7 @@ }, "autotagger": true, "branch-alias": { - "dev-trunk": "5.4.x-dev" + "dev-trunk": "5.5.x-dev" }, "textdomain": "jetpack-mu-wpcom", "version-constants": { diff --git a/projects/packages/jetpack-mu-wpcom/package.json b/projects/packages/jetpack-mu-wpcom/package.json index 314c18fede547..5b0a64be0e253 100644 --- a/projects/packages/jetpack-mu-wpcom/package.json +++ b/projects/packages/jetpack-mu-wpcom/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-mu-wpcom", - "version": "5.4.0", + "version": "5.5.0", "description": "Enhances your site with features powered by WordPress.com", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/jetpack-mu-wpcom/#readme", "bugs": { diff --git a/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php b/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php index e5d057ba687ac..1acadd5ee6953 100644 --- a/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php +++ b/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php @@ -14,7 +14,7 @@ */ class Jetpack_Mu_Wpcom { - const PACKAGE_VERSION = '5.4.0'; + const PACKAGE_VERSION = '5.5.0'; const PKG_DIR = __DIR__ . '/../'; const BASE_DIR = __DIR__ . '/'; const BASE_FILE = __FILE__; diff --git a/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php b/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php index 0ae47762260bc..ab6e02398716f 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php +++ b/projects/packages/jetpack-mu-wpcom/src/features/launchpad/launchpad-task-definitions.php @@ -983,8 +983,7 @@ function wpcom_launchpad_is_woocommerce_setup_visible() { return false; } - $active_plugins = get_option( 'active_plugins' ); - return in_array( 'woocommerce/woocommerce.php', $active_plugins, true ); + return is_plugin_active( 'woocommerce/woocommerce.php' ); } /** diff --git a/projects/packages/my-jetpack/CHANGELOG.md b/projects/packages/my-jetpack/CHANGELOG.md index 45be5b1b6aac3..a1ca7d050a298 100644 --- a/projects/packages/my-jetpack/CHANGELOG.md +++ b/projects/packages/my-jetpack/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.1.4] - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + ## [4.1.3] - 2023-12-11 ### Changed - Updated Jetpack AI interstitial to repeat the feature's list on all the tiers. [#34541] @@ -1158,6 +1162,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Created package +[4.1.4]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.1.3...4.1.4 [4.1.3]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.1.2...4.1.3 [4.1.2]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.1.1...4.1.2 [4.1.1]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.1.0...4.1.1 diff --git a/projects/packages/my-jetpack/package.json b/projects/packages/my-jetpack/package.json index 0b053ad49c51e..8d731cf75b18d 100644 --- a/projects/packages/my-jetpack/package.json +++ b/projects/packages/my-jetpack/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-my-jetpack", - "version": "4.1.3", + "version": "4.1.4", "description": "WP Admin page with information and configuration shared among all Jetpack stand-alone plugins", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/my-jetpack/#readme", "bugs": { @@ -49,9 +49,9 @@ "@automattic/jetpack-webpack-config": "workspace:*", "@babel/core": "7.23.5", "@babel/preset-env": "7.23.5", - "@storybook/react": "7.4.6", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@storybook/react": "7.6.5", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", diff --git a/projects/packages/my-jetpack/src/class-initializer.php b/projects/packages/my-jetpack/src/class-initializer.php index 7c14939072543..0347f0317f171 100644 --- a/projects/packages/my-jetpack/src/class-initializer.php +++ b/projects/packages/my-jetpack/src/class-initializer.php @@ -32,7 +32,7 @@ class Initializer { * * @var string */ - const PACKAGE_VERSION = '4.1.3'; + const PACKAGE_VERSION = '4.1.4'; /** * HTML container ID for the IDC screen on My Jetpack page. diff --git a/projects/packages/publicize/CHANGELOG.md b/projects/packages/publicize/CHANGELOG.md index a2411025bce43..a6f1f370a595b 100644 --- a/projects/packages/publicize/CHANGELOG.md +++ b/projects/packages/publicize/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.38.3] - 2023-12-20 +### Fixed +- Fixed backwards compatibility with Social store refactor. [#34566] + +## [0.38.2] - 2023-12-15 +### Fixed +- Social: Fixed issue with auto-conversion option logic. [#34666] + ## [0.38.1] - 2023-12-14 ### Fixed - Fixed Jetpack Social scheduled post messaging. [#34182] @@ -439,6 +447,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated package dependencies. - Update package.json metadata. +[0.38.3]: https://github.com/Automattic/jetpack-publicize/compare/v0.38.2...v0.38.3 +[0.38.2]: https://github.com/Automattic/jetpack-publicize/compare/v0.38.1...v0.38.2 [0.38.1]: https://github.com/Automattic/jetpack-publicize/compare/v0.38.0...v0.38.1 [0.38.0]: https://github.com/Automattic/jetpack-publicize/compare/v0.37.2...v0.38.0 [0.37.2]: https://github.com/Automattic/jetpack-publicize/compare/v0.37.1...v0.37.2 diff --git a/projects/packages/publicize/package.json b/projects/packages/publicize/package.json index 1335b835d8f98..6a9e502fe5886 100644 --- a/projects/packages/publicize/package.json +++ b/projects/packages/publicize/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-publicize", - "version": "0.38.1", + "version": "0.38.3", "description": "Publicize makes it easy to share your site’s posts on several social media networks automatically when you publish a new post.", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/publicize/#readme", "bugs": { diff --git a/projects/packages/publicize/src/auto-conversion-settings/class-rest-settings-controller.php b/projects/packages/publicize/src/auto-conversion-settings/class-rest-settings-controller.php new file mode 100644 index 0000000000000..1858b808d6d01 --- /dev/null +++ b/projects/packages/publicize/src/auto-conversion-settings/class-rest-settings-controller.php @@ -0,0 +1,136 @@ +<?php +/** + * Class used to register REST API auto-conversion settings endpoints. + * + * Flagged to be removed after deprecation. + * + * @deprecated $$next_version$$ + * + * @package automattic/jetpack-publicize + */ + +namespace Automattic\Jetpack\Publicize\Auto_Conversion; + +use Automattic\Jetpack\Publicize\Jetpack_Social_Settings\Settings as Jetpack_Social_Settings; +use WP_Error; +use WP_REST_Controller; +use WP_REST_Server; + +/** + * Defines our endpoints. + */ +class REST_Settings_Controller extends WP_REST_Controller { + /** + * Register REST API endpoints. + * + * @return void + */ + public function register_routes() { + register_rest_route( + 'jetpack/v4', + '/auto-conversion/settings', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_auto_coversion_settings' ), + 'permission_callback' => array( $this, 'settings_permissions_callback' ), + ), + array( + 'methods' => WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'update_auto_coversion_settings' ), + 'permission_callback' => array( $this, 'settings_permissions_callback' ), + 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * GET `/jetpack/v4/auto-conversion/settings` + * + * @return WP_REST_Response + */ + public function get_auto_coversion_settings() { + $settings = ( new Jetpack_Social_Settings() )->get_settings(); + $response = array(); + $schema = $this->get_item_schema(); + $properties = array_keys( $schema['properties'] ); + + if ( in_array( 'image', $properties, true ) ) { + $response['image'] = $settings['autoConversionSettings']['enabled']; + } + + if ( in_array( 'auto-conversion', $properties, true ) ) { + $response['auto-conversion'] = $settings['autoConversionSettings']['enabled']; + } + + return rest_ensure_response( $response ); + } + + /** + * POST `/jetpack/v4/auto-conversion/settings` + * + * @param WP_REST_Request $request The API request. + * + * @return WP_REST_Response|WP_Error + */ + public function update_auto_coversion_settings( $request ) { + $settings = new Jetpack_Social_Settings(); + + if ( isset( $request['image'] ) ) { + $settings->update_auto_conversion_setting( array( 'enabled' => $request['image'] ) ); + } + + return rest_ensure_response( $this->get_auto_coversion_settings() ); + } + + /** + * Check the permissions for accessing and updating the settings endpoint. + * + * @return bool|WP_Error True if user can manage options. + */ + public function settings_permissions_callback() { + if ( ! current_user_can( 'edit_posts' ) ) { + return new WP_Error( + 'rest_forbidden_context', + __( 'Sorry, you are not allowed to access this endpoint.', 'jetpack-publicize-pkg' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + return true; + } + + /** + * Retrieves the settings schema, conforming to JSON Schema. + * + * @return array Schema data. + */ + public function get_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'auto-conversion-settings', + 'type' => 'object', + 'properties' => array( + 'image' => array( + 'description' => __( 'Whether or not auto-conversion for images is enabled.', 'jetpack-publicize-pkg' ), + 'type' => 'boolean', + 'context' => array( 'view', 'edit' ), + ), + 'video' => array( + 'description' => __( 'Whether or not auto-conversion for videos is enabled.', 'jetpack-publicize-pkg' ), + 'type' => 'boolean', + 'context' => array( 'view', 'edit' ), + ), + 'auto-conversion' => array( + 'description' => __( 'Whether or not auto-conversion is enabled.', 'jetpack-publicize-pkg' ), + 'type' => 'boolean', + 'context' => array( 'view', 'edit' ), + ), + ), + ); + + return rest_default_additional_properties_to_false( $schema ); + } +} diff --git a/projects/packages/publicize/src/auto-conversion-settings/class-settings.php b/projects/packages/publicize/src/auto-conversion-settings/class-settings.php new file mode 100644 index 0000000000000..e7c17e183b363 --- /dev/null +++ b/projects/packages/publicize/src/auto-conversion-settings/class-settings.php @@ -0,0 +1,76 @@ +<?php +/** + * Settings class. + * Flagged to be removed after deprecation. + * + * @deprecated $$next_version$$ + * + * @package automattic/jetpack-publicize + */ + +namespace Automattic\Jetpack\Publicize\Auto_Conversion; + +use Automattic\Jetpack\Publicize\Jetpack_Social_Settings\Settings as Jetpack_Social_Settings; + +/** + * This class is used to get and update Auto_Conversion_Settings. + */ +class Settings { + /** + * Name of the database option. + * + * @var string + */ + const OPTION_NAME = 'jetpack_social_settings'; + + /** + * Array with auto conversion settings. + * + * @var array $settings + */ + public $settings; + + /** + * Constructor. + */ + public function __construct() { + $this->settings = $this->get_settings(); + } + + /** + * Get the current auto conversion settings. + * + * @return array + */ + private function get_settings() { + $new_settings = ( new Jetpack_Social_Settings() )->get_settings(); + + return array( + 'image' => $new_settings['autoConversionSettings']['enabled'], + ); + } + + /** + * Check if the auto conversion feature is available. + * + * @param string $type Whether video or image. + * @return bool True if available, false otherwise. + */ + public function is_available( $type ) { + return ( new Jetpack_Social_Settings() )->is_auto_conversion_available( $type ); + } + + /** + * Check if the auto conversion feature is enabled. + * + * @param string $type Whether video or image. + * + * @return bool True if the feature is enabled, false otherwise. + */ + public function is_enabled( $type ) { + if ( 'image' === $type ) { + $new_settings = ( new Jetpack_Social_Settings() )->get_settings(); + return $new_settings['autoConversionSettings']['enabled']; + } + } +} diff --git a/projects/packages/publicize/src/class-publicize-setup.php b/projects/packages/publicize/src/class-publicize-setup.php index 2c8663f0490f8..439ebecd79d32 100644 --- a/projects/packages/publicize/src/class-publicize-setup.php +++ b/projects/packages/publicize/src/class-publicize-setup.php @@ -45,6 +45,10 @@ public static function on_jetpack_feature_publicize_enabled() { add_action( 'rest_api_init', array( new Jetpack_Social_Settings\Settings(), 'register_settings' ) ); add_action( 'admin_init', array( new Jetpack_Social_Settings\Settings(), 'register_settings' ) ); + // Flagged to be removed after deprecation. + // @deprecated $$next_version$$ + add_action( 'rest_api_init', array( new Auto_Conversion\REST_Settings_Controller(), 'register_routes' ) ); + ( new Social_Image_Generator\Setup() )->init(); } diff --git a/projects/packages/publicize/src/jetpack-social-settings/class-settings.php b/projects/packages/publicize/src/jetpack-social-settings/class-settings.php index abd8a18226264..066f55089b477 100644 --- a/projects/packages/publicize/src/jetpack-social-settings/class-settings.php +++ b/projects/packages/publicize/src/jetpack-social-settings/class-settings.php @@ -54,7 +54,9 @@ private function migrate_old_option() { } // Checking if the new option is valid. $auto_conversion_settings = get_option( self::OPTION_PREFIX . self::AUTOCONVERT_IMAGES ); - if ( ! is_array( $auto_conversion_settings ) || ! isset( $auto_conversion_settings['enabled'] ) ) { + // If the option is not set, we don't need to delete it. + // If it is set, but it is not an array or it does not have the enabled key, we delete it. + if ( false !== $auto_conversion_settings && ( ! is_array( $auto_conversion_settings ) || ! isset( $auto_conversion_settings['enabled'] ) ) ) { delete_option( self::OPTION_PREFIX . self::AUTOCONVERT_IMAGES ); } diff --git a/projects/packages/publicize/src/social-image-generator/class-rest-settings-controller.php b/projects/packages/publicize/src/social-image-generator/class-rest-settings-controller.php new file mode 100644 index 0000000000000..4ffe62522c6cf --- /dev/null +++ b/projects/packages/publicize/src/social-image-generator/class-rest-settings-controller.php @@ -0,0 +1,142 @@ +<?php +/** + * Class used to register REST API settings endpoints used by Social Image Generator. + * + * Flagged to be removed after deprecation. + * + * @deprecated $$next_version$$ + * + * @package automattic/jetpack-publicize + */ + +namespace Automattic\Jetpack\Publicize\Social_Image_Generator; + +use Automattic\Jetpack\Publicize\Jetpack_Social_Settings\Settings as Jetpack_Social_Settings; +use WP_Error; +use WP_REST_Controller; +use WP_REST_Server; + +/** + * Defines our endpoints. + */ +class REST_Settings_Controller extends WP_REST_Controller { + /** + * Register REST API endpoints. + * + * @return void + */ + public function register_routes() { + register_rest_route( + 'jetpack/v4', + '/social-image-generator/settings', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_settings' ), + 'permission_callback' => array( $this, 'settings_permissions_callback' ), + ), + array( + 'methods' => WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'update_settings' ), + 'permission_callback' => array( $this, 'settings_permissions_callback' ), + 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * GET `/jetpack/v4/social-image-generator/settings` + * + * @return WP_REST_Response + */ + public function get_settings() { + $settings = ( new Jetpack_Social_Settings() )->get_settings(); + $response = array(); + $schema = $this->get_item_schema(); + $properties = array_keys( $schema['properties'] ); + + if ( in_array( 'enabled', $properties, true ) ) { + $response['enabled'] = $settings['socialImageGeneratorSettings']['enabled']; + } + + if ( in_array( 'defaults', $properties, true ) ) { + $response['defaults'] = array( 'template' => $settings['socialImageGeneratorSettings']['template'] ); + } + + return rest_ensure_response( $response ); + } + + /** + * POST `/jetpack/v4/social-image-generator/settings` + * + * @param WP_REST_Request $request The API request. + * + * @return WP_REST_Response|WP_Error + */ + public function update_settings( $request ) { + $settings = new Jetpack_Social_Settings(); + + if ( isset( $request['enabled'] ) ) { + $settings->update_social_image_generator_settings( array( 'enabled' => $request['enabled'] ) ); + + } + + if ( $request['defaults'] && $request['defaults']['template'] ) { + $settings->update_social_image_generator_settings( array( 'template' => $request['defaults']['template'] ) ); + } + + return rest_ensure_response( $this->get_settings() ); + } + + /** + * Check the permissions for accessing and updating the settings endpoint. + * + * @return bool|WP_Error True if user can manage options. + */ + public function settings_permissions_callback() { + if ( ! current_user_can( 'manage_options' ) ) { + return new WP_Error( + 'rest_forbidden_context', + __( 'Sorry, you are not allowed to access this endpoint.', 'jetpack-publicize-pkg' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + return true; + } + + /** + * Retrieves the Social Image Generator's settings schema, conforming to JSON Schema. + * + * @return array Schema data. + */ + public function get_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'social-image-generator-settings', + 'type' => 'object', + 'properties' => array( + 'enabled' => array( + 'description' => __( 'Whether or not Social Image Generator is enabled.', 'jetpack-publicize-pkg' ), + 'type' => 'boolean', + 'context' => array( 'view', 'edit' ), + ), + 'defaults' => array( + 'description' => __( 'The default settings for a new generated image.', 'jetpack-publicize-pkg' ), + 'type' => 'object', + 'context' => array( 'view', 'edit' ), + 'properties' => array( + 'template' => array( + 'type' => 'string', + 'enum' => Templates::TEMPLATES, + ), + ), + ), + ), + ); + + return rest_default_additional_properties_to_false( $schema ); + } +} diff --git a/projects/packages/publicize/src/social-image-generator/class-settings.php b/projects/packages/publicize/src/social-image-generator/class-settings.php new file mode 100644 index 0000000000000..b991594c4bed2 --- /dev/null +++ b/projects/packages/publicize/src/social-image-generator/class-settings.php @@ -0,0 +1,102 @@ +<?php +/** + * Settings class. + * + * Flagged to be removed after deprecation. + * + * @deprecated $$next_version$$ + * + * @package automattic/jetpack-publicize + */ + +namespace Automattic\Jetpack\Publicize\Social_Image_Generator; + +use Automattic\Jetpack\Publicize\Jetpack_Social_Settings\Settings as Jetpack_Social_Settings; + +/** + * This class is used to get and update SIG-specific global settings. + */ +class Settings { + /** + * Name of the database option. + * + * @var string + */ + const OPTION_NAME = 'jetpack_social_image_generator_settings'; + + /** + * Array with SIG's settings. + * + * @var array $settings + */ + public $settings; + + /** + * Constructor. + */ + public function __construct() { + $this->settings = $this->get_settings(); + } + + /** + * Get all current SIG settings. + * + * @return array + */ + private function get_settings() { + $new_settings = ( new Jetpack_Social_Settings() )->get_settings(); + + return array( + 'enabled' => $new_settings['socialImageGeneratorSettings']['enabled'], + 'defaults' => array( + 'template' => $new_settings['socialImageGeneratorSettings']['template'], + ), + ); + } + + /** + * Check if SIG is available. + * + * @return bool True if SIG is available, false otherwise. + */ + public function is_available() { + return ( new Jetpack_Social_Settings() )->is_sig_available(); + } + + /** + * Check if SIG is enabled. + * + * @return bool True if SIG is enabled, false otherwise. + */ + public function is_enabled() { + $new_settings = ( new Jetpack_Social_Settings() )->get_settings(); + + return $new_settings['socialImageGeneratorSettings']['enabled']; + } + + /** + * Get an array of all current defaults. + * + * @return array + */ + public function get_defaults() { + if ( isset( $this->settings['defaults'] ) ) { + return $this->settings['defaults']; + } + + return array( + 'template' => Templates::DEFAULT_TEMPLATE, + ); + } + + /** + * Get the current default template. + * + * @return string + */ + public function get_default_template() { + $defaults = $this->get_defaults(); + + return isset( $defaults['template'] ) ? $defaults['template'] : Templates::DEFAULT_TEMPLATE; + } +} diff --git a/projects/packages/publicize/src/social-image-generator/class-setup.php b/projects/packages/publicize/src/social-image-generator/class-setup.php index 89c29c5c13e13..43583fd08994b 100644 --- a/projects/packages/publicize/src/social-image-generator/class-setup.php +++ b/projects/packages/publicize/src/social-image-generator/class-setup.php @@ -26,6 +26,10 @@ public function init() { // of 10 we make sure that our code runs before Sync processes the post. add_action( 'wp_after_insert_post', array( $this, 'generate_token_on_save' ), 10, 3 ); add_action( 'rest_api_init', array( new REST_Token_Controller(), 'register_routes' ) ); + + // Flagged to be removed after deprecation. + // @deprecated $$next_version$$ + add_action( 'rest_api_init', array( new REST_Settings_Controller(), 'register_routes' ) ); } /** diff --git a/projects/packages/search/CHANGELOG.md b/projects/packages/search/CHANGELOG.md index d4e1e2f99f257..bb14a88bc6385 100644 --- a/projects/packages/search/CHANGELOG.md +++ b/projects/packages/search/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.40.4] - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + ## [0.40.3] - 2023-12-11 ### Changed - Updated package dependencies. [#34416] @@ -861,6 +865,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated package dependencies. - Update PHPUnit configs to include just what needs coverage rather than include everything then try to exclude stuff that doesn't. +[0.40.4]: https://github.com/Automattic/jetpack-search/compare/v0.40.3...v0.40.4 [0.40.3]: https://github.com/Automattic/jetpack-search/compare/v0.40.2...v0.40.3 [0.40.2]: https://github.com/Automattic/jetpack-search/compare/v0.40.1...v0.40.2 [0.40.1]: https://github.com/Automattic/jetpack-search/compare/v0.40.0...v0.40.1 diff --git a/projects/packages/search/package.json b/projects/packages/search/package.json index 1ef71fd0ee63a..812bd5d77e4d9 100644 --- a/projects/packages/search/package.json +++ b/projects/packages/search/package.json @@ -1,6 +1,6 @@ { "name": "jetpack-search", - "version": "0.40.3", + "version": "0.40.4", "description": "Package for Jetpack Search products", "main": "main.js", "directories": { @@ -71,9 +71,9 @@ "@babel/preset-typescript": "7.23.3", "@babel/runtime": "7.23.5", "@size-limit/preset-app": "8.2.6", - "@testing-library/dom": "8.20.1", + "@testing-library/dom": "9.3.3", "@testing-library/preact": "3.2.3", - "@testing-library/react": "13.4.0", + "@testing-library/react": "14.1.2", "@wordpress/babel-plugin-import-jsx-pragma": "4.30.0", "@wordpress/browserslist-config": "5.30.0", "@wordpress/dependency-extraction-webpack-plugin": "4.30.0", diff --git a/projects/packages/search/src/class-package.php b/projects/packages/search/src/class-package.php index b3a9aa083e06c..867bc0b1b3e08 100644 --- a/projects/packages/search/src/class-package.php +++ b/projects/packages/search/src/class-package.php @@ -11,7 +11,7 @@ * Search package general information */ class Package { - const VERSION = '0.40.3'; + const VERSION = '0.40.4'; const SLUG = 'search'; /** diff --git a/projects/packages/stats/changelog/add-utm-tracking b/projects/packages/stats/changelog/add-utm-tracking new file mode 100644 index 0000000000000..da83c6633866d --- /dev/null +++ b/projects/packages/stats/changelog/add-utm-tracking @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Stats: added passing select UTM parameters to Tracking Pixel requests. diff --git a/projects/packages/stats/src/class-tracking-pixel.php b/projects/packages/stats/src/class-tracking-pixel.php index c6e2cca3c8764..e9caff4ce1567 100644 --- a/projects/packages/stats/src/class-tracking-pixel.php +++ b/projects/packages/stats/src/class-tracking-pixel.php @@ -27,6 +27,18 @@ class Tracking_Pixel { */ const STATS_ARRAY_TO_STRING_FILTER = 'stats_array'; + const TRACKED_UTM_PARAMETERS = array( + 'utm_id', + 'utm_source', + 'utm_medium', + 'utm_campaign', + 'utm_term', + 'utm_content', + 'utm_source_platform', + 'utm_creative_format', + 'utm_marketing_tactic', + ); + /** * Stats Build View Data. * @@ -61,7 +73,20 @@ public static function build_view_data() { } else { $post = '0'; } - return compact( 'v', 'blog', 'post', 'tz', 'srv' ); + $view_data = compact( 'v', 'blog', 'post', 'tz', 'srv' ); + // Batcache removes some of the UTM params from $_GET, we need to extract them from uri directly instead. + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We're sanitizing individual params in the loop. + $url_query = wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ), PHP_URL_QUERY ); + parse_str( (string) $url_query, $url_params ); + foreach ( self::TRACKED_UTM_PARAMETERS as $utm_parameter ) { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- UTMs are standardized parameters coming from outside WordPress, adding nonce is not possible + if ( isset( $url_params[ $utm_parameter ] ) && is_scalar( $url_params[ $utm_parameter ] ) ) { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- UTMs are standardized parameters coming from outside WordPress, adding nonce is not possible + $view_data[ $utm_parameter ] = substr( sanitize_textarea_field( wp_unslash( $url_params[ $utm_parameter ] ) ), 0, 255 ); + } + } + + return $view_data; } /** @@ -78,7 +103,7 @@ private static function build_stats_details( $data ) { return sprintf( '_stq = window._stq || []; -_stq.push([ "view", {%1$s} ]); +_stq.push([ "view", JSON.parse(%1$s) ]); _stq.push([ "clickTrackerInit", "%2$s", "%3$s" ]);', $data_stats_array, $data['blog'], @@ -236,13 +261,12 @@ private static function stats_array_to_string( $kvs ) { * * @param array $kvs Array of options about the site and page you're on. */ - $kvs = (array) apply_filters( self::STATS_ARRAY_TO_STRING_FILTER, $kvs ); - $kvs = array_map( 'addslashes', $kvs ); - $jskvs = array(); - foreach ( $kvs as $k => $v ) { - $jskvs[] = "$k:'$v'"; - } - return implode( ',', $jskvs ); + $kvs = (array) apply_filters( self::STATS_ARRAY_TO_STRING_FILTER, $kvs ); + $kvs = array_map( 'strval', $kvs ); + + // Encode into JSON object, and then encode it into a string that's safe to embed into Javascript. + // We will then use JSON.parse method in JS to read the array. + return wp_json_encode( wp_json_encode( $kvs ) ); } /** diff --git a/projects/packages/stats/tests/php/test-tracking-pixel.php b/projects/packages/stats/tests/php/test-tracking-pixel.php index 90351a4c58310..b199ba8c6cf64 100644 --- a/projects/packages/stats/tests/php/test-tracking-pixel.php +++ b/projects/packages/stats/tests/php/test-tracking-pixel.php @@ -15,6 +15,14 @@ * @covers \Automattic\Jetpack\Stats\Tracking_Pixel */ class Test_Tracking_Pixel extends StatsBaseTestCase { + /** + * Set up + */ + protected function set_up() { + parent::set_up(); + + $_SERVER['REQUEST_URI'] = 'index.html?utm_source=a_source&utm_id=some_id'; + } /** * Clean up the testing environment. @@ -25,7 +33,8 @@ public function tear_down() { parent::tear_down(); global $wp_the_query; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited - $wp_the_query = new WP_Query(); + $wp_the_query = new WP_Query(); + $_SERVER['REQUEST_URI'] = ''; } /** @@ -39,11 +48,13 @@ public function test_build_view_data_with_post() { $wp_the_query->queried_object = self::post( 7 ); $view_data = Tracking_Pixel::build_view_data(); $expected_view_data = array( - 'v' => 'ext', - 'blog' => 1234, - 'post' => 7, - 'tz' => false, - 'srv' => 'example.org', + 'v' => 'ext', + 'blog' => 1234, + 'post' => 7, + 'tz' => false, + 'srv' => 'example.org', + 'utm_id' => 'some_id', + 'utm_source' => 'a_source', ); $this->assertSame( $expected_view_data, $view_data ); } @@ -57,11 +68,13 @@ public function test_build_view_data_with_gmt_offset() { add_option( 'gmt_offset', '5' ); $view_data = Tracking_Pixel::build_view_data(); $expected_view_data = array( - 'v' => 'ext', - 'blog' => 1234, - 'post' => '0', - 'tz' => '5', - 'srv' => 'example.org', + 'v' => 'ext', + 'blog' => 1234, + 'post' => '0', + 'tz' => '5', + 'srv' => 'example.org', + 'utm_id' => 'some_id', + 'utm_source' => 'a_source', ); $this->assertSame( $expected_view_data, $view_data ); } @@ -122,9 +135,9 @@ public function test_get_footer_to_add_applies_filter() { $method->setAccessible( true ); $pixel_details = $method->invoke( new Tracking_Pixel(), $data ); - $expected_pixel_details = "_stq = window._stq || []; -_stq.push([ \"view\", {v:'ext',blog:'1234',post:'0',tz:'',srv:'replaced.com'} ]); -_stq.push([ \"clickTrackerInit\", \"1234\", \"0\" ]);"; + $expected_pixel_details = '_stq = window._stq || []; +_stq.push([ "view", JSON.parse("{\"v\":\"ext\",\"blog\":\"1234\",\"post\":\"0\",\"tz\":\"\",\"srv\":\"replaced.com\"}") ]); +_stq.push([ "clickTrackerInit", "1234", "0" ]);'; remove_filter( 'stats_array', array( $this, 'stats_array_filter_replace_srv' ) ); $this->assertSame( $expected_pixel_details, $pixel_details ); diff --git a/projects/packages/sync/CHANGELOG.md b/projects/packages/sync/CHANGELOG.md index 312d78baa8c74..0edf3271e0044 100644 --- a/projects/packages/sync/CHANGELOG.md +++ b/projects/packages/sync/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.3.0] - 2023-12-20 +### Added +- Add wpcom_ai_site_prompt option to the site settings endpoint. [#34709] + +### Fixed +- Added preemptive check to break expanding metadata for posts loop in Full Sync. [#34661] + ## [2.2.1] - 2023-12-13 ### Changed - Refactored loop to improve efficiency and code readability [#34565] @@ -1003,6 +1010,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Packages: Move sync to a classmapped package +[2.3.0]: https://github.com/Automattic/jetpack-sync/compare/v2.2.1...v2.3.0 [2.2.1]: https://github.com/Automattic/jetpack-sync/compare/v2.2.0...v2.2.1 [2.2.0]: https://github.com/Automattic/jetpack-sync/compare/v2.1.2...v2.2.0 [2.1.2]: https://github.com/Automattic/jetpack-sync/compare/v2.1.1...v2.1.2 diff --git a/projects/packages/sync/composer.json b/projects/packages/sync/composer.json index 2e081cd3169fa..89c76bbc87d2c 100644 --- a/projects/packages/sync/composer.json +++ b/projects/packages/sync/composer.json @@ -58,7 +58,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "config": { diff --git a/projects/packages/sync/src/class-defaults.php b/projects/packages/sync/src/class-defaults.php index df88d7d4e3fc5..bba2931eb9c99 100644 --- a/projects/packages/sync/src/class-defaults.php +++ b/projects/packages/sync/src/class-defaults.php @@ -178,6 +178,7 @@ class Defaults { 'wp_mobile_excerpt', 'wp_mobile_featured_images', 'wp_page_for_privacy_policy', + 'wpcom_ai_site_prompt', 'wpcom_featured_image_in_email', 'wpcom_gifting_subscription', 'wpcom_is_fse_activated', diff --git a/projects/packages/sync/src/class-package-version.php b/projects/packages/sync/src/class-package-version.php index fef9c87ac0806..deaf42f468b36 100644 --- a/projects/packages/sync/src/class-package-version.php +++ b/projects/packages/sync/src/class-package-version.php @@ -12,7 +12,7 @@ */ class Package_Version { - const PACKAGE_VERSION = '2.2.1'; + const PACKAGE_VERSION = '2.3.0'; const PACKAGE_SLUG = 'sync'; diff --git a/projects/packages/sync/src/modules/class-posts.php b/projects/packages/sync/src/modules/class-posts.php index 01c367898992f..ef8cfc74cf868 100644 --- a/projects/packages/sync/src/modules/class-posts.php +++ b/projects/packages/sync/src/modules/class-posts.php @@ -891,6 +891,9 @@ public function filter_posts_and_metadata_max_size( $posts, $metadata ) { } $current_metadata[] = $metadata_item; $metadata_size += $metadata_item_size >= self::MAX_POST_META_LENGTH ? 0 : $metadata_item_size; + if ( ! empty( $filtered_post_ids ) && ( $current_size + $post_content_size + $metadata_size ) > ( self::MAX_SIZE_FULL_SYNC ) ) { + break 2; // Break both foreach loops. + } unset( $metadata[ $key ] ); } } diff --git a/projects/packages/videopress/CHANGELOG.md b/projects/packages/videopress/CHANGELOG.md index a928e23ed221b..597ce72d634b3 100644 --- a/projects/packages/videopress/CHANGELOG.md +++ b/projects/packages/videopress/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.21.5] - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + +### Fixed +- Updated name of Abstract_Token_Subscription_Service [#34723] + ## [0.21.4] - 2023-12-06 ### Changed - Updated package dependencies. [#34416] @@ -1206,6 +1213,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Created empty package [#24952] +[0.21.5]: https://github.com/Automattic/jetpack-videopress/compare/v0.21.4...v0.21.5 [0.21.4]: https://github.com/Automattic/jetpack-videopress/compare/v0.21.3...v0.21.4 [0.21.3]: https://github.com/Automattic/jetpack-videopress/compare/v0.21.2...v0.21.3 [0.21.2]: https://github.com/Automattic/jetpack-videopress/compare/v0.21.1...v0.21.2 diff --git a/projects/packages/videopress/package.json b/projects/packages/videopress/package.json index fc6bc8d11e063..e6b72c219d1d4 100644 --- a/projects/packages/videopress/package.json +++ b/projects/packages/videopress/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-videopress", - "version": "0.21.4", + "version": "0.21.5", "description": "VideoPress package", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/videopress/#readme", "bugs": { @@ -29,11 +29,11 @@ "@babel/core": "7.23.5", "@babel/preset-react": "7.23.3", "@jest/globals": "29.4.3", - "@storybook/blocks": "7.4.6", - "@storybook/client-api": "7.4.6", - "@storybook/react": "7.4.6", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@storybook/blocks": "7.6.5", + "@storybook/client-api": "7.6.5", + "@storybook/react": "7.6.5", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@types/jest": "29.5.10", "@types/react": "18.2.33", "@types/react-dom": "18.2.14", @@ -61,7 +61,7 @@ "@automattic/jetpack-components": "workspace:*", "@automattic/jetpack-connection": "workspace:*", "@automattic/jetpack-shared-extension-utils": "workspace:*", - "@storybook/addon-actions": "7.4.6", + "@storybook/addon-actions": "7.6.5", "@wordpress/api-fetch": "6.44.0", "@wordpress/blob": "3.47.0", "@wordpress/block-editor": "12.15.0", diff --git a/projects/packages/videopress/src/class-access-control.php b/projects/packages/videopress/src/class-access-control.php index dd1503a96332c..e6a9fa2c5ffe5 100644 --- a/projects/packages/videopress/src/class-access-control.php +++ b/projects/packages/videopress/src/class-access-control.php @@ -7,6 +7,8 @@ namespace Automattic\Jetpack\VideoPress; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; use Automattic\Jetpack\Modules; use VIDEOPRESS_PRIVACY; @@ -177,7 +179,12 @@ private function check_block_level_access( $restriction_details, $guid, $embedde $paywall = \Automattic\Jetpack\Extensions\Premium_Content\subscription_service(); // Only paid subscribers should be granted access to the premium content. - $access_level = \Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS; + if ( class_exists( Abstract_Token_Subscription_Service::class ) ) { + $access_level = Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS; + } else { + $access_level = Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS; + } + $can_view = $paywall->visitor_can_view_content( array( $selected_plan_id ), $access_level ); $restriction_details['can_access'] = $can_view || current_user_can( 'edit_post', $embedded_post_id ); // Editors can always view the content. } diff --git a/projects/packages/videopress/src/class-package-version.php b/projects/packages/videopress/src/class-package-version.php index 5611da28eabd4..a79e165d42646 100644 --- a/projects/packages/videopress/src/class-package-version.php +++ b/projects/packages/videopress/src/class-package-version.php @@ -11,7 +11,7 @@ * The Package_Version class. */ class Package_Version { - const PACKAGE_VERSION = '0.21.4'; + const PACKAGE_VERSION = '0.21.5'; const PACKAGE_SLUG = 'videopress'; diff --git a/projects/packages/wordads/CHANGELOG.md b/projects/packages/wordads/CHANGELOG.md index 54dd8ed4a4222..0642913a4687f 100644 --- a/projects/packages/wordads/CHANGELOG.md +++ b/projects/packages/wordads/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.3] - 2023-12-20 +### Changed +- Updated package dependencies. [#34694] + ## [0.3.2] - 2023-12-11 ### Changed - Updated package dependencies. [#34416] @@ -283,6 +287,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - PHPCS: Fix `WordPress.Security.ValidatedSanitizedInput` - Updated package dependencies. +[0.3.3]: https://github.com/Automattic/jetpack-wordads/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/Automattic/jetpack-wordads/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/Automattic/jetpack-wordads/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/Automattic/jetpack-wordads/compare/v0.2.58...v0.3.0 diff --git a/projects/packages/wordads/package.json b/projects/packages/wordads/package.json index 1cfe1a379fc84..f93b4b210302c 100644 --- a/projects/packages/wordads/package.json +++ b/projects/packages/wordads/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-wordads", - "version": "0.3.2", + "version": "0.3.3", "description": "Earn income by allowing Jetpack to display high quality ads.", "main": "main.js", "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/wordads/#readme", @@ -66,9 +66,9 @@ "@babel/preset-react": "7.23.3", "@babel/preset-typescript": "7.23.3", "@babel/runtime": "7.23.5", - "@testing-library/dom": "8.20.1", + "@testing-library/dom": "9.3.3", "@testing-library/preact": "3.2.3", - "@testing-library/react": "13.4.0", + "@testing-library/react": "14.1.2", "@wordpress/babel-plugin-import-jsx-pragma": "4.30.0", "@wordpress/browserslist-config": "5.30.0", "@wordpress/dependency-extraction-webpack-plugin": "4.30.0", diff --git a/projects/packages/wordads/src/class-package.php b/projects/packages/wordads/src/class-package.php index 2c66b2d4fc89e..c2e7a59fbbb56 100644 --- a/projects/packages/wordads/src/class-package.php +++ b/projects/packages/wordads/src/class-package.php @@ -11,7 +11,7 @@ * WordAds package general information */ class Package { - const VERSION = '0.3.2'; + const VERSION = '0.3.3'; const SLUG = 'wordads'; /** diff --git a/projects/plugins/backup/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/backup/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/backup/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/backup/composer.json b/projects/plugins/backup/composer.json index 7d8cc4a8dbb80..9fe9ec4f8b7c6 100644 --- a/projects/plugins/backup/composer.json +++ b/projects/plugins/backup/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "prefer-stable": true, "config": { - "autoloader-suffix": "9559eef123208b7d1b9c15b978567267_backupⓥ2_3", + "autoloader-suffix": "9559eef123208b7d1b9c15b978567267_backupⓥ2_4_alpha", "allow-plugins": { "automattic/jetpack-autoloader": true, "automattic/jetpack-composer-plugin": true diff --git a/projects/plugins/backup/composer.lock b/projects/plugins/backup/composer.lock index 19563b07707e3..d0c8752ff9fef 100644 --- a/projects/plugins/backup/composer.lock +++ b/projects/plugins/backup/composer.lock @@ -1405,7 +1405,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1437,7 +1437,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/backup/jetpack-backup.php b/projects/plugins/backup/jetpack-backup.php index dfd253eba1c97..840369391f631 100644 --- a/projects/plugins/backup/jetpack-backup.php +++ b/projects/plugins/backup/jetpack-backup.php @@ -4,7 +4,7 @@ * Plugin Name: Jetpack VaultPress Backup * Plugin URI: https://jetpack.com/jetpack-backup * Description: Easily restore or download a backup of your site from a specific moment in time. - * Version: 2.3 + * Version: 2.4-alpha * Author: Automattic - Jetpack Backup team * Author URI: https://jetpack.com/ * License: GPLv2 or later diff --git a/projects/plugins/boost/CHANGELOG.md b/projects/plugins/boost/CHANGELOG.md index 754ba133e3318..27f0c59e3267a 100644 --- a/projects/plugins/boost/CHANGELOG.md +++ b/projects/plugins/boost/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.2.0-beta] - 2023-10-26 +## [2.2.1] - 2023-12-21 +### Fixed +- Defer JS: added importmap to the exclusion list to fix compatibility issues. [#34746] + +## [2.2.0] - 2023-10-31 ### Changed - General: Indicate full compatibility with the latest version of WordPress, 6.4. [#33776] - Getting Started: Improved how features are sorted in the getting started page. [#33766] @@ -341,7 +345,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - First public alpha release -[2.2.0-beta]: https://github.com/Automattic/jetpack-boost-production/compare/2.1.1...2.2.0-beta +[2.2.1]: https://github.com/Automattic/jetpack-boost-production/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/Automattic/jetpack-boost-production/compare/2.1.1...2.2.0 [2.1.1]: https://github.com/Automattic/jetpack-boost-production/compare/2.0.2...2.1.1 [2.0.2]: https://github.com/Automattic/jetpack-boost-production/compare/2.0.1...2.0.2 [2.0.1]: https://github.com/Automattic/jetpack-boost-production/compare/2.0.0...2.0.1 diff --git a/projects/plugins/boost/app/admin/class-admin.php b/projects/plugins/boost/app/admin/class-admin.php index dad7e0a08de47..0e9f72b86f929 100644 --- a/projects/plugins/boost/app/admin/class-admin.php +++ b/projects/plugins/boost/app/admin/class-admin.php @@ -14,7 +14,6 @@ use Automattic\Jetpack_Boost\Lib\Analytics; use Automattic\Jetpack_Boost\Lib\Environment_Change_Detector; use Automattic\Jetpack_Boost\Lib\Premium_Features; -use Automattic\Jetpack_Boost\Lib\Premium_Pricing; use Automattic\Jetpack_Boost\Lib\Super_Cache_Info; use Automattic\Jetpack_Boost\Modules\Modules_Setup; @@ -50,7 +49,6 @@ public function __construct( Modules_Setup $modules ) { $this->modules = $modules; $this->speed_score = new Speed_Score( $modules, 'boost-plugin' ); Environment_Change_Detector::init(); - Premium_Pricing::init(); $this->config = new Config(); $this->config->init(); diff --git a/projects/plugins/boost/app/admin/class-config.php b/projects/plugins/boost/app/admin/class-config.php index ce151a0afb766..7439ec00c60c5 100644 --- a/projects/plugins/boost/app/admin/class-config.php +++ b/projects/plugins/boost/app/admin/class-config.php @@ -4,6 +4,7 @@ use Automattic\Jetpack\Status; use Automattic\Jetpack\Status\Host; +use Automattic\Jetpack_Boost\Data_Sync\Getting_Started_Entry; use Automattic\Jetpack_Boost\Lib\Premium_Features; use Automattic\Jetpack_Boost\Modules\Modules_Setup; use Automattic\Jetpack_Boost\REST_API\Permissions\Nonce; @@ -84,36 +85,10 @@ public function check_for_permissions() { */ public function on_module_status_change( $module, $status ) { if ( $status ) { - self::set_getting_started( false ); + ( new Getting_Started_Entry() )->set( false ); } } - /** - * Enable of disable getting started page. - * - * If enabled, trying to open boost dashboard will take a user to the getting started page. - */ - public static function set_getting_started( $value ) { - return \update_option( 'jb_get_started', $value, false ); - } - - /** - * Check if force redirect to getting started page is enabled. - */ - public static function is_getting_started() { - // Aside from the boolean flag in the database, we also assume site already got started if they have premium features. - return ! Premium_Features::has_feature( Premium_Features::CLOUD_CSS ) && ! ( new Status() )->is_offline_mode(); - } - - /** - * Clear the getting started option. - * @deprecated - This option is no longer used. - * We'll keep the value cleaning here for a while, but it should be removed in the future. - */ - public static function clear_getting_started() { - \delete_option( 'jb_get_started' ); - } - /** * Retrieves custom post types. * diff --git a/projects/plugins/boost/app/assets/src/css/admin-style.scss b/projects/plugins/boost/app/assets/src/css/admin-style.scss index ac77d6b0a4578..fb0f03c51e008 100644 --- a/projects/plugins/boost/app/assets/src/css/admin-style.scss +++ b/projects/plugins/boost/app/assets/src/css/admin-style.scss @@ -8,7 +8,6 @@ // Components @import 'components/connection'; @import 'components/feature-toggle'; -@import 'components/benchmarks'; @import 'components/error-message'; @import 'components/critical-css'; @import 'components/close-button'; diff --git a/projects/plugins/boost/app/assets/src/css/components/connection.scss b/projects/plugins/boost/app/assets/src/css/components/connection.scss index f83a1b9aecb15..c9a2d1d15e12e 100644 --- a/projects/plugins/boost/app/assets/src/css/components/connection.scss +++ b/projects/plugins/boost/app/assets/src/css/components/connection.scss @@ -115,6 +115,10 @@ @include breakpoint(md) { padding: 0 70px; } + + &:focus-visible { + outline: none; + } } .jb-connection-overlay { diff --git a/projects/plugins/boost/app/assets/src/css/components/critical-css.scss b/projects/plugins/boost/app/assets/src/css/components/critical-css.scss index 8dc2708b1d9bc..76c82b4cb8e5b 100644 --- a/projects/plugins/boost/app/assets/src/css/components/critical-css.scss +++ b/projects/plugins/boost/app/assets/src/css/components/critical-css.scss @@ -166,29 +166,3 @@ min-width: 48px; } } - -.jb-premium-cta { - width: 100%; - display: flex; - justify-content: space-between; - align-items: center; - padding: 16px 24px; - margin: 32px 0; - border: 2px solid $jetpack-green; - border-radius: $border-radius; - background-color: #ffffff; - text-align: left; - cursor: pointer; - - p { - margin: 0; - } - - &__action-line { - font-weight: bold; - } - - &__icon svg { - fill: $jetpack-green; - } -} diff --git a/projects/plugins/boost/app/assets/src/css/main/dashboard.scss b/projects/plugins/boost/app/assets/src/css/main/dashboard.scss index e50df02ffa663..7c2de36949244 100644 --- a/projects/plugins/boost/app/assets/src/css/main/dashboard.scss +++ b/projects/plugins/boost/app/assets/src/css/main/dashboard.scss @@ -1,6 +1,3 @@ -.jb-feature-toggle__content h3:focus-visible, .jb-connection__title:focus-visible { - outline: none; -} .jb-section { padding-top: $padding; diff --git a/projects/plugins/boost/app/assets/src/js/Main.svelte b/projects/plugins/boost/app/assets/src/js/Main.svelte index c25bd8af17393..452a2d969b7fe 100644 --- a/projects/plugins/boost/app/assets/src/js/Main.svelte +++ b/projects/plugins/boost/app/assets/src/js/Main.svelte @@ -1,84 +1,28 @@ <script lang="ts"> - import AdvancedCriticalCss from './pages/critical-css-advanced/critical-css-advanced'; - import GettingStarted from './pages/getting-started/getting-started'; - import RecommendationsPage from './pages/image-size-analysis/ImageSizeAnalysis.svelte'; - import Index from './pages/index/Index.svelte'; - import PurchaseSuccess from './pages/purchase-success/purchase-success'; - import Upgrade from './pages/upgrade/upgrade'; import ReactComponent from '$features/ReactComponent.svelte'; - import Redirect from '$features/Redirect.svelte'; - import SettingsPage from '$layout/SettingsPage/SettingsPage.svelte'; - import config from '$lib/stores/config'; - import { connection } from '$lib/stores/connection'; - import { criticalCssIssues } from '$features/critical-css'; - import { modulesState } from '$lib/stores/modules'; - import { recordBoostEvent } from '$lib/utils/analytics'; - import debounce from '$lib/utils/debounce'; - import { Route, Router } from '$lib/utils/router'; - import routerHistory from '$lib/utils/router-history'; - - routerHistory.listen( - debounce( history => { - // Event names must conform to the following regex: ^[a-z_][a-z0-9_]*$ - let path = history.location.pathname.replace( /[-/]/g, '_' ); - if ( path === '_' ) { - path = '_settings'; - } - - recordBoostEvent( `page_view${ path }`, { - path: history.location.pathname, - } ); - }, 10 ) - ); - - $: pricing = $config.pricing; - - $: siteDomain = $config.site.domain; - $: userConnected = $connection.userConnected; - $: isPremium = $config.isPremium; - $: isImageGuideActive = $modulesState.image_guide.active; - $: isImageSizeAnalysisAvailable = $modulesState.image_size_analysis.available; - $: isImageSizeAnalysisActive = $modulesState.image_size_analysis.active; - - $: shouldGetStarted = ! $connection.connected && $config.site.online; + import Main from './main'; + import { + criticalCssState, + continueGeneratingLocalCriticalCss, + regenerateCriticalCss, + criticalCssProgress, + isFatalError, + criticalCssIssues, + primaryErrorSet, + } from '$features/critical-css'; </script> -<Router history={routerHistory}> - <Route path="upgrade"> - <ReactComponent this={Upgrade} {pricing} {siteDomain} {userConnected} /> - </Route> - - <Route path="getting-started"> - <ReactComponent - this={GettingStarted} - {userConnected} - {pricing} - {isPremium} - domain={siteDomain} - /> - </Route> - - <Route path="purchase-successful"> - <ReactComponent this={PurchaseSuccess} {isImageGuideActive} /> - </Route> - - <Route path="critical-css-advanced"> - <Redirect when={shouldGetStarted} to="/getting-started"> - <SettingsPage> - <ReactComponent this={AdvancedCriticalCss} issues={$criticalCssIssues} /> - </SettingsPage> - </Redirect> - </Route> - - <Route path="/"> - <Redirect when={shouldGetStarted} to="/getting-started"> - <SettingsPage> - <Index /> - </SettingsPage> - </Redirect> - </Route> - - {#if isImageSizeAnalysisAvailable && isImageSizeAnalysisActive} - <Route path="image-size-analysis/:group/:page" component={RecommendationsPage} /> - {/if} -</Router> +<div> + <ReactComponent + this={Main} + criticalCss={{ + criticalCssState: $criticalCssState, + continueGeneratingLocalCriticalCss, + regenerateCriticalCss, + criticalCssProgress: $criticalCssProgress, + isFatalError: $isFatalError, + issues: $criticalCssIssues, + primaryErrorSet: $primaryErrorSet, + }} + /> +</div> diff --git a/projects/plugins/boost/app/assets/src/js/features/ErrorNotice.svelte b/projects/plugins/boost/app/assets/src/js/features/ErrorNotice.svelte deleted file mode 100644 index 5a517f5224e2a..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/ErrorNotice.svelte +++ /dev/null @@ -1,98 +0,0 @@ -<script lang="ts"> - import { createEventDispatcher } from 'svelte'; - import TemplatedString from './TemplatedString.svelte'; - import { ApiError } from '$lib/api/api-error'; - import actionLinkTemplateVar from '$lib/utils/action-link-template-var'; - import { TemplateVars } from '$lib/utils/copy-dom-template'; - import { standardizeError } from '$lib/utils/standardize-error'; - import supportLinkTemplateVar from '$lib/utils/support-link-template-var'; - import NoticeIcon from '$svg/notice-outline.svg'; - - /** - * Title to display above the error message. - */ - export let title: string; - - /** - * Error being displayed. Automatically populates - * description (and if appropriate data) sections. - * - * Note: Description can be overridden by the default slot, if one is provided. - */ - export let error: Error | string = new Error( title ); - - /** - * Optional raw string data to include with error. Automatically pulled out of ApiErrors. - */ - export let data = ''; - - /** - * Optional suggestion to include after the error message. - */ - export let suggestion = ''; - - /** - * Optional template variables to substitute for tags in the error suggestions. - * Note: Unless you supply a custom description slot and template it yourself, - * these will not apply to the main message / description, as it may be unsafe to parse as HTML. - * Note: the following template vars are automatically included in all errors: - * - <support>: a link to support. - * - <action name="">: A link to dispatch the named action. - */ - export let vars: TemplateVars = {}; - - // Figure out an appropriate description based on error object or message. - const description = standardizeError( error ).message; - - // Pull data out of ApiError if no data fed in. - if ( ! data && error instanceof ApiError ) { - data = error.getDisplayBody(); - } - - // Prepare an event dispatcher - which can dispatch actions when <action> links clicked. - // Dispatch as both the action by name, and as 'action' with a name attached. - const dispatch = createEventDispatcher(); - function dispatchAction( name ) { - dispatch( name ); - dispatch( 'action', name ); - } - - // Prepare template variables available to all errors. i.e.: <support> and <action> - const allVars = { - ...supportLinkTemplateVar(), - ...actionLinkTemplateVar( dispatchAction, 'action' ), - ...vars, - }; -</script> - -<div class="jb-error"> - <NoticeIcon class="icon" /> - - <div class="jb-error__main-content"> - <div class="jb-error__description"> - {title} - </div> - - <div class="jb-error__message"> - <slot> - <p> - {description} - </p> - </slot> - - {#if data} - <pre class="data">{data}</pre> - {/if} - - {#if suggestion} - <p class="suggestion"> - <TemplatedString template={suggestion} vars={allVars} /> - </p> - {/if} - </div> - </div> - - <div class="jb-error__main-action"> - <slot name="actionButton" /> - </div> -</div> diff --git a/projects/plugins/boost/app/assets/src/js/features/Module.svelte b/projects/plugins/boost/app/assets/src/js/features/Module.svelte deleted file mode 100644 index ac6763e5a553e..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/Module.svelte +++ /dev/null @@ -1,78 +0,0 @@ -<script lang="ts"> - import { createEventDispatcher, onMount } from 'svelte'; - import Toggle from '$features/ui/Toggle.svelte'; - import { modulesState, modulesStatePending } from '$lib/stores/modules'; - - export let toggle = true; - export let slug: string; - - const dispatch = createEventDispatcher(); - - $: isModuleActive = $modulesState[ slug ].active; - $: isModuleAvailable = $modulesState[ slug ].available; - - async function handleToggle() { - $modulesState[ slug ].active = ! isModuleActive; - } - - /** - * Watch for changes in state and dispatch an event when the state is no longer pending. - */ - let lastToggledState = $modulesState[ slug ].active; - $: { - if ( ! $modulesStatePending ) { - const newState = $modulesState[ slug ].active; - if ( lastToggledState !== newState ) { - lastToggledState = newState; - dispatch( newState ? 'enabled' : 'disabled' ); - } - } - } - - onMount( async () => { - if ( isModuleAvailable && isModuleActive ) { - dispatch( 'mountEnabled' ); - } - } ); -</script> - -{#if isModuleAvailable || slug === 'lazy_images'} - <div class="jb-feature-toggle"> - <div class="jb-feature-toggle__toggle"> - {#if toggle} - <Toggle - id={`jb-feature-toggle-${ slug }`} - checked={isModuleActive} - disabled={! isModuleAvailable} - on:click={handleToggle} - /> - {/if} - </div> - - <div class="jb-feature-toggle__content"> - <slot name="title" /> - - <div class="jb-feature-toggle__text"> - <slot name="description" /> - </div> - - <div class="jb-feature-toggle__content"> - <slot /> - - {#if isModuleActive} - <slot name="meta" /> - - <slot name="notice" /> - - <slot name="cta" /> - {/if} - </div> - </div> - </div> -{/if} - -<style> - .jb-feature-toggle__toggle { - min-width: 36px; - } -</style> diff --git a/projects/plugins/boost/app/assets/src/js/features/Notice.svelte b/projects/plugins/boost/app/assets/src/js/features/Notice.svelte deleted file mode 100644 index ae52274007fdd..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/Notice.svelte +++ /dev/null @@ -1,54 +0,0 @@ -<script lang="ts"> - import { Button, Notice } from '@automattic/jetpack-components'; - import React from 'react'; - import { createEventDispatcher } from 'svelte'; - import { slide } from 'svelte/transition'; - import ReactComponent from './ReactComponent.svelte'; - - type ActionButton = { - label: string; - onClick?: () => void; - isLoading?: boolean; - disabled?: boolean; - isExternalLink?: boolean; - variant?: 'primary' | 'secondary' | 'link' | 'tertiary'; - }; - - export let level: 'info' | 'warning' | 'success' | 'error' = 'info'; - export let title: string; - export let message: string; - export let actions: ActionButton[] = []; - export let hideCloseButton = true; - - const dispatch = createEventDispatcher(); - - const actionComponents = actions?.map( ( action, index ) => - React.createElement( - Button, - { - isPrimary: true, - onClick: action.onClick, - key: index, - isLoading: !! action.isLoading, - disabled: !! action.disabled, - isExternalLink: !! action.isExternalLink, - variant: action.variant || 'primary', - }, - action.label - ) - ); -</script> - -<div transition:slide|local> - <ReactComponent - this={Notice} - {level} - {title} - children={message} - actions={actionComponents} - onClose={() => { - dispatch( 'onClose' ); - }} - {hideCloseButton} - /> -</div> diff --git a/projects/plugins/boost/app/assets/src/js/features/ResizingUnavailable.svelte b/projects/plugins/boost/app/assets/src/js/features/ResizingUnavailable.svelte deleted file mode 100644 index 1b24437e5f438..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/ResizingUnavailable.svelte +++ /dev/null @@ -1,34 +0,0 @@ -<script lang="ts"> - import { __ } from '@wordpress/i18n'; -</script> - -<div class="jetpack-boost-notice"> - <h2>{__( 'Image resizing is unavailable', 'jetpack-boost' )}</h2> - <p> - {__( - "It looks like your server doesn't have Imagick or GD extensions installed.", - 'jetpack-boost' - )} - </p> - <p> - {__( - "Jetpack Boost is able to work without these extensions, but it's likely that it's going to be difficult for you to optimize the images that the Image Guide will identify without one of these extensions.", - 'jetpack-boost' - )} - </p> - <p> - {__( - 'Please contact your hosting provider or system administrator and ask them to install or activate one of these extensions.', - 'jetpack-boost' - )} - </p> -</div> - -<style lang="scss"> - .jetpack-boost-notice { - border: 2px solid var( --jp-green ); - padding: 24px 24px; - margin: 0 -24px; - border-radius: 4px; - } -</style> diff --git a/projects/plugins/boost/app/assets/src/js/features/UpgradeCTA.svelte b/projects/plugins/boost/app/assets/src/js/features/UpgradeCTA.svelte deleted file mode 100644 index 779026bd42682..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/UpgradeCTA.svelte +++ /dev/null @@ -1,45 +0,0 @@ -<script lang="ts"> - import { getCurrencyObject } from '@automattic/format-currency'; - import { onMount } from 'svelte'; - import { __, sprintf } from '@wordpress/i18n'; - import { recordBoostEvent } from '$lib/utils/analytics'; - import routerHistory from '$lib/utils/router-history'; - import RightArrow from '$svg/right-arrow.svg'; - - const { navigate } = routerHistory; - - export let description = ''; - export let yearlyPricing: typeof Jetpack_Boost.pricing.yearly; - - onMount( () => { - // Throw away promise, as we don't need to wait for it. - void recordBoostEvent( 'view_upsell_cta_in_settings_page_in_plugin', {} ); - } ); - - function showBenefits() { - const eventProps = {}; - recordBoostEvent( 'upsell_cta_from_settings_page_in_plugin', eventProps ); - navigate( '/upgrade' ); - } - - $: currencyObjectAfter = getCurrencyObject( - yearlyPricing?.priceAfter / 12, - yearlyPricing?.currencyCode - ); -</script> - -<button class="jb-premium-cta" on:click={showBenefits}> - <div class="jb-premium-cta__content"> - <p>{description}</p> - <p class="jb-premium-cta__action-line"> - {sprintf( - /* translators: %s is the price including the currency symbol in front. */ - __( `Upgrade now only %s`, 'jetpack-boost' ), - currencyObjectAfter.symbol + currencyObjectAfter.integer + currencyObjectAfter.fraction - )} - </p> - </div> - <div class="jb-premium-cta__icon"> - <RightArrow /> - </div> -</button> diff --git a/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx b/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx index b1fe2d2e290ca..48daee2e8cd2c 100644 --- a/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx @@ -1,3 +1,4 @@ +import { ConfigType, useConfig } from '$lib/stores/config-ds'; import { Button, getRedirectUrl, @@ -103,24 +104,28 @@ const isaContext = __( 'jetpack-boost' ); +type BoostPricingTableProps = { + pricing: ConfigType[ 'pricing' ]; + onPremiumCTA: () => void; + onFreeCTA: () => void; + chosenFreePlan: boolean; + chosenPaidPlan: boolean; +}; + export const BoostPricingTable = ( { - pricing, onPremiumCTA, onFreeCTA, chosenFreePlan, chosenPaidPlan, -} ) => { - // If no pricing info is available, set up a fake object to avoid errors. - if ( ! pricing || ! pricing.yearly ) { - pricing = { yearly: {} }; - } +}: BoostPricingTableProps ) => { + const { pricing } = useConfig(); // If the first year discount ends, we want to show the default label. - const legend = pricing.yearly.isIntroductoryOffer + const legend = pricing?.isIntroductoryOffer ? __( '/month for the first year, billed yearly', 'jetpack-boost' ) : undefined; - const isDiscounted = pricing.yearly.priceBefore > pricing.yearly.priceAfter; + const isDiscounted = pricing?.priceBefore && pricing?.priceBefore > pricing?.priceAfter; return ( <PricingTable @@ -171,9 +176,9 @@ export const BoostPricingTable = ( { <PricingTableColumn primary> <PricingTableHeader> <ProductPrice - price={ pricing.yearly.priceBefore / 12 } - offPrice={ isDiscounted ? pricing.yearly.priceAfter / 12 : null } - currency={ pricing.yearly.currencyCode } + price={ ( pricing?.priceBefore ?? 0 ) / 12 } + offPrice={ isDiscounted ? ( pricing?.priceAfter ?? 0 ) / 12 : undefined } + currency={ pricing?.currencyCode } hideDiscountLabel={ false } legend={ legend } /> @@ -210,7 +215,7 @@ export const BoostPricingTable = ( { <ProductPrice price={ 0 } legend="" - currency={ pricing.yearly.currencyCode } + currency={ pricing?.currencyCode } hidePriceFraction /> <Button diff --git a/projects/plugins/boost/app/assets/src/js/features/critical-css/critical-css-meta/critical-css-meta.tsx b/projects/plugins/boost/app/assets/src/js/features/critical-css/critical-css-meta/critical-css-meta.tsx index 6cb7d1baa7edf..7c02d16627e29 100644 --- a/projects/plugins/boost/app/assets/src/js/features/critical-css/critical-css-meta/critical-css-meta.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/critical-css/critical-css-meta/critical-css-meta.tsx @@ -29,9 +29,9 @@ const CriticalCssMeta: React.FC< CriticalCssMetaProps > = ( { } ) => { const [ hasRetried, setHasRetried ] = useState( false ); - const successCount = cssState.providers.filter( - provider => provider.status === 'success' - ).length; + const successCount = cssState.providers + ? cssState.providers.filter( provider => provider.status === 'success' ).length + : 0; function retry() { setHasRetried( true ); diff --git a/projects/plugins/boost/app/assets/src/js/features/critical-css/index.ts b/projects/plugins/boost/app/assets/src/js/features/critical-css/index.ts index 7124f51a5aeec..18ed93cc1a612 100644 --- a/projects/plugins/boost/app/assets/src/js/features/critical-css/index.ts +++ b/projects/plugins/boost/app/assets/src/js/features/critical-css/index.ts @@ -1,6 +1,7 @@ export { RegenerateCriticalCssSuggestion } from './regenerate-critical-css-suggestion/regenerate-critical-css-suggestion'; export { criticalCssState, + criticalCssStateCreated, isGenerating, replaceCssState, updateProvider, diff --git a/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/stores/critical-css-state.ts b/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/stores/critical-css-state.ts index a34334ef00976..38e68431f3cb8 100644 --- a/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/stores/critical-css-state.ts +++ b/projects/plugins/boost/app/assets/src/js/features/critical-css/lib/stores/critical-css-state.ts @@ -33,6 +33,8 @@ export const criticalCssState = { }, }; +export const criticalCssStateCreated = get( criticalCssState ).created ?? 0; + export const replaceCssState = ( value: CriticalCssState ) => { cssStateStore.update( oldValue => { return { ...oldValue, ...value }; diff --git a/projects/plugins/boost/app/assets/src/js/features/critical-css/show-stopper-error/show-stopper-error.tsx b/projects/plugins/boost/app/assets/src/js/features/critical-css/show-stopper-error/show-stopper-error.tsx index 2d348a527b97f..ce3b2a4f68625 100644 --- a/projects/plugins/boost/app/assets/src/js/features/critical-css/show-stopper-error/show-stopper-error.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/critical-css/show-stopper-error/show-stopper-error.tsx @@ -28,6 +28,7 @@ const ShowStopperError: React.FC< ShowStopperErrorTypes > = ( { return ( <ErrorNotice title={ __( 'Failed to generate Critical CSS', 'jetpack-boost' ) } + variant="module" actionButton={ showRetry ? ( <button className="secondary" onClick={ regenerateCriticalCss }> diff --git a/projects/plugins/boost/app/assets/src/js/features/critical-css/status/status.tsx b/projects/plugins/boost/app/assets/src/js/features/critical-css/status/status.tsx index f403b557d0726..5db3a64146608 100644 --- a/projects/plugins/boost/app/assets/src/js/features/critical-css/status/status.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/critical-css/status/status.tsx @@ -6,8 +6,7 @@ import TimeAgo from '../time-ago/time-ago'; import InfoIcon from '$svg/info'; import RefreshIcon from '$svg/refresh'; import { createInterpolateElement } from '@wordpress/element'; -import actionLinkInterpolateVar from '$lib/utils/action-link-interpolate-var'; -import { navigate } from '$lib/utils/navigate'; +import { Link } from 'react-router-dom'; type StatusTypes = { status: CriticalCssState[ 'status' ]; @@ -86,10 +85,7 @@ const Status: React.FC< StatusTypes > = ( { issues.length ), { - ...actionLinkInterpolateVar( - () => navigate( 'critical-css-advanced' ), - 'advanced' - ), + advanced: <Link to="/critical-css-advanced" />, } ) } </> diff --git a/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.module.scss b/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.module.scss index 4135d1c341ee3..5daed4c1729af 100644 --- a/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.module.scss +++ b/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.module.scss @@ -14,11 +14,6 @@ justify-content: left; } - p { - margin: .25em 0; - color: $red_50; - } - :global(.raw-error) { color: $primary-black; } @@ -32,46 +27,58 @@ color: #0f0f0f; border-radius: 6px; } -} - -.icon { - color: inherit; - height: 20px; - width: 20px; - line-height: 0; -} -.offset { - padding-left: 0.5em; -} + .icon { + color: inherit; + height: 20px; + width: 20px; + line-height: 0; + } -.main-action:not( :empty ) { - margin-left: auto; - button { - margin-left: 0; - @include breakpoint(sm) { - margin-left: 20px; + &.variant-module .icon-wrapper { + position: absolute; + left: -65px; + top: 0; + width: 20px; + } + + &:not(.variant-module) .offset { + padding-left: 0.5em; + } + + .main-action:not( :empty ) { + margin-left: auto; + button { + margin-left: 0; + @include breakpoint(sm) { + margin-left: 20px; + } } } -} - -.description { - color: $red_50; - font-weight: bold; - margin-bottom: .5em; -} - -.message { - list-style-type: disc; - color: $red_50; - - button { - color: $primary-black; - font-size: 16px; - margin: 16px auto; + + .description { + color: $red_50; + font-weight: bold; + margin-bottom: .5em; } + + .message { + list-style-type: disc; + color: $red_50; - li { - @include word-wrap(); + p { + margin: .25em 0; + color: $red_50; + } + + button { + color: $primary-black; + font-size: 16px; + margin: 16px auto; + } + + li { + @include word-wrap(); + } } } diff --git a/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.tsx b/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.tsx index b7fa072d55f71..334841a7abad5 100644 --- a/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/error-notice/error-notice.tsx @@ -2,11 +2,12 @@ import { createInterpolateElement } from '@wordpress/element'; import { standardizeError } from '$lib/utils/standardize-error'; import NoticeOutline from '$svg/notice-outline'; import styles from './error-notice.module.scss'; -import React from 'react'; +import classNames from 'classnames'; type ErrorNoticeProps = { title: string; error?: string | Error; + variant?: 'normal' | 'module'; data?: string; suggestion?: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -18,6 +19,7 @@ type ErrorNoticeProps = { const ErrorNotice = ( { title, error = new Error( title ), + variant = 'normal', data, suggestion, vars = {}, @@ -27,8 +29,12 @@ const ErrorNotice = ( { const description = standardizeError( error ).message; return ( - <div className={ styles[ 'error-notice' ] }> - <div> + <div + className={ classNames( styles[ 'error-notice' ], { + [ styles[ 'variant-module' ] ]: variant === 'module', + } ) } + > + <div className={ styles[ 'icon-wrapper' ] }> <NoticeOutline className={ styles.icon } /> </div> diff --git a/projects/plugins/boost/app/assets/src/js/features/error-notice/stories/error-notice.stories.tsx b/projects/plugins/boost/app/assets/src/js/features/error-notice/stories/error-notice.stories.tsx index 8a805e68e2e19..cc17ffbed9f16 100644 --- a/projects/plugins/boost/app/assets/src/js/features/error-notice/stories/error-notice.stories.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/error-notice/stories/error-notice.stories.tsx @@ -9,13 +9,14 @@ const meta: Meta< typeof ErrorNotice > = { argTypes: { title: { control: 'text' }, error: { control: 'text' }, + variant: { control: 'select', options: [ 'normal', 'module' ] }, data: { control: 'text' }, description: { control: 'text' }, suggestion: { control: 'text' }, }, decorators: [ Story => ( - <div style={ { maxWidth: '1320px', margin: '200px auto', fontSize: '16px' } }> + <div style={ { maxWidth: '1320px', padding: '0 100px', margin: '200px auto', fontSize: '16px' } }> <Story /> </div> ), @@ -27,6 +28,7 @@ export const _default = Template.bind( {} ); _default.args = { title: 'Error', error: 'This is an error message', + variant: 'normal', data: "{\n\t\"errorData\": \"This is some more error data\"\n}", description: 'This is error description ErrorNotice is wrapping.', suggestion: 'Contact <support>support</support> for help.', diff --git a/projects/plugins/boost/app/assets/src/js/features/image-cdn/quality-settings/quality-settings.tsx b/projects/plugins/boost/app/assets/src/js/features/image-cdn/quality-settings/quality-settings.tsx index 7bf4da2850964..d53d33f95e39e 100644 --- a/projects/plugins/boost/app/assets/src/js/features/image-cdn/quality-settings/quality-settings.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/image-cdn/quality-settings/quality-settings.tsx @@ -6,10 +6,10 @@ import { __, sprintf } from '@wordpress/i18n'; import styles from './quality-settings.module.scss'; import { IconTooltip } from '@automattic/jetpack-components'; import QualityControl from '../quality-control/quality-control'; -import { DataSyncProvider, useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; import { type QualityConfig, imageCdnSettingsSchema } from '../lib/stores'; import { z } from 'zod'; -import NavigationLink from '$features/ui/navigation-link/navigation-link'; +import { Link } from 'react-router-dom'; type QualitySettingsProps = { isPremium: boolean; @@ -20,7 +20,7 @@ const QualitySettings = ( { isPremium }: QualitySettingsProps ) => { return createInterpolateElement( __( `For more control over image quality, <link>upgrade now!</link>`, 'jetpack-boost' ), { - link: <NavigationLink route="/upgrade" />, + link: <Link to="/upgrade" />, } ); } @@ -106,10 +106,4 @@ const Header = () => ( </div> ); -export default function QualitySettingsWrapper( props: QualitySettingsProps ) { - return ( - <DataSyncProvider> - <QualitySettings { ...props } /> - </DataSyncProvider> - ); -} +export default QualitySettings; diff --git a/projects/plugins/boost/app/assets/src/js/features/image-size-analysis/recommendations-meta/recommendations-meta.tsx b/projects/plugins/boost/app/assets/src/js/features/image-size-analysis/recommendations-meta/recommendations-meta.tsx new file mode 100644 index 0000000000000..113c7478004c2 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/features/image-size-analysis/recommendations-meta/recommendations-meta.tsx @@ -0,0 +1,7 @@ +import { Notice } from '@automattic/jetpack-components'; + +export const RecommendationsMeta = () => ( + <Notice level="info" title="Recommendations Meta" hideCloseButton={ true }> + <p>Implement RecommendationsMeta for ISA here.</p> + </Notice> +); diff --git a/projects/plugins/boost/app/assets/src/js/features/minify-meta/minify-meta.tsx b/projects/plugins/boost/app/assets/src/js/features/minify-meta/minify-meta.tsx index c62a4ea64a828..fbd51f77f0342 100644 --- a/projects/plugins/boost/app/assets/src/js/features/minify-meta/minify-meta.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/minify-meta/minify-meta.tsx @@ -1,7 +1,7 @@ -import { DataSyncProvider } from '@automattic/jetpack-react-data-sync-client'; import { useEffect, useState } from 'react'; import { __, sprintf } from '@wordpress/i18n'; -import { type Props, useMetaQuery, useConfig } from '$lib/stores/minify'; +import { type Props, useMetaQuery } from '$lib/stores/minify'; +import { useConfig } from '$lib/stores/config-ds'; const MetaComponent = ( { inputLabel, buttonText, placeholder, datasyncKey }: Props ) => { const config = useConfig(); @@ -73,10 +73,4 @@ const MetaComponent = ( { inputLabel, buttonText, placeholder, datasyncKey }: Pr ); }; -export default function ( props: Props ) { - return ( - <DataSyncProvider> - <MetaComponent { ...props } /> - </DataSyncProvider> - ); -} +export default MetaComponent; diff --git a/projects/plugins/boost/app/assets/src/js/features/module/lib/stores.ts b/projects/plugins/boost/app/assets/src/js/features/module/lib/stores.ts new file mode 100644 index 0000000000000..9361e9076f1c7 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/features/module/lib/stores.ts @@ -0,0 +1,50 @@ +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { useCallback } from 'react'; +import { z } from 'zod'; + +const modulesStateSchema = z.record( + z.string().min( 1 ), + z.object( { + active: z.boolean(), + available: z.boolean(), + } ) +); + +export const useModulesState = () => { + return useDataSync( 'jetpack_boost_ds', 'modules_state', modulesStateSchema ); +}; + +export type ModulesState = z.infer< typeof modulesStateSchema >; +export const useSingleModuleState = ( + moduleSlug: string, + onSuccess?: ( state: boolean ) => void +) => { + const [ { data }, { mutate } ] = useModulesState(); + + const setModuleState = useCallback( + ( state: boolean ) => { + if ( data?.[ moduleSlug ]?.active === state ) { + return; + } + + mutate( + { + ...data, + [ moduleSlug ]: { + ...data?.[ moduleSlug ], + active: state, + }, + }, + { + onSuccess: moduleStates => { + // Run the passed on callbacks after the mutation has been applied + onSuccess?.( moduleStates[ moduleSlug ].active ); + }, + } + ); + }, + [ data, moduleSlug, mutate, onSuccess ] + ); + + return [ data?.[ moduleSlug ], setModuleState ] as const; +}; diff --git a/projects/plugins/boost/app/assets/src/js/features/module/module.module.scss b/projects/plugins/boost/app/assets/src/js/features/module/module.module.scss new file mode 100644 index 0000000000000..4a54353b96b14 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/features/module/module.module.scss @@ -0,0 +1,32 @@ +.module { + margin-bottom: 2em; + display: flex; + margin-left: auto; + margin-right: auto; + + + a { + text-decoration: underline; + } + + h2 { + font-size: 22px; + margin-top: 0; + } + + p { + margin: 1em 0; + } + + .content h3:focus-visible { + outline: none; + } +} + +.toggle { + // Compensate for header line height + // Manually move the switch to align it better + transform: translateY(8px); + margin-right: 2em; + min-width: 36px; +} diff --git a/projects/plugins/boost/app/assets/src/js/features/module/module.tsx b/projects/plugins/boost/app/assets/src/js/features/module/module.tsx new file mode 100644 index 0000000000000..5d09f9a8f9814 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/features/module/module.tsx @@ -0,0 +1,78 @@ +import { ToggleControl } from '@automattic/jetpack-components'; +import { useEffect } from 'react'; +import { useSingleModuleState } from './lib/stores'; +import styles from './module.module.scss'; + +type ModuleProps = { + title: React.ReactNode; + description: React.ReactNode; + children?: React.ReactNode; + slug: string; + toggle?: boolean; + onEnable?: () => void; + onDisable?: () => void; + onMountEnable?: () => void; +}; + +const Module = ( { + title, + description, + children, + slug, + toggle = true, + onEnable, + onDisable, + onMountEnable, +}: ModuleProps ) => { + const [ status, setStatus ] = useSingleModuleState( slug, active => { + if ( active ) { + onEnable?.(); + } else { + onDisable?.(); + } + } ); + const isModuleActive = status?.active ?? false; + const isModuleAvailable = status?.available ?? false; + + const handleToggle = () => { + setStatus( ! isModuleActive ); + }; + + useEffect( () => { + if ( isModuleActive ) { + onMountEnable?.(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [] ); + + // Don't show unavailable modules, except for lazy_images. + if ( ! isModuleAvailable && slug !== 'lazy_images' ) { + return null; + } + + return ( + <div className={ styles.module }> + <div className={ styles.toggle }> + { toggle && ( + <ToggleControl + className={ `jb-feature-toggle-${ slug }` } + size="small" + checked={ isModuleActive } + disabled={ ! isModuleAvailable } + onChange={ handleToggle } + /> + ) } + </div> + + <div className={ styles.content }> + <h3>{ title }</h3> + + <div className={ styles.description }>{ description }</div> + + { isModuleActive && children } + </div> + </div> + ); +}; + +export default Module; diff --git a/projects/plugins/boost/app/assets/src/js/features/performance-history/performance-history.tsx b/projects/plugins/boost/app/assets/src/js/features/performance-history/performance-history.tsx index 3cdcdaade5481..8c847be588dbb 100644 --- a/projects/plugins/boost/app/assets/src/js/features/performance-history/performance-history.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/performance-history/performance-history.tsx @@ -7,19 +7,19 @@ import GraphComponent from './graph-component/graph-component'; import ErrorNotice from '$features/error-notice/error-notice'; import { __ } from '@wordpress/i18n'; import { Panel, PanelBody, PanelRow } from '@wordpress/components'; -import { navigate } from '$lib/utils/navigate'; import { PerformanceHistoryData } from './lib/types'; - -import styles from './performance-history.module.scss'; import { Button } from '@automattic/jetpack-components'; +import { useNavigate } from 'react-router-dom'; +import { useSingleModuleState } from '$features/module/lib/stores'; +import styles from './performance-history.module.scss'; -type PerformanceHistoryProps = { - needsUpgrade: boolean; -}; +const PerformanceHistoryBody = () => { + const [ performanceHistoryState ] = useSingleModuleState( 'performance_history' ); + const needsUpgrade = ! performanceHistoryState?.available; -const PerformanceHistoryBody = ( { needsUpgrade }: PerformanceHistoryProps ) => { const { data, isFetching, isError, error, refetch } = usePerformanceHistoryQuery(); const [ isFreshStart, dismissFreshStart ] = usePerformanceHistoryFreshStartState(); + const navigate = useNavigate(); if ( isError && ! isFetching ) { return ( @@ -47,7 +47,7 @@ const PerformanceHistoryBody = ( { needsUpgrade }: PerformanceHistoryProps ) => ); }; -const PerformanceHistory = ( { needsUpgrade }: PerformanceHistoryProps ) => { +const PerformanceHistory = () => { const [ isPanelOpen, setPanelOpen ] = usePerformanceHistoryPanelQuery(); return ( @@ -56,14 +56,14 @@ const PerformanceHistory = ( { needsUpgrade }: PerformanceHistoryProps ) => { <PanelBody title={ __( 'Historical Performance', 'jetpack-boost' ) } initialOpen={ isPanelOpen } - onToggle={ value => { + onToggle={ ( value: boolean ) => { setPanelOpen( value ); } } className={ styles[ 'performance-history-body' ] } > <PanelRow> <div style={ { flexGrow: 1, minHeight: '300px' } }> - <PerformanceHistoryBody needsUpgrade={ needsUpgrade } /> + <PerformanceHistoryBody /> </div> </PanelRow> </PanelBody> diff --git a/projects/plugins/boost/app/assets/src/js/features/premium-tooltip/premium-tooltip.tsx b/projects/plugins/boost/app/assets/src/js/features/premium-tooltip/premium-tooltip.tsx index 6606083b370ff..1238cc47c73d7 100644 --- a/projects/plugins/boost/app/assets/src/js/features/premium-tooltip/premium-tooltip.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/premium-tooltip/premium-tooltip.tsx @@ -3,9 +3,11 @@ import { __ } from '@wordpress/i18n'; import { Tooltip } from '$features/ui'; import { recordBoostEvent } from '$lib/utils/analytics'; import styles from './premium-tooltip.module.scss'; -import { navigate } from '$lib/utils/navigate'; +import { useNavigate } from 'react-router-dom'; const PremiumTooltip = () => { + const navigate = useNavigate(); + function showBenefits( event: React.MouseEvent< HTMLAnchorElement > ) { event.preventDefault(); const eventProps = {}; diff --git a/projects/plugins/boost/app/assets/src/js/features/speed-score/pop-out/pop-out.tsx b/projects/plugins/boost/app/assets/src/js/features/speed-score/pop-out/pop-out.tsx index e8aa588728028..460651c3ce356 100644 --- a/projects/plugins/boost/app/assets/src/js/features/speed-score/pop-out/pop-out.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/speed-score/pop-out/pop-out.tsx @@ -3,7 +3,7 @@ import CloseButton from '$features/ui/close-button/close-button'; import styles from './pop-out.module.scss'; import { __ } from '@wordpress/i18n'; import { useState, useEffect, ReactNode } from 'react'; -import { DataSyncProvider, useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; import { z } from 'zod'; import { Button } from '@wordpress/components'; @@ -54,20 +54,6 @@ const slowerMessage = { ctaLink: 'https://jetpack.com/support/speed-up-your-site/', }; -/** - * Wrapper for PopOut which provides a data sync context. Can be removed once we know the - * parent of PopOut is always wrapped in a DataSyncProvider. - * - * @param {Props} props Properties. - */ -export default function PopOut( props: Props ) { - return ( - <DataSyncProvider> - <_PopOut { ...props } /> - </DataSyncProvider> - ); -} - /** * Helper hook - Use data sync to track which score popouts have been dismissed. * @@ -95,7 +81,7 @@ function useDismissedScoreAlerts( id: string | null ): [ boolean, () => void ] { return [ isDismissed, dismiss ]; } -function _PopOut( { scoreChange, onClose }: Props ) { +function PopOut( { scoreChange, onClose }: Props ) { const [ message, setMessage ] = useState< ScoreChangeMessage | null >( null ); const hasScoreChanged = scoreChange !== false && Math.abs( scoreChange ) > 5; @@ -152,3 +138,5 @@ function _PopOut( { scoreChange, onClose }: Props ) { </div> ); } + +export default PopOut; diff --git a/projects/plugins/boost/app/assets/src/js/features/speed-score/speed-score.tsx b/projects/plugins/boost/app/assets/src/js/features/speed-score/speed-score.tsx index 027f00d205b60..9e8fa5e5749c3 100644 --- a/projects/plugins/boost/app/assets/src/js/features/speed-score/speed-score.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/speed-score/speed-score.tsx @@ -11,29 +11,35 @@ import PopOut from './pop-out/pop-out'; import PerformanceHistory from '$features/performance-history/performance-history'; import ErrorNotice from '$features/error-notice/error-notice'; import classNames from 'classnames'; -import React, { useState, useEffect } from 'react'; -import { DataSyncProvider } from '@automattic/jetpack-react-data-sync-client'; +import { useState, useEffect, useMemo } from 'react'; import { useDebouncedRefreshScore, useSpeedScores } from './lib/hooks'; import styles from './speed-score.module.scss'; +import { useModulesState } from '$features/module/lib/stores'; const siteIsOnline = Jetpack_Boost.site.online; type SpeedScoreProps = { - moduleStates: boolean[]; criticalCssCreated: number; criticalCssIsGenerating: boolean; - performanceHistoryNeedsUpgrade: boolean; }; -const SpeedScore = ( { - moduleStates, - criticalCssCreated, - criticalCssIsGenerating, - performanceHistoryNeedsUpgrade, -}: SpeedScoreProps ) => { +const SpeedScore = ( { criticalCssCreated, criticalCssIsGenerating }: SpeedScoreProps ) => { const [ { status, error, scores }, loadScore ] = useSpeedScores(); const scoreLetter = scores ? getScoreLetter( scores.current.mobile, scores.current.desktop ) : ''; const showPrevScores = scores && didScoresChange( scores ) && ! scores.isStale; + const [ { data } ] = useModulesState(); + + // Construct an array of current module states + const moduleStates = useMemo( + () => + Object.entries( data || {} ).reduce( ( acc: boolean[], [ key, value ] ) => { + if ( key !== 'image_guide' && key !== 'image_size_analysis' ) { + acc.push( value.active ); + } + return acc; + }, [] ), + [ data ] + ); const [ closedScorePopOut, setClosePopOut ] = useState( false ); const showScoreChangePopOut = @@ -127,7 +133,7 @@ const SpeedScore = ( { noBoostScoreTooltip={ __( 'Your desktop score without Boost', 'jetpack-boost' ) } /> </div> - { siteIsOnline && <PerformanceHistory needsUpgrade={ performanceHistoryNeedsUpgrade } /> } + { siteIsOnline && <PerformanceHistory /> } </div> <PopOut scoreChange={ showScoreChangePopOut } onClose={ () => setClosePopOut( true ) } /> @@ -135,10 +141,4 @@ const SpeedScore = ( { ); }; -export default function ( props: SpeedScoreProps ) { - return ( - <DataSyncProvider> - <SpeedScore { ...props } /> - </DataSyncProvider> - ); -} +export default SpeedScore; diff --git a/projects/plugins/boost/app/assets/src/js/features/super-cache-info/super-cache-info.tsx b/projects/plugins/boost/app/assets/src/js/features/super-cache-info/super-cache-info.tsx index f3a979870ae33..bc428eb2a5a14 100644 --- a/projects/plugins/boost/app/assets/src/js/features/super-cache-info/super-cache-info.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/super-cache-info/super-cache-info.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { DataSyncProvider, useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; import { __, sprintf } from '@wordpress/i18n'; import { Notice, Button } from '@automattic/jetpack-components'; import { @@ -139,10 +139,4 @@ const SuperCacheInfo = () => { ); }; -export default function () { - return ( - <DataSyncProvider> - <SuperCacheInfo /> - </DataSyncProvider> - ); -} +export default SuperCacheInfo; diff --git a/projects/plugins/boost/app/assets/src/js/features/ui/back-button/back-button.tsx b/projects/plugins/boost/app/assets/src/js/features/ui/back-button/back-button.tsx index 61c9bb3bc9cc1..83cb3472a619c 100644 --- a/projects/plugins/boost/app/assets/src/js/features/ui/back-button/back-button.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/ui/back-button/back-button.tsx @@ -1,12 +1,13 @@ import { __ } from '@wordpress/i18n'; -import { navigate } from '$lib/utils/navigate'; import LeftArrow from '$svg/left-arrow'; +import { useNavigate } from 'react-router-dom'; type BackButtonProps = { route?: string; }; const BackButton: React.FC< BackButtonProps > = ( { route = '/' } ) => { + const navigate = useNavigate(); const handleBack = () => { navigate( route ); }; diff --git a/projects/plugins/boost/app/assets/src/js/features/ui/navigation-link/navigation-link.tsx b/projects/plugins/boost/app/assets/src/js/features/ui/navigation-link/navigation-link.tsx deleted file mode 100644 index 7e32c4123210c..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/ui/navigation-link/navigation-link.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { navigate } from '$lib/utils/navigate'; -import React from 'react'; - -type NavigationLinkProps = { - route: string; -}; - -/** - * A component that renders a link that navigates to internal routes. - * @param {{route: string}} props - */ -const NavigationLink: React.FC< NavigationLinkProps > = ( { route, ...props } ) => { - const handleClick = event => { - event.preventDefault(); - navigate( route ); - }; - - return ( - // eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid - <a href={ `#${ route }` } onClick={ handleClick } { ...props } /> - ); -}; - -export default NavigationLink; diff --git a/projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.module.scss b/projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.module.scss new file mode 100644 index 0000000000000..5d757951ac5a7 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.module.scss @@ -0,0 +1,27 @@ +@import '../../../css/main/variables.scss'; + +.upgrade-cta { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px 24px; + margin: 32px 0; + border: 2px solid $jetpack-green; + border-radius: $border-radius; + background-color: #ffffff; + text-align: left; + cursor: pointer; + + .body p { + margin: 0; + } + + .action-line { + font-weight: bold; + } + + .icon svg { + fill: $jetpack-green; + } +} \ No newline at end of file diff --git a/projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.tsx b/projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.tsx new file mode 100644 index 0000000000000..4b947d3a4743d --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/features/upgrade-cta/upgrade-cta.tsx @@ -0,0 +1,53 @@ +import { getCurrencyObject } from '@automattic/format-currency'; +import { __, sprintf } from '@wordpress/i18n'; +import RightArrow from '$svg/right-arrow'; +import { recordBoostEvent } from '$lib/utils/analytics'; +import { useEffect } from 'react'; +import styles from './upgrade-cta.module.scss'; +import { useConfig } from '$lib/stores/config-ds'; +import { useNavigate } from 'react-router-dom'; + +type UpgradeCTAProps = { + description: string; +}; + +const UpgradeCTA = ( { description }: UpgradeCTAProps ) => { + const navigate = useNavigate(); + + const showBenefits = () => { + recordBoostEvent( 'upsell_cta_from_settings_page_in_plugin', {} ); + navigate( '/upgrade' ); + }; + + useEffect( () => { + recordBoostEvent( 'view_upsell_cta_in_settings_page_in_plugin', {} ); + }, [] ); + + const { pricing } = useConfig(); + const currencyObjectAfter = ! pricing + ? null + : getCurrencyObject( pricing.priceAfter / 12, pricing.currencyCode ); + const priceString = currencyObjectAfter + ? currencyObjectAfter.symbol + currencyObjectAfter.integer + currencyObjectAfter.fraction + : '_'; + + return ( + <button className={ styles[ 'upgrade-cta' ] } onClick={ showBenefits }> + <div className={ styles.body }> + <p>{ description }</p> + <p className={ styles[ 'action-line' ] }> + { sprintf( + /* translators: %s is the price including the currency symbol in front. */ + __( `Upgrade now only %s`, 'jetpack-boost' ), + priceString + ) } + </p> + </div> + <div className={ styles.icon }> + <RightArrow /> + </div> + </button> + ); +}; + +export default UpgradeCTA; diff --git a/projects/plugins/boost/app/assets/src/js/global.d.ts b/projects/plugins/boost/app/assets/src/js/global.d.ts index 6274cc30814d5..0211edabe94c4 100644 --- a/projects/plugins/boost/app/assets/src/js/global.d.ts +++ b/projects/plugins/boost/app/assets/src/js/global.d.ts @@ -2,7 +2,6 @@ * Type definitions for the global namespace. i.e.: things we expect to find in window. */ -import type { ConnectionStatus } from './stores/connection'; import type { Optimizations } from './stores/modules'; import type { BrowserInterfaceIframe, generateCriticalCSS } from 'jetpack-boost-critical-css-gen'; @@ -32,7 +31,6 @@ declare global { prefix: string; }; connectionIframeOriginUrl: string; - connection: ConnectionStatus; fixImageNonce?: string; superCache: { pluginActive: boolean; @@ -56,14 +54,6 @@ declare global { nonces: { [ key: string ]: string; }; - pricing: { - yearly?: { - priceBefore: number; - priceAfter: number; - currencyCode: string; - isIntroductoryOffer: boolean; - }; - }; }; // Critical CSS Generator library. diff --git a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/SettingsPage.svelte b/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/SettingsPage.svelte deleted file mode 100644 index 1c87a736dcde6..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/SettingsPage.svelte +++ /dev/null @@ -1,53 +0,0 @@ -<script lang="ts"> - import SpeedScore from '../../features/speed-score/speed-score'; - import Support from './support/support'; - import Tips from './Tips.svelte'; - import ReactComponent from '$features/ReactComponent.svelte'; - import Footer from '$layout/footer/footer'; - import Header from '$layout/header/header'; - import { criticalCssState, isGenerating } from '$features/critical-css'; - import { modulesState } from '$lib/stores/modules'; - import { hasPrioritySupport } from '$lib/utils/paid-plan'; - - $: criticalCssCreated = $criticalCssState.created; - $: criticalCssIsGenerating = $isGenerating; - $: moduleStates = Object.entries( $modulesState ).reduce( ( acc, [ key, value ] ) => { - if ( key !== 'image_guide' && key !== 'image_size_analysis' ) { - acc.push( value.active ); - } - return acc; - }, [] ); - $: performanceHistoryNeedsUpgrade = ! $modulesState.performance_history.available; -</script> - -<div id="jb-dashboard" class="jb-dashboard jb-dashboard--main"> - <ReactComponent this={Header} /> - - <div class="jb-section jb-section--alt jb-section--scores"> - <ReactComponent - this={SpeedScore} - {moduleStates} - {criticalCssCreated} - {criticalCssIsGenerating} - {performanceHistoryNeedsUpgrade} - /> - </div> - - <div class="jb-section jb-section--main"> - <slot /> - </div> - - <Tips /> - - {#if $hasPrioritySupport} - <ReactComponent this={Support} /> - {/if} - - <ReactComponent this={Footer} /> -</div> - -<style lang="scss"> - .jb-section--main { - z-index: 14; - } -</style> diff --git a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/Tips.svelte b/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/Tips.svelte deleted file mode 100644 index 003c474d02429..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/Tips.svelte +++ /dev/null @@ -1,45 +0,0 @@ -<script lang="ts"> - import { getRedirectUrl } from '@automattic/jetpack-components'; - import { __ } from '@wordpress/i18n'; - import TemplatedString from '$features/TemplatedString.svelte'; - import externalLinkTemplateVar from '$lib/utils/external-link-template-var'; - - const pingdomLink = getRedirectUrl( 'jetpack-boost-pingdom' ); - const whySpeedLink = getRedirectUrl( 'jetpack-boost-why-speed' ); -</script> - -<div class="jb-section jb-section--alt"> - <div class="jb-container--narrow"> - <div class="jb-tips"> - <h3 class="jb-tips__title"> - {__( 'Did you know?', 'jetpack-boost' )} - </h3> - <div class="jb-tips__items"> - <div class="item"> - <div class="item__rate">4x</div> - <div class="item__description"> - <TemplatedString - template={__( - `Pages that take over 3 seconds to load have 4x the bounce rate of pages that load in 2 seconds or less. (source: <link>Pingdom</link>).`, - 'jetpack-boost' - )} - vars={externalLinkTemplateVar( pingdomLink )} - /> - </div> - </div> - <div class="item"> - <div class="item__rate">20%</div> - <div class="item__description"> - <TemplatedString - template={__( - `A one-second delay in loading times can reduce conversion rates by 20%. (source: <link>Google</link>).`, - 'jetpack-boost' - )} - vars={externalLinkTemplateVar( whySpeedLink )} - /> - </div> - </div> - </div> - </div> - </div> -</div> diff --git a/projects/plugins/boost/app/assets/src/js/layout/header/header.tsx b/projects/plugins/boost/app/assets/src/js/layout/header/header.tsx index b2165f7163cb9..f4cd6e7ec28d5 100644 --- a/projects/plugins/boost/app/assets/src/js/layout/header/header.tsx +++ b/projects/plugins/boost/app/assets/src/js/layout/header/header.tsx @@ -2,9 +2,9 @@ import classNames from 'classnames'; import React from 'react'; import styles from './header.module.scss'; import { BackButton } from '$features/ui'; -import { navigate } from '$lib/utils/navigate'; import ChevronRight from '$svg/chevron-right'; import Logo from '$svg/logo'; +import { useNavigate } from 'react-router-dom'; type HeaderProps = { subPageTitle?: string; @@ -12,6 +12,7 @@ type HeaderProps = { }; const Header = ( { subPageTitle = '', children }: HeaderProps ) => { + const navigate = useNavigate(); return ( <div className={ classNames( styles.header ) }> <div className={ classNames( 'jb-container', styles.masthead ) }> diff --git a/projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.module.scss b/projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.module.scss new file mode 100644 index 0000000000000..4e841e3c801c0 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.module.scss @@ -0,0 +1,3 @@ +:global(.jb-section).section { + z-index: 14; +} diff --git a/projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.tsx b/projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.tsx new file mode 100644 index 0000000000000..2fe150fc3dab1 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/layout/settings-page/settings-page.tsx @@ -0,0 +1,57 @@ +import SpeedScore from '$features/speed-score/speed-score'; +import Footer from '$layout/footer/footer'; +import Header from '$layout/header/header'; +import { criticalCssStateCreated, isGenerating } from '$features/critical-css'; +import Support from './support/support'; +import Tips from './tips/tips'; +import { useEffect, useState } from 'react'; +import classNames from 'classnames'; +import styles from './settings-page.module.scss'; +import { usePremiumFeatures } from '../../pages/index/lib/hooks'; + +type SettingsPageProps = { + children: React.ReactNode; +}; + +const SettingsPage = ( { children }: SettingsPageProps ) => { + const [ isGeneratingValue, setIsGeneratingValue ] = useState( false ); + const premiumFeatures = usePremiumFeatures(); + const hasPrioritySupport = premiumFeatures?.includes( 'support' ); + + useEffect( () => { + const unsubscribe = isGenerating.subscribe( value => { + setIsGeneratingValue( value ); + } ); + + return () => { + unsubscribe(); + }; + }, [] ); + + return ( + <div id="jb-dashboard" className="jb-dashboard jb-dashboard--main"> + <Header /> + + <div className="jb-section jb-section--alt jb-section--scores"> + <SpeedScore + criticalCssCreated={ criticalCssStateCreated } + criticalCssIsGenerating={ isGeneratingValue } + /> + </div> + + { children && ( + <div className={ classNames( 'jb-section jb-section--main', styles.section ) }> + { children } + </div> + ) } + + <Tips /> + + { hasPrioritySupport && <Support /> } + + <Footer /> + </div> + ); +}; + +export default SettingsPage; diff --git a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/support/support.module.scss b/projects/plugins/boost/app/assets/src/js/layout/settings-page/support/support.module.scss similarity index 100% rename from projects/plugins/boost/app/assets/src/js/layout/SettingsPage/support/support.module.scss rename to projects/plugins/boost/app/assets/src/js/layout/settings-page/support/support.module.scss diff --git a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/support/support.tsx b/projects/plugins/boost/app/assets/src/js/layout/settings-page/support/support.tsx similarity index 84% rename from projects/plugins/boost/app/assets/src/js/layout/SettingsPage/support/support.tsx rename to projects/plugins/boost/app/assets/src/js/layout/settings-page/support/support.tsx index 52723a9281c36..2b26f93b4b5a4 100644 --- a/projects/plugins/boost/app/assets/src/js/layout/SettingsPage/support/support.tsx +++ b/projects/plugins/boost/app/assets/src/js/layout/settings-page/support/support.tsx @@ -1,8 +1,12 @@ import { __ } from '@wordpress/i18n'; import styles from './support.module.scss'; -import { openPaidSupport } from '$lib/utils/paid-plan'; const Support = () => { + const openPaidSupport = () => { + const supportUrl = 'https://jetpackme.wordpress.com/contact-support/'; + window.open( supportUrl, '_blank' ); + }; + return ( <div className="jb-section"> <div className="jb-container--narrow"> diff --git a/projects/plugins/boost/app/assets/src/css/components/benchmarks.scss b/projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.module.scss similarity index 78% rename from projects/plugins/boost/app/assets/src/css/components/benchmarks.scss rename to projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.module.scss index 14bb65050c494..be10eda352649 100644 --- a/projects/plugins/boost/app/assets/src/css/components/benchmarks.scss +++ b/projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.module.scss @@ -1,15 +1,19 @@ -.jb-dashboard .jb-tips { +@import '../../../../css/main/variables.scss'; +@import '../../../../css/main/mixins.scss'; + +.tips { margin: 0 auto; - &__title { + .tips-title { margin-bottom: $padding; } - &__items { + .tips-items { @include breakpoint(md) { display: grid; grid-template-columns: 1fr 1fr; - grid-gap: 2em; } + grid-gap: 2em; + } } .item { @@ -17,13 +21,12 @@ display: grid; grid-template-columns: 80px 1fr; grid-gap: 1em; - } margin-bottom: 2em; - &__rate { + .item-rate { font-size: 24px; font-weight: 400; line-height: 30px; @@ -36,7 +39,7 @@ } } - &__description { + .item-description { flex-basis: 70%; font-weight: 400; line-height: 24px; diff --git a/projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.tsx b/projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.tsx new file mode 100644 index 0000000000000..a11acbbc54495 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/layout/settings-page/tips/tips.tsx @@ -0,0 +1,53 @@ +import { getRedirectUrl } from '@automattic/jetpack-components'; +import { createInterpolateElement } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import styles from './tips.module.scss'; + +const Tips = () => { + const pingdomLink = getRedirectUrl( 'jetpack-boost-pingdom' ); + const whySpeedLink = getRedirectUrl( 'jetpack-boost-why-speed' ); + + return ( + <div className="jb-section jb-section--alt"> + <div className="jb-container--narrow"> + <div className={ styles.tips }> + <h3 className={ styles[ 'tips-title' ] }>{ __( 'Did you know?', 'jetpack-boost' ) }</h3> + <div className={ styles[ 'tips-items' ] }> + <div className={ styles.item }> + <div className={ styles[ 'item-rate' ] }>4x</div> + <div className={ styles[ 'item-description' ] }> + { createInterpolateElement( + __( + `Pages that take over 3 seconds to load have 4x the bounce rate of pages that load in 2 seconds or less. (source: <link>Pingdom</link>).`, + 'jetpack-boost' + ), + { + // eslint-disable-next-line jsx-a11y/anchor-has-content + link: <a href={ pingdomLink } target="_blank" rel="noopener noreferrer" />, + } + ) } + </div> + </div> + <div className={ styles.item }> + <div className={ styles[ 'item-rate' ] }>20%</div> + <div className={ styles[ 'item-description' ] }> + { createInterpolateElement( + __( + `A one-second delay in loading times can reduce conversion rates by 20%. (source: <link>Google</link>).`, + 'jetpack-boost' + ), + { + // eslint-disable-next-line jsx-a11y/anchor-has-content + link: <a href={ whySpeedLink } target="_blank" rel="noopener noreferrer" />, + } + ) } + </div> + </div> + </div> + </div> + </div> + </div> + ); +}; + +export default Tips; diff --git a/projects/plugins/boost/app/assets/src/js/lib/stores/config-ds.ts b/projects/plugins/boost/app/assets/src/js/lib/stores/config-ds.ts new file mode 100644 index 0000000000000..718d5730009ff --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/lib/stores/config-ds.ts @@ -0,0 +1,32 @@ +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { z } from 'zod'; + +export const configSchema = z.object( { + plugin_dir_url: z.string().url(), + pricing: z + .object( { + priceBefore: z.number(), + priceAfter: z.number(), + currencyCode: z.string(), + isIntroductoryOffer: z.boolean(), + } ) + .nullable(), + site: z.object( { + domain: z.string(), + online: z.boolean(), + } ), + is_premium: z.boolean(), + connection: z.object( { + connected: z.boolean(), + userConnected: z.boolean(), + wpcomBlogId: z.number().nullable(), + } ), +} ); + +export type ConfigType = z.infer< typeof configSchema >; + +export const useConfig = () => { + const [ { data } ] = useDataSync( 'jetpack_boost_ds', 'config', configSchema ); + + return data as z.infer< typeof configSchema >; +}; diff --git a/projects/plugins/boost/app/assets/src/js/lib/stores/connection.ts b/projects/plugins/boost/app/assets/src/js/lib/stores/connection.ts index f1f2beeae8f6a..bae03a4f43c69 100644 --- a/projects/plugins/boost/app/assets/src/js/lib/stores/connection.ts +++ b/projects/plugins/boost/app/assets/src/js/lib/stores/connection.ts @@ -1,15 +1,9 @@ -import { writable } from 'svelte/store'; +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; import api from '../api/api'; -import { reloadModulesState } from './modules'; - -export type ConnectionStatus = { - connected: boolean; - userConnected: boolean; - wpcomBlogId: number; -}; - -const initialState = Jetpack_Boost.connection; -const connectionStatus = writable< ConnectionStatus >( initialState ); +import { configSchema } from './config-ds'; +import { useModulesState } from '$features/module/lib/stores'; +import { useCallback } from 'react'; +import { z } from 'zod'; /** * Get the URL to upgrade boost. @@ -43,24 +37,28 @@ export function getUpgradeURL( domain: string, isUserConnected = false ) { return checkoutProductUrl.toString(); } -export async function initializeConnection(): Promise< void > { - const connection = ( await api.post( '/connection' ) ) as ConnectionStatus; +export const useConnection = () => { + const [ { data, refetch: reloadConfig } ] = useDataSync( + 'jetpack_boost_ds', + 'config', + configSchema + ); + const [ { refetch: reloadModules } ] = useModulesState(); - // As a part of connecting (before marking the connection as ready) - // refresh the modules state to fetch the latest. - // Ideally, we should replace this with a more general server-state update thing. - // 🔻 🔻 🔻 🔻 🔻 🔻 🔻 🔻 🔻 🔻 🔻 - if ( connection.connected ) { - await reloadModulesState(); - } - // 🔺 🔺 🔺 🔺 🔺 🔺 🔺 🔺 🔺 🔺 🔺 - - connectionStatus.update( store => { - return { ...store, ...connection }; - } ); -} + const connection = data?.connection as z.infer< typeof configSchema >[ 'connection' ]; -// Export only the readable store. -export const connection = { - subscribe: connectionStatus.subscribe, + return { + connection, + initializeConnection: useCallback( async () => { + if ( connection?.connected ) { + return; + } + return api.post( '/connection' ).then( results => { + if ( results.connected ) { + reloadConfig(); + reloadModules(); + } + } ); + }, [ connection, reloadConfig, reloadModules ] ), + }; }; diff --git a/projects/plugins/boost/app/assets/src/js/lib/stores/getting-started.ts b/projects/plugins/boost/app/assets/src/js/lib/stores/getting-started.ts new file mode 100644 index 0000000000000..7f28b8cfcb438 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/lib/stores/getting-started.ts @@ -0,0 +1,15 @@ +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { z } from 'zod'; + +export const useGettingStarted = () => { + const [ { data }, { mutateAsync } ] = useDataSync( + 'jetpack_boost_ds', + 'getting_started', + z.boolean() + ); + + return { + shouldGetStarted: data, + markGettingStartedComplete: async () => await mutateAsync( false ), + }; +}; diff --git a/projects/plugins/boost/app/assets/src/js/lib/stores/minify.ts b/projects/plugins/boost/app/assets/src/js/lib/stores/minify.ts index e480a97f34b01..5cf9c2879f36e 100644 --- a/projects/plugins/boost/app/assets/src/js/lib/stores/minify.ts +++ b/projects/plugins/boost/app/assets/src/js/lib/stores/minify.ts @@ -10,7 +10,6 @@ export interface Props { inputLabel: string; buttonText: string; placeholder: string; - value: string[]; } export const useMetaQuery = ( key: MinifyMetaKeys ) => { @@ -22,15 +21,3 @@ export const useMetaQuery = ( key: MinifyMetaKeys ) => { return [ data, updateValues ] as const; }; - -export const useConfig = () => { - const [ { data } ] = useDataSync( - 'jetpack_boost_ds', - 'config', - z.object( { - plugin_dir_url: z.string().url(), - } ) - ); - - return data; -}; diff --git a/projects/plugins/boost/app/assets/src/js/lib/stores/modules.ts b/projects/plugins/boost/app/assets/src/js/lib/stores/modules.ts index ddcc0abd59bfc..3e362ec8cbc86 100644 --- a/projects/plugins/boost/app/assets/src/js/lib/stores/modules.ts +++ b/projects/plugins/boost/app/assets/src/js/lib/stores/modules.ts @@ -66,4 +66,3 @@ export const reloadModulesState = async () => { }; export const modulesState = modulesStateClient.store; -export const modulesStatePending = modulesStateClient.pending; diff --git a/projects/plugins/boost/app/assets/src/js/lib/utils/analytics.ts b/projects/plugins/boost/app/assets/src/js/lib/utils/analytics.ts index 79b6f9cca7217..5d8ec2c948000 100644 --- a/projects/plugins/boost/app/assets/src/js/lib/utils/analytics.ts +++ b/projects/plugins/boost/app/assets/src/js/lib/utils/analytics.ts @@ -61,11 +61,7 @@ function addBoostProps( props: TracksEventProperties ): TracksEventProperties { if ( 'version' in Jetpack_Boost ) { defaultProps.boost_version = Jetpack_Boost.version; } - if ( 'connection' in Jetpack_Boost ) { - defaultProps.jetpack_connection = Jetpack_Boost.connection.connected - ? 'connected' - : 'disconnected'; - } + if ( 'optimizations' in Jetpack_Boost ) { defaultProps.optimizations = JSON.stringify( Jetpack_Boost.optimizations ); } diff --git a/projects/plugins/boost/app/assets/src/js/lib/utils/enable-cloud-css.ts b/projects/plugins/boost/app/assets/src/js/lib/utils/enable-cloud-css.ts deleted file mode 100644 index a58294f055287..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/lib/utils/enable-cloud-css.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { modulesState } from '../stores/modules'; - -export default function enableCloudCss() { - // Enable cloud css module on upgrade. - modulesState.update( oldValue => { - return { ...oldValue, cloud_css: { ...oldValue.cloud_css, active: true } }; - } ); -} diff --git a/projects/plugins/boost/app/assets/src/js/lib/utils/navigate.ts b/projects/plugins/boost/app/assets/src/js/lib/utils/navigate.ts deleted file mode 100644 index 1333137b1bb23..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/lib/utils/navigate.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const navigate = ( to: string ) => { - window.location.hash = to; -}; diff --git a/projects/plugins/boost/app/assets/src/js/lib/utils/paid-plan.ts b/projects/plugins/boost/app/assets/src/js/lib/utils/paid-plan.ts deleted file mode 100644 index 2452ec68b5e80..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/lib/utils/paid-plan.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { derived } from 'svelte/store'; -import config from '../stores/config'; - -export const hasPrioritySupport = derived( config, $config => $config.preferences.prioritySupport ); - -export const openPaidSupport = () => { - const supportUrl = 'https://jetpackme.wordpress.com/contact-support/'; - window.open( supportUrl, '_blank' ); -}; - -export const SupportUrl = getSupportUrl(); - -function getSupportUrl() { - if ( hasPrioritySupport ) { - return 'https://jetpackme.wordpress.com/contact-support/'; - } - return 'https://wordpress.org/support/plugin/jetpack-boost/#new-topic-0'; -} diff --git a/projects/plugins/boost/app/assets/src/js/main.tsx b/projects/plugins/boost/app/assets/src/js/main.tsx new file mode 100644 index 0000000000000..5c09dbb461efd --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/main.tsx @@ -0,0 +1,155 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + createHashRouter, + redirect, + RouterProvider, + useLocation, + useParams, +} from 'react-router-dom'; +import Upgrade from './pages/upgrade/upgrade'; +import Index from './pages/index'; +import AdvancedCriticalCss from './pages/critical-css-advanced/critical-css-advanced'; +import GettingStarted from './pages/getting-started/getting-started'; +import PurchaseSuccess from './pages/purchase-success/purchase-success'; +import SettingsPage from '$layout/settings-page/settings-page'; +import { useEffect } from 'react'; +import { recordBoostEvent } from '$lib/utils/analytics'; +import { DataSyncProvider } from '@automattic/jetpack-react-data-sync-client'; +import { useGettingStarted } from '$lib/stores/getting-started'; +import { useSingleModuleState } from '$features/module/lib/stores'; + +/* + * For the time being, we will pass the props from a svelte file. + * Ones the stores are converted to react, we wont need to do this. + */ +type MainProps = { + criticalCss: any; +}; + +const useBoostRouter = ( { criticalCss }: MainProps ) => { + const { shouldGetStarted } = useGettingStarted(); + const [ isaState ] = useSingleModuleState( 'image_size_analysis' ); + + return createHashRouter( [ + { + path: '*', + loader: () => { + if ( shouldGetStarted ) { + return redirect( '/getting-started' ); + } + return null; + }, + element: ( + <SettingsPage> + <Tracks> + <Index criticalCss={ criticalCss } /> + </Tracks> + </SettingsPage> + ), + }, + { + path: '/critical-css-advanced', + loader: () => { + if ( shouldGetStarted ) { + return redirect( '/getting-started' ); + } + + if ( criticalCss?.issues?.length === 0 ) { + return redirect( '/' ); + } + + return null; + }, + element: ( + <SettingsPage> + <Tracks> + <AdvancedCriticalCss issues={ criticalCss.issues } /> + </Tracks> + </SettingsPage> + ), + }, + { + path: 'image-size-analysis/:group/:page', + loader: () => { + if ( ! isaState?.available ) { + return redirect( '/' ); + } + return null; + }, + element: ( + <Tracks> + <ISAPage /> + </Tracks> + ), + }, + { + path: '/upgrade', + element: ( + <Tracks> + <Upgrade /> + </Tracks> + ), + }, + { + path: '/getting-started', + element: ( + <Tracks> + <GettingStarted /> + </Tracks> + ), + }, + { + path: '/purchase-successful', + element: ( + <Tracks> + <PurchaseSuccess /> + </Tracks> + ), + }, + ] ); +}; + +function Main( props: MainProps ) { + const router = useBoostRouter( { ...props } ); + return <RouterProvider router={ router } />; +} + +/** + * Track the page view. + * + * @param props + * @param props.children - The actual page to render + */ +const Tracks = ( { children }: { children: JSX.Element } ) => { + const location = useLocation(); + + useEffect( () => { + let path = location.pathname.replace( /[-/]/g, '_' ); + if ( path === '_' ) { + path = '_settings'; + } + + recordBoostEvent( `page_view${ path }`, { + path: location.pathname, + } ); + }, [ location ] ); + + return children; +}; + +const ISAPage = () => { + const { group, page } = useParams< { group: string; page: string } >(); + return ( + <h1> + ISA Page for group: { group }, page: { page } + </h1> + ); +}; + +export default ( props: MainProps ) => { + return ( + <DataSyncProvider> + <Main { ...props } /> + </DataSyncProvider> + ); +}; diff --git a/projects/plugins/boost/app/assets/src/js/pages/critical-css-advanced/critical-css-advanced.tsx b/projects/plugins/boost/app/assets/src/js/pages/critical-css-advanced/critical-css-advanced.tsx index 172af7946a0fb..89c09f568eff9 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/critical-css-advanced/critical-css-advanced.tsx +++ b/projects/plugins/boost/app/assets/src/js/pages/critical-css-advanced/critical-css-advanced.tsx @@ -6,7 +6,6 @@ import { } from '$features/critical-css/lib/stores/critical-css-state'; import { groupErrorsByFrequency } from '$features/critical-css/lib/stores/critical-css-state-errors'; import { type Provider } from '$features/critical-css/lib/stores/critical-css-state-types'; -import { navigate } from '$lib/utils/navigate'; import { BackButton, CloseButton } from '$features/ui'; import CriticalCssErrorDescription from '$features/critical-css/error-description/error-description'; import InfoIcon from '$svg/info'; @@ -17,14 +16,6 @@ type PropTypes = { }; const AdvancedCriticalCss: React.FC< PropTypes > = ( { issues } ) => { - /** - * Automatically navigate back to main Settings page if generator isn't done. - */ - if ( issues.length === 0 ) { - navigate( '/' ); - return null; - } - const [ dismissedIssues, setDismissedIssues ] = useState( [] ); const [ activeIssues, setActiveIssues ] = useState( [] ); diff --git a/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx b/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx index eebf5c14e11ac..d6bd64cc7d5dd 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx +++ b/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx @@ -1,36 +1,47 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Snackbar } from '@wordpress/components'; -import { initializeConnection, getUpgradeURL } from '$lib/stores/connection'; +import { getUpgradeURL, useConnection } from '$lib/stores/connection'; import { recordBoostEvent } from '$lib/utils/analytics'; -import { navigate } from '$lib/utils/navigate'; import { BoostPricingTable } from '$features/boost-pricing-table/boost-pricing-table'; import ActivateLicense from '$features/activate-license/activate-license'; import Footer from '$layout/footer/footer'; import Header from '$layout/header/header'; import styles from './getting-started.module.scss'; +import { useConfig } from '$lib/stores/config-ds'; +import { useGettingStarted } from '$lib/stores/getting-started'; +import { useNavigate } from 'react-router-dom'; +import { __ } from '@wordpress/i18n'; -type GettingStartedProps = { - userConnected: boolean; - pricing: ( typeof Jetpack_Boost )[ 'pricing' ]; - isPremium: boolean; - domain: string; -}; - -const GettingStarted: React.FC< GettingStartedProps > = ( { - userConnected, - pricing, - isPremium, - domain, -} ) => { +const GettingStarted: React.FC = () => { const [ selectedPlan, setSelectedPlan ] = useState< 'free' | 'premium' | false >( false ); const [ snackbarMessage, setSnackbarMessage ] = useState< string >( '' ); + const navigate = useNavigate(); + + const { + pricing, + is_premium: isPremium, + site: { domain }, + } = useConfig(); + + const { shouldGetStarted, markGettingStartedComplete } = useGettingStarted(); - async function initialize( - plan: 'free' | 'premium', - isPremiumValue: boolean, - domainValue: string, - userConnectedValue: boolean - ) { + const { + connection: { userConnected }, + initializeConnection, + } = useConnection(); + + useEffect( () => { + if ( ! shouldGetStarted && selectedPlan ) { + // Go to the purchase flow if the user doesn't have a premium plan. + if ( ! isPremium && selectedPlan === 'premium' ) { + window.location.href = getUpgradeURL( domain, userConnected ); + } else { + navigate( '/', { replace: true } ); + } + } + }, [ domain, isPremium, navigate, selectedPlan, shouldGetStarted, userConnected ] ); + + async function initialize( plan: 'free' | 'premium' ) { setSelectedPlan( plan ); try { @@ -43,18 +54,13 @@ const GettingStarted: React.FC< GettingStartedProps > = ( { // * premium_cta_from_getting_started_page_in_plugin await recordBoostEvent( `${ plan }_cta_from_getting_started_page_in_plugin`, {} ); - // Go to the purchase flow if the user doesn't have a premium plan. - if ( ! isPremiumValue && plan === 'premium' ) { - window.location.href = getUpgradeURL( domainValue, userConnectedValue ); - } else { - // Otherwise go to dashboard home. - // @todo - fix when react routing - // navigate( '/', { replace: true } ); - navigate( '/' ); - } + markGettingStartedComplete(); } catch ( e ) { // Display the error in a snackbar message - setSnackbarMessage( e.message || 'Unknown error occurred during the plan selection.' ); + setSnackbarMessage( + ( e as Error ).message || + __( 'Unknown error occurred. Please reload the page and try again.', 'jetpack-boost' ) + ); } } @@ -69,8 +75,8 @@ const GettingStarted: React.FC< GettingStartedProps > = ( { <div className={ styles[ 'pricing-table' ] }> <BoostPricingTable pricing={ pricing } - onPremiumCTA={ () => initialize( 'premium', isPremium, domain, userConnected ) } - onFreeCTA={ () => initialize( 'free', isPremium, domain, userConnected ) } + onPremiumCTA={ () => initialize( 'premium' ) } + onFreeCTA={ () => initialize( 'free' ) } chosenFreePlan={ selectedPlan === 'free' } chosenPaidPlan={ selectedPlan === 'premium' } /> diff --git a/projects/plugins/boost/app/assets/src/js/pages/index/Index.svelte b/projects/plugins/boost/app/assets/src/js/pages/index/Index.svelte deleted file mode 100644 index 8e582b76dee20..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/pages/index/Index.svelte +++ /dev/null @@ -1,371 +0,0 @@ -<script lang="ts" context="module"> - let alreadyResumed = false; -</script> - -<script lang="ts"> - import { getRedirectUrl } from '@automattic/jetpack-components'; - import { onMount } from 'svelte'; - import { __ } from '@wordpress/i18n'; - import RecommendationsMeta from '$features/image-size-analysis/RecommendationsMeta.svelte'; - import { - initializeIsaSummary, - isaSummary, - } from '$features/image-size-analysis/lib/stores/isa-summary'; - import Notice from '$features/Notice.svelte'; - import ReactComponent from '$features/ReactComponent.svelte'; - import TemplatedString from '$features/TemplatedString.svelte'; - import CloudCssMeta from '$features/critical-css/cloud-css-meta/cloud-css-meta'; - import CriticalCssMeta from '$features/critical-css/critical-css-meta/critical-css-meta'; - import MinifyMeta from '$features/minify-meta/minify-meta'; - import Module from '$features/Module.svelte'; - import PremiumTooltip from '$features/premium-tooltip/premium-tooltip'; - import { RegenerateCriticalCssSuggestion } from '$features/critical-css'; - import ResizingUnavailable from '../../features/ResizingUnavailable.svelte'; - import SuperCacheInfo from '$features/super-cache-info/super-cache-info'; - import UpgradeCTA from '$features/UpgradeCTA.svelte'; - import config from '$lib/stores/config'; - import { - criticalCssState, - continueGeneratingLocalCriticalCss, - regenerateCriticalCss, - criticalCssProgress, - isFatalError, - criticalCssIssues, - primaryErrorSet, - } from '$features/critical-css'; - import { suggestRegenerateDS } from '$features/critical-css'; - import { modulesState } from '$lib/stores/modules'; - import { premiumFeatures } from '$lib/stores/premium-features'; - import { - startPollingCloudStatus, - stopPollingCloudCssStatus, - } from '$features/critical-css/lib/cloud-css'; - import externalLinkTemplateVar from '$lib/utils/external-link-template-var'; - import { QualitySettings } from '$features/image-cdn'; - - const criticalCssLink = getRedirectUrl( 'jetpack-boost-critical-css' ); - const deferJsLink = getRedirectUrl( 'jetpack-boost-defer-js' ); - const lazyLoadLink = getRedirectUrl( 'jetpack-boost-lazy-load' ); - const learnLazyLoadDeprecation = () => { - window.open( getRedirectUrl( 'jetpack-boost-lazy-load-deprecation' ), '_blank' ); - }; - - $: lazyLoadDeprecationMessage = $modulesState.lazy_images?.available - ? __( - 'Modern browsers now support lazy loading, and WordPress itself bundles lazy loading for images. This feature will consequently be removed from Jetpack Boost.', - 'jetpack-boost' - ) - : __( - 'Modern browsers now support lazy loading, and WordPress itself bundles lazy loading for images. This feature has been disabled to avoid potential conflicts with Gutenberg 16.6.0+ or WordPress 6.4+. This feature will consequently be removed from Jetpack Boost.', - 'jetpack-boost' - ); - - const suggestRegenerate = suggestRegenerateDS.store; - - $: yearlyPricing = $config.pricing.yearly; - - async function resume() { - if ( alreadyResumed ) { - return; - } - alreadyResumed = true; - - if ( ! $criticalCssState || $criticalCssState.status === 'not_generated' ) { - return regenerateCriticalCss(); - } - await continueGeneratingLocalCriticalCss( $criticalCssState ); - } - - onMount( () => { - if ( $modulesState.image_size_analysis.active ) { - initializeIsaSummary(); - } - } ); -</script> - -<div class="jb-container--narrow"> - <Module - slug="critical_css" - on:enabled={resume} - on:mountEnabled={resume} - on:disabled={() => ( alreadyResumed = false )} - > - <h3 slot="title"> - {__( 'Optimize Critical CSS Loading (manual)', 'jetpack-boost' )} - </h3> - - <div slot="description"> - <p> - <TemplatedString - template={__( - `Move important styling information to the start of the page, which helps pages display your content sooner, so your users don’t have to wait for the entire page to load. Commonly referred to as <link>Critical CSS</link>.`, - 'jetpack-boost' - )} - vars={externalLinkTemplateVar( criticalCssLink )} - /> - </p> - - <p> - <TemplatedString - template={__( - `<b>You should regenerate your Critical CSS</b> whenever you make changes to the HTML or CSS structure of your site.`, - 'jetpack-boost' - )} - vars={{ - b: [ 'strong', {}, '' ], - }} - /> - <ReactComponent inline this={PremiumTooltip} /> - </p> - </div> - - <div slot="meta"> - <ReactComponent - this={CriticalCssMeta} - cssState={$criticalCssState} - isCloudCssAvailable={$modulesState.cloud_css?.available} - criticalCssProgress={$criticalCssProgress} - issues={$criticalCssIssues} - isFatalError={$isFatalError} - primaryErrorSet={$primaryErrorSet} - suggestRegenerate={$suggestRegenerate} - {regenerateCriticalCss} - /> - </div> - - <div slot="notice"> - <ReactComponent - this={RegenerateCriticalCssSuggestion} - show={$suggestRegenerate && $criticalCssState.status !== 'pending'} - type={$suggestRegenerate} - /> - </div> - - <svelte:fragment slot="cta"> - <UpgradeCTA - description={__( - 'Save time by upgrading to Automatic Critical CSS generation.', - 'jetpack-boost' - )} - {yearlyPricing} - /> - </svelte:fragment> - </Module> - - <Module - slug="cloud_css" - on:enabled={startPollingCloudStatus} - on:disabled={stopPollingCloudCssStatus} - on:mountEnabled={startPollingCloudStatus} - > - <h3 slot="title"> - {__( 'Automatically Optimize CSS Loading', 'jetpack-boost' )} - <span class="jb-badge">Upgraded</span> - </h3> - <div slot="description"> - <p> - <TemplatedString - template={__( - `Move important styling information to the start of the page, which helps pages display your content sooner, so your users don’t have to wait for the entire page to load. Commonly referred to as <link>Critical CSS</link>.`, - 'jetpack-boost' - )} - vars={externalLinkTemplateVar( criticalCssLink )} - /> - </p> - - <p> - <TemplatedString - template={__( - `<b>Boost will automatically generate your Critical CSS</b> whenever you make changes to the HTML or CSS structure of your site.`, - 'jetpack-boost' - )} - vars={{ - b: [ 'strong', {}, '' ], - }} - /> - </p> - </div> - - <div slot="meta" class="jb-feature-toggle__meta"> - <ReactComponent - this={CloudCssMeta} - cssState={$criticalCssState} - isCloudCssAvailable={$modulesState.cloud_css?.available} - criticalCssProgress={$criticalCssProgress} - issues={$criticalCssIssues} - isFatalError={$isFatalError} - primaryErrorSet={$primaryErrorSet} - suggestRegenerate={$suggestRegenerate} - {regenerateCriticalCss} - /> - </div> - </Module> - - <Module slug="render_blocking_js"> - <h3 slot="title"> - {__( 'Defer Non-Essential JavaScript', 'jetpack-boost' )} - </h3> - <p slot="description"> - <TemplatedString - template={__( - `Run non-essential JavaScript after the page has loaded so that styles and images can load more quickly. Read more on <link>web.dev</link>.`, - 'jetpack-boost' - )} - vars={externalLinkTemplateVar( deferJsLink )} - /> - </p> - </Module> - - <Module slug="lazy_images"> - <h3 slot="title">{__( 'Lazy Image Loading', 'jetpack-boost' )}</h3> - <p slot="description"> - <TemplatedString - template={__( - `Improve page loading speed by only loading images when they are required. Read more on <link>web.dev</link>.`, - 'jetpack-boost' - )} - vars={externalLinkTemplateVar( lazyLoadLink )} - /> - </p> - <Notice - title={__( 'Lazy image loading is going away', 'jetpack-boost' )} - message={lazyLoadDeprecationMessage} - actions={[ - { - label: __( 'Learn more', 'jetpack-boost' ), - onClick: learnLazyLoadDeprecation, - isExternalLink: true, - variant: 'link', - }, - ]} - /> - </Module> - - <Module slug="minify_js"> - <h3 slot="title">{__( 'Concatenate JS', 'jetpack-boost' )}</h3> - <p slot="description"> - {__( - 'Scripts are grouped by their original placement, concatenated and minified to reduce site loading time and reduce the number of requests.', - 'jetpack-boost' - )} - </p> - <div slot="meta"> - <ReactComponent - this={MinifyMeta} - datasyncKey="minify_js_excludes" - inputLabel={__( 'Exclude JS Strings:', 'jetpack-boost' )} - buttonText={__( 'Exclude JS Strings', 'jetpack-boost' )} - placeholder={__( 'Comma separated list of JS scripts to exclude', 'jetpack-boost' )} - /> - </div> - </Module> - - <Module slug="minify_css"> - <h3 slot="title">{__( 'Concatenate CSS', 'jetpack-boost' )}</h3> - <p slot="description"> - {__( - 'Styles are grouped by their original placement, concatenated and minified to reduce site loading time and reduce the number of requests.', - 'jetpack-boost' - )} - </p> - - <div slot="meta"> - <ReactComponent - this={MinifyMeta} - datasyncKey="minify_css_excludes" - inputLabel={__( 'Exclude CSS Strings:', 'jetpack-boost' )} - buttonText={__( 'Exclude CSS Strings', 'jetpack-boost' )} - placeholder={__( 'Comma separated list of CSS stylesheets to exclude', 'jetpack-boost' )} - /> - </div> - </Module> - - <Module slug="image_cdn"> - <h3 slot="title">{__( 'Image CDN', 'jetpack-boost' )}</h3> - <p slot="description"> - {__( - `Deliver images from Jetpack's Content Delivery Network. Automatically resizes your images to an appropriate size, converts them to modern efficient formats like WebP, and serves them from a worldwide network of servers.`, - 'jetpack-boost' - )} - </p> - - <div slot="meta"> - <ReactComponent - this={QualitySettings} - isPremium={$premiumFeatures.includes( 'image-cdn-quality' )} - /> - </div> - </Module> - - <div class="settings"> - <Module slug="image_guide"> - <h3 slot="title">{__( 'Image Guide', 'jetpack-boost' )}<span class="beta">Beta</span></h3> - <p slot="description"> - {__( - `This feature helps you discover images that are too large. When you browse your site, the image guide will show you an overlay with information about each image's size.`, - 'jetpack-boost' - )} - </p> - <!-- svelte-ignore missing-declaration --> - {#if false === Jetpack_Boost.site.canResizeImages} - <ResizingUnavailable /> - {/if} - - <svelte:fragment slot="cta"> - {#if ! $modulesState.image_size_analysis.available} - <UpgradeCTA - description={__( - 'Upgrade to scan your site for issues - automatically!', - 'jetpack-boost' - )} - {yearlyPricing} - /> - {/if} - </svelte:fragment> - </Module> - - <Module slug="image_size_analysis" toggle={false}> - <h3 slot="title"> - {__( 'Image Size Analysis', 'jetpack-boost' )}<span class="beta">Beta</span> - </h3> - <p slot="description"> - {__( - `This tool will search your site for images that are too large and have an impact on your visitors' experience, page loading times, and search rankings. Once finished, it will give you a report of all improperly sized images with suggestions on how to fix them.`, - 'jetpack-boost' - )} - </p> - - <svelte:fragment slot="meta"> - {#if $modulesState.image_size_analysis.active} - <RecommendationsMeta - isaSummary={$isaSummary} - isCdnActive={$modulesState.image_cdn.active} - /> - {/if} - </svelte:fragment> - </Module> - </div> - - <ReactComponent this={SuperCacheInfo} /> -</div> - -<style lang="scss"> - .settings { - border-top: 1px solid hsl( 0, 0%, 90% ); - padding-top: 20px; - } - .beta { - background: var( --jp-green-5 ); - color: var( --jp-green-60 ); - padding: 2px 5px; - border-radius: 3px; - font-size: 0.8rem; - margin-left: 10px; - transform: translateY( -4.5px ); - display: inline-block; - } - - [slot='notice'] { - margin-top: 1rem; - } -</style> diff --git a/projects/plugins/boost/app/assets/src/js/pages/index/index.module.scss b/projects/plugins/boost/app/assets/src/js/pages/index/index.module.scss new file mode 100644 index 0000000000000..02e6a4522d186 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/pages/index/index.module.scss @@ -0,0 +1,14 @@ +.settings { + border-top: 1px solid hsl( 0, 0%, 90% ); + padding-top: 20px; +} +.beta { + background: var( --jp-green-5 ); + color: var( --jp-green-60 ); + padding: 2px 5px; + border-radius: 3px; + font-size: 0.8rem; + margin-left: 10px; + transform: translateY( -4.5px ); + display: inline-block; +} diff --git a/projects/plugins/boost/app/assets/src/js/pages/index/index.tsx b/projects/plugins/boost/app/assets/src/js/pages/index/index.tsx new file mode 100644 index 0000000000000..c889c5245d38f --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/pages/index/index.tsx @@ -0,0 +1,393 @@ +import CriticalCssMeta from '$features/critical-css/critical-css-meta/critical-css-meta'; +import { CriticalCssState } from '$features/critical-css/lib/stores/critical-css-state-types'; +import { useSingleModuleState } from '$features/module/lib/stores'; +import Module from '$features/module/module'; +import UpgradeCTA from '$features/upgrade-cta/upgrade-cta'; +import { Button, Notice, getRedirectUrl } from '@automattic/jetpack-components'; +import { createInterpolateElement } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { usePremiumFeatures, useSuggestRegenerate } from './lib/hooks'; +import { + RegenerateCriticalCssSuggestion, + continueGeneratingLocalCriticalCss, + regenerateCriticalCss, +} from '$features/critical-css'; +import { useCallback, useEffect, useState } from 'react'; +import { + startPollingCloudStatus, + stopPollingCloudCssStatus, +} from '$features/critical-css/lib/cloud-css'; +import CloudCssMeta from '$features/critical-css/cloud-css-meta/cloud-css-meta'; +import MinifyMeta from '$features/minify-meta/minify-meta'; +import { QualitySettings } from '$features/image-cdn'; +import styles from './index.module.scss'; +import { RecommendationsMeta } from '$features/image-size-analysis/recommendations-meta/recommendations-meta'; +import { initializeIsaSummary } from '$features/image-size-analysis/lib/stores/isa-summary'; +import SuperCacheInfo from '$features/super-cache-info/super-cache-info'; + +type IndexProps = { + /* + * TODO: Move these to react DS and get them directly from DS instead of as props. + * This should be done when moving the Main.svelte component to React. + */ + criticalCss: { + criticalCssState: CriticalCssState; + continueGeneratingLocalCriticalCss: unknown; + regenerateCriticalCss: unknown; + criticalCssProgress: number; + isFatalError: boolean; + issues: CriticalCssState[ 'providers' ]; + primaryErrorSet: unknown; + }; +}; + +const Index = ( { criticalCss }: IndexProps ) => { + const [ alreadyResumed, setAlreadyResumed ] = useState( false ); + const resume = useCallback( () => { + if ( alreadyResumed ) { + return; + } + setAlreadyResumed( true ); + + if ( + ! criticalCss.criticalCssState || + criticalCss.criticalCssState.status === 'not_generated' + ) { + return regenerateCriticalCss(); + } + continueGeneratingLocalCriticalCss( criticalCss.criticalCssState ); + }, [ alreadyResumed, criticalCss.criticalCssState ] ); + + const criticalCssLink = getRedirectUrl( 'jetpack-boost-critical-css' ); + const deferJsLink = getRedirectUrl( 'jetpack-boost-defer-js' ); + const lazyLoadLink = getRedirectUrl( 'jetpack-boost-lazy-load' ); + const learnLazyLoadDeprecation = () => { + window.open( getRedirectUrl( 'jetpack-boost-lazy-load-deprecation' ), '_blank' ); + }; + + const [ lazyLoadState ] = useSingleModuleState( 'lazy_images' ); + const [ cloudCssState ] = useSingleModuleState( 'cloud_css' ); + const [ isaState ] = useSingleModuleState( 'image_size_analysis' ); + + const lazyLoadDeprecationMessage = lazyLoadState?.available + ? __( + 'Modern browsers now support lazy loading, and WordPress itself bundles lazy loading for images. This feature will consequently be removed from Jetpack Boost.', + 'jetpack-boost' + ) + : __( + 'Modern browsers now support lazy loading, and WordPress itself bundles lazy loading for images. This feature has been disabled to avoid potential conflicts with Gutenberg 16.6.0+ or WordPress 6.4+. This feature will consequently be removed from Jetpack Boost.', + 'jetpack-boost' + ); + + const [ { data: suggestRegenerate } ] = useSuggestRegenerate(); + const premiumFeatures = usePremiumFeatures(); + + useEffect( () => { + if ( isaState?.active ) { + initializeIsaSummary(); + } + }, [ isaState?.active ] ); + + return ( + <div className="jb-container--narrow"> + <Module + slug="critical_css" + title={ __( 'Optimize Critical CSS Loading (manual)', 'jetpack-boost' ) } + onDisable={ () => setAlreadyResumed( false ) } + onEnable={ resume } + onMountEnable={ resume } + description={ + <> + <p> + { createInterpolateElement( + __( + `Move important styling information to the start of the page, which helps pages display your content sooner, so your users don’t have to wait for the entire page to load. Commonly referred to as <link>Critical CSS</link>.`, + 'jetpack-boost' + ), + { + // eslint-disable-next-line jsx-a11y/anchor-has-content + link: <a href={ criticalCssLink } target="_blank" rel="noopener noreferrer" />, + } + ) } + </p> + <p> + { createInterpolateElement( + __( + `<b>You should regenerate your Critical CSS</b> whenever you make changes to the HTML or CSS structure of your site.`, + 'jetpack-boost' + ), + { + b: <b />, + } + ) } + </p> + </> + } + > + <CriticalCssMeta + cssState={ criticalCss.criticalCssState } + isCloudCssAvailable={ cloudCssState?.available === true } + criticalCssProgress={ criticalCss.criticalCssProgress } + issues={ criticalCss.issues } + isFatalError={ criticalCss.isFatalError } + primaryErrorSet={ criticalCss.primaryErrorSet } + suggestRegenerate={ suggestRegenerate } + regenerateCriticalCss={ criticalCss.regenerateCriticalCss } + /> + <RegenerateCriticalCssSuggestion + show={ suggestRegenerate && criticalCss.criticalCssState.status !== 'pending' } + type={ suggestRegenerate } + /> + <UpgradeCTA + description={ __( + 'Save time by upgrading to Automatic Critical CSS generation.', + 'jetpack-boost' + ) } + /> + </Module> + <Module + slug="cloud_css" + title={ + <> + { __( 'Automatically Optimize CSS Loading', 'jetpack-boost' ) } + <span className="jb-badge">Upgraded</span> + </> + } + description={ + <> + <p> + { createInterpolateElement( + __( + `Move important styling information to the start of the page, which helps pages display your content sooner, so your users don’t have to wait for the entire page to load. Commonly referred to as <link>Critical CSS</link>.`, + 'jetpack-boost' + ), + { + // eslint-disable-next-line jsx-a11y/anchor-has-content + link: <a href={ criticalCssLink } target="_blank" rel="noopener noreferrer" />, + } + ) } + </p> + <p> + { createInterpolateElement( + __( + `<b>Boost will automatically generate your Critical CSS</b> whenever you make changes to the HTML or CSS structure of your site.`, + 'jetpack-boost' + ), + { + b: <strong />, + } + ) } + </p> + </> + } + onEnable={ startPollingCloudStatus } + onDisable={ stopPollingCloudCssStatus } + onMountEnable={ startPollingCloudStatus } + > + <CloudCssMeta + cssState={ criticalCss.criticalCssState } + isCloudCssAvailable={ cloudCssState?.available === true } + criticalCssProgress={ criticalCss.criticalCssProgress } + issues={ criticalCss.issues } + isFatalError={ criticalCss.isFatalError } + primaryErrorSet={ criticalCss.primaryErrorSet } + suggestRegenerate={ suggestRegenerate } + regenerateCriticalCss={ regenerateCriticalCss } + /> + </Module> + <Module + slug="render_blocking_js" + title={ __( 'Defer Non-Essential JavaScript', 'jetpack-boost' ) } + description={ + <p> + { createInterpolateElement( + __( + `Run non-essential JavaScript after the page has loaded so that styles and images can load more quickly. Read more on <link>web.dev</link>.`, + 'jetpack-boost' + ), + { + // eslint-disable-next-line jsx-a11y/anchor-has-content + link: <a href={ deferJsLink } target="_blank" rel="noopener noreferrer" />, + } + ) } + </p> + } + ></Module> + <Module + slug="lazy_images" + title={ __( 'Lazy Image Loading', 'jetpack-boost' ) } + description={ + <> + <p> + { createInterpolateElement( + __( + `Improve page loading speed by only loading images when they are required. Read more on <link>web.dev</link>.`, + 'jetpack-boost' + ), + { + // eslint-disable-next-line jsx-a11y/anchor-has-content + link: <a href={ lazyLoadLink } target="_blank" rel="noopener noreferrer" />, + } + ) } + </p> + <Notice + level="info" + title={ __( 'Lazy image loading is going away', 'jetpack-boost' ) } + hideCloseButton={ true } + actions={ [ + <Button + key="learn-more" + isPrimary={ true } + onClick={ learnLazyLoadDeprecation } + isExternalLink={ true } + variant="link" + > + { __( 'Learn more', 'jetpack-boost' ) } + </Button>, + ] } + > + { lazyLoadDeprecationMessage } + </Notice> + </> + } + ></Module> + <Module + slug="minify_js" + title={ __( 'Concatenate JS', 'jetpack-boost' ) } + description={ + <p> + { __( + 'Scripts are grouped by their original placement, concatenated and minified to reduce site loading time and reduce the number of requests.', + 'jetpack-boost' + ) } + </p> + } + > + <MinifyMeta + datasyncKey="minify_js_excludes" + inputLabel={ __( 'Exclude JS Strings:', 'jetpack-boost' ) } + buttonText={ __( 'Exclude JS Strings', 'jetpack-boost' ) } + placeholder={ __( 'Comma separated list of JS scripts to exclude', 'jetpack-boost' ) } + /> + </Module> + <Module + slug="minify_css" + title={ __( 'Concatenate CSS', 'jetpack-boost' ) } + description={ + <p> + { __( + 'Styles are grouped by their original placement, concatenated and minified to reduce site loading time and reduce the number of requests.', + 'jetpack-boost' + ) } + </p> + } + > + <MinifyMeta + datasyncKey="minify_css_excludes" + inputLabel={ __( 'Exclude CSS Strings:', 'jetpack-boost' ) } + buttonText={ __( 'Exclude CSS Strings', 'jetpack-boost' ) } + placeholder={ __( + 'Comma separated list of CSS stylesheets to exclude', + 'jetpack-boost' + ) } + /> + </Module> + <Module + slug="image_cdn" + title={ __( 'Image CDN', 'jetpack-boost' ) } + description={ + <p> + { __( + `Deliver images from Jetpack's Content Delivery Network. Automatically resizes your images to an appropriate size, converts them to modern efficient formats like WebP, and serves them from a worldwide network of servers.`, + 'jetpack-boost' + ) } + </p> + } + > + <QualitySettings isPremium={ premiumFeatures?.includes( 'image-cdn-quality' ) ?? false } /> + </Module> + + <div className={ styles.settings }> + <Module + slug="image_guide" + title={ + <> + { __( 'Image Guide', 'jetpack-boost' ) } + <span className={ styles.beta }>Beta</span> + </> + } + description={ + <> + <p> + { __( + `This feature helps you discover images that are too large. When you browse your site, the image guide will show you an overlay with information about each image's size.`, + 'jetpack-boost' + ) } + </p> + { ! isaState?.available && ( + <UpgradeCTA + description={ __( + 'Upgrade to scan your site for issues - automatically!', + 'jetpack-boost' + ) } + /> + ) } + </> + } + > + { false === Jetpack_Boost.site.canResizeImages && ( + <Notice + level="warning" + title={ __( 'Image resizing is unavailable', 'jetpack-boost' ) } + hideCloseButton={ true } + > + <p> + { __( + "It looks like your server doesn't have Imagick or GD extensions installed.", + 'jetpack-boost' + ) } + </p> + <p> + { __( + "Jetpack Boost is able to work without these extensions, but it's likely that it's going to be difficult for you to optimize the images that the Image Guide will identify without one of these extensions.", + 'jetpack-boost' + ) } + </p> + <p> + { __( + 'Please contact your hosting provider or system administrator and ask them to install or activate one of these extensions.', + 'jetpack-boost' + ) } + </p> + </Notice> + ) } + </Module> + + <Module + slug="image_size_analysis" + toggle={ false } + title={ + <> + { __( 'Image Size Analysis', 'jetpack-boost' ) } + <span className={ styles.beta }>Beta</span> + </> + } + description={ + <p> + { __( + `This tool will search your site for images that are too large and have an impact on your visitors' experience, page loading times, and search rankings. Once finished, it will give you a report of all improperly sized images with suggestions on how to fix them.`, + 'jetpack-boost' + ) } + </p> + } + > + { isaState?.active && <RecommendationsMeta /> } + </Module> + </div> + + <SuperCacheInfo /> + </div> + ); +}; + +export default Index; diff --git a/projects/plugins/boost/app/assets/src/js/pages/index/lib/hooks.ts b/projects/plugins/boost/app/assets/src/js/pages/index/lib/hooks.ts new file mode 100644 index 0000000000000..0ff9dc6399af1 --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/pages/index/lib/hooks.ts @@ -0,0 +1,29 @@ +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { z } from 'zod'; + +const allowedSuggestions = [ + '1', + 'page_saved', + 'post_saved', + 'switched_theme', + 'plugin_change', +] as const; + +export type RegenerationReason = ( typeof allowedSuggestions )[ number ]; + +export const useSuggestRegenerate = () => + useDataSync( + 'jetpack_boost_ds', + 'critical_css_suggest_regenerate', + z.enum( allowedSuggestions ).nullable() + ); + +export const usePremiumFeatures = () => { + const [ { data: premiumFeatures } ] = useDataSync( + 'jetpack_boost_ds', + 'premium_features', + z.array( z.string() ) + ); + + return premiumFeatures; +}; diff --git a/projects/plugins/boost/app/assets/src/js/pages/purchase-success/purchase-success.tsx b/projects/plugins/boost/app/assets/src/js/pages/purchase-success/purchase-success.tsx index 527af99901193..89fdb50f2cf69 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/purchase-success/purchase-success.tsx +++ b/projects/plugins/boost/app/assets/src/js/pages/purchase-success/purchase-success.tsx @@ -3,23 +3,28 @@ import { Button } from '@wordpress/components'; import { createInterpolateElement, useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { requestImageAnalysis } from '$features/image-size-analysis/lib/stores/isa-summary'; -import enableCloudCss from '$lib/utils/enable-cloud-css'; -import { navigate } from '$lib/utils/navigate'; import Logo from '$svg/jetpack-green'; +import { useSingleModuleState } from '$features/module/lib/stores'; +import { useNavigate } from 'react-router-dom'; -type PurchaseSuccessProps = { - isImageGuideActive: boolean; -}; +const PurchaseSuccess: React.FC = () => { + const [ , setCloudCssState ] = useSingleModuleState( 'cloud_css' ); + const [ imageGuideState ] = useSingleModuleState( 'image_guide' ); + const [ isaState ] = useSingleModuleState( 'image_size_analysis' ); + const navigate = useNavigate(); -const PurchaseSuccess: React.FC< PurchaseSuccessProps > = ( { isImageGuideActive } ) => { useEffect( () => { - enableCloudCss(); + setCloudCssState( true ); // If image guide is enabled, request a new ISA report. - if ( isImageGuideActive && false !== Jetpack_Boost.site.canResizeImages ) { + if ( + imageGuideState?.active && + isaState?.active && + false !== Jetpack_Boost.site.canResizeImages + ) { requestImageAnalysis(); } - }, [ isImageGuideActive ] ); + }, [ imageGuideState?.active, isaState?.active, setCloudCssState ] ); const wpcomPricingUrl = getRedirectUrl( 'wpcom-pricing' ); diff --git a/projects/plugins/boost/app/assets/src/js/pages/upgrade/upgrade.tsx b/projects/plugins/boost/app/assets/src/js/pages/upgrade/upgrade.tsx index d80a9723e737c..c00e5fe15baeb 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/upgrade/upgrade.tsx +++ b/projects/plugins/boost/app/assets/src/js/pages/upgrade/upgrade.tsx @@ -2,29 +2,31 @@ import { PricingCard } from '@automattic/jetpack-components'; import classNames from 'classnames'; import { __ } from '@wordpress/i18n'; import ActivateLicense from '$features/activate-license/activate-license'; -import { getUpgradeURL } from '$lib/stores/connection'; +import { getUpgradeURL, useConnection } from '$lib/stores/connection'; import { recordBoostEventAndRedirect } from '$lib/utils/analytics'; import BackButton from '$features/ui/back-button/back-button'; import Footer from '$layout/footer/footer'; import Header from '$layout/header/header'; import JetpackLogo from '$svg/jetpack-green'; import styles from './upgrade.module.scss'; +import { useConfig } from '$lib/stores/config-ds'; -type UpgradeProps = { - pricing: ( typeof Jetpack_Boost )[ 'pricing' ]; - siteDomain: string; - userConnected: boolean; -}; +const Upgrade: React.FC = () => { + const { + pricing, + site: { domain: siteDomain }, + } = useConfig(); + + const { connection } = useConnection(); -const Upgrade: React.FC< UpgradeProps > = ( { pricing, siteDomain, userConnected } ) => { const goToCheckout = () => { recordBoostEventAndRedirect( - getUpgradeURL( siteDomain, userConnected ), + getUpgradeURL( siteDomain, connection.userConnected ), 'checkout_from_pricing_page_in_plugin' ); }; - if ( ! ( 'yearly' in pricing ) ) { + if ( ! pricing ) { goToCheckout(); } @@ -79,14 +81,14 @@ const Upgrade: React.FC< UpgradeProps > = ( { pricing, siteDomain, userConnected </div> <div className="jb-card__cta px-2 my-4"> - { 'yearly' in pricing && ( + { pricing && ( <PricingCard title={ __( 'Jetpack Boost', 'jetpack-boost' ) } icon={ `${ Jetpack_Boost.site.staticAssetPath }images/forward.svg` } - priceBefore={ pricing.yearly.priceBefore / 12 } - priceAfter={ pricing.yearly.priceAfter / 12 } + priceBefore={ pricing.priceBefore / 12 } + priceAfter={ pricing.priceAfter / 12 } priceDetails={ __( '/month, paid yearly', 'jetpack-boost' ) } - currencyCode={ pricing.yearly.currencyCode } + currencyCode={ pricing.currencyCode } ctaText={ __( 'Upgrade Jetpack Boost', 'jetpack-boost' ) } onCtaClick={ goToCheckout } /> diff --git a/projects/plugins/boost/app/assets/src/js/svg/right-arrow.svg b/projects/plugins/boost/app/assets/src/js/svg/right-arrow.svg deleted file mode 100644 index d2d6394ec093d..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/svg/right-arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ -<svg width="19" height="17" viewBox="0 0 19 17" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M10.6953 16.3906L18.4062 8.60938L10.6953 0.828125L8.63281 2.98438L12.8516 7.10938H0.699219V10.1094H12.8516L8.63281 14.2344L10.6953 16.3906Z" /> -</svg> diff --git a/projects/plugins/boost/app/assets/src/js/svg/right-arrow.tsx b/projects/plugins/boost/app/assets/src/js/svg/right-arrow.tsx new file mode 100644 index 0000000000000..f894b8814cccf --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/svg/right-arrow.tsx @@ -0,0 +1,7 @@ +const RightArrow = () => ( + <svg width="19" height="17" viewBox="0 0 19 17" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M10.6953 16.3906L18.4062 8.60938L10.6953 0.828125L8.63281 2.98438L12.8516 7.10938H0.699219V10.1094H12.8516L8.63281 14.2344L10.6953 16.3906Z" /> + </svg> +); + +export default RightArrow; diff --git a/projects/plugins/boost/app/class-jetpack-boost.php b/projects/plugins/boost/app/class-jetpack-boost.php index 4cf0884927d96..d525fe24c77d8 100644 --- a/projects/plugins/boost/app/class-jetpack-boost.php +++ b/projects/plugins/boost/app/class-jetpack-boost.php @@ -17,8 +17,8 @@ use Automattic\Jetpack\My_Jetpack\Initializer as My_Jetpack_Initializer; use Automattic\Jetpack\Plugin_Deactivation\Deactivation_Handler; use Automattic\Jetpack_Boost\Admin\Admin; -use Automattic\Jetpack_Boost\Admin\Config; use Automattic\Jetpack_Boost\Admin\Regenerate_Admin_Notice; +use Automattic\Jetpack_Boost\Data_Sync\Getting_Started_Entry; use Automattic\Jetpack_Boost\Features\Setup_Prompt\Setup_Prompt; use Automattic\Jetpack_Boost\Lib\Analytics; use Automattic\Jetpack_Boost\Lib\CLI; @@ -85,6 +85,7 @@ public function __construct() { $this->plugin_name = 'jetpack-boost'; $this->connection = new Connection(); + $this->connection->init(); // Require plugin features. $this->init_textdomain(); @@ -137,7 +138,7 @@ private function register_deactivation_hook() { */ public static function activate() { // Make sure user sees the "Get Started" when first time opening. - Config::set_getting_started( true ); + ( new Getting_Started_Entry() )->set( true ); Analytics::record_user_event( 'activate_plugin' ); } @@ -145,13 +146,14 @@ public static function activate() { * Plugin connected to Jetpack handler. */ public function handle_jetpack_connection() { - if ( Config::is_getting_started() ) { + $getting_started = new Getting_Started_Entry(); + if ( $getting_started->get() === true ) { // Special case: when getting started, ensure that the Critical CSS module is enabled. $status = new Status( 'critical_css' ); $status->update( true ); } - Config::clear_getting_started(); + $getting_started->set( false ); } /** @@ -249,6 +251,6 @@ public function uninstall() { Transient::delete_by_prefix( '' ); // Clear getting started value - Config::clear_getting_started(); + ( new Getting_Started_Entry() )->set( false ); } } diff --git a/projects/plugins/boost/app/data-sync/Getting_Started_Entry.php b/projects/plugins/boost/app/data-sync/Getting_Started_Entry.php new file mode 100644 index 0000000000000..b4ebde94f2576 --- /dev/null +++ b/projects/plugins/boost/app/data-sync/Getting_Started_Entry.php @@ -0,0 +1,44 @@ +<?php + +namespace Automattic\Jetpack_Boost\Data_Sync; + +use Automattic\Jetpack\Status; +use Automattic\Jetpack\WP_JS_Data_Sync\Contracts\Entry_Can_Get; +use Automattic\Jetpack\WP_JS_Data_Sync\Contracts\Entry_Can_Set; +use Automattic\Jetpack_Boost\Lib\Connection; +use Automattic\Jetpack_Boost\Lib\Premium_Features; + +class Getting_Started_Entry implements Entry_Can_Get, Entry_Can_Set { + private $option_key = 'jb_get_started'; + + /** + * Determines if the user should be shown the Getting Started page. + */ + public function get() { + // No point in showing the page if the site is offline, it's probably localhost. + if ( ( new Status() )->is_offline_mode() ) { + return false; + } + + // If there is no connection, the page must be shown to give them a chance to connect by choosing a plan. + if ( ! ( new Connection() )->is_connected() ) { + return true; + } + + // If the site already has premium plan, there is no need to show the page. + if ( Premium_Features::has_any() ) { + return false; + } + + // For all other cases, the page should be shown only if the flag is set. It indicates that it's a new site. + return \get_option( $this->option_key, false ); + } + + public function set( $value ) { + if ( $value === true ) { + update_option( $this->option_key, $value, false ); + } else { + delete_option( $this->option_key ); + } + } +} diff --git a/projects/plugins/boost/app/features/setup-prompt/Setup_Prompt.php b/projects/plugins/boost/app/features/setup-prompt/Setup_Prompt.php index f8dd936871816..7465ba0902422 100644 --- a/projects/plugins/boost/app/features/setup-prompt/Setup_Prompt.php +++ b/projects/plugins/boost/app/features/setup-prompt/Setup_Prompt.php @@ -5,8 +5,8 @@ namespace Automattic\Jetpack_Boost\Features\Setup_Prompt; -use Automattic\Jetpack_Boost\Admin\Config; use Automattic\Jetpack_Boost\Contracts\Has_Setup; +use Automattic\Jetpack_Boost\Data_Sync\Getting_Started_Entry; class Setup_Prompt implements Has_Setup { @@ -22,7 +22,7 @@ public function setup() { } public function load_banner() { - if ( ! Config::is_getting_started() || $this->is_banner_dismissed() ) { + if ( ( new Getting_Started_Entry() )->get() === false || $this->is_banner_dismissed() ) { return; } diff --git a/projects/plugins/boost/app/lib/Premium_Pricing.php b/projects/plugins/boost/app/lib/Premium_Pricing.php index 8886abd17fad3..2a4a75ea420c8 100644 --- a/projects/plugins/boost/app/lib/Premium_Pricing.php +++ b/projects/plugins/boost/app/lib/Premium_Pricing.php @@ -8,29 +8,28 @@ class Premium_Pricing { const PRODUCT_SLUG_BASE = 'jetpack_boost'; - public static function init() { - add_filter( 'jetpack_boost_js_constants', array( static::class, 'add_js_constants' ) ); - } - - public static function add_js_constants( $constants ) { - $constants['pricing'] = array(); - $yearly_pricing_slug = self::PRODUCT_SLUG_BASE . '_yearly'; - $yearly_pricing = Wpcom_Products::get_product_pricing( $yearly_pricing_slug ); + /** + * Get an object containing the yearly pricing information for Jetpack Boost. + * + * Used by Jetpack_Boost js constants and data sync. + */ + public static function get_yearly_pricing() { + $yearly_pricing_slug = self::PRODUCT_SLUG_BASE . '_yearly'; + $yearly_pricing = Wpcom_Products::get_product_pricing( $yearly_pricing_slug ); if ( empty( $yearly_pricing ) ) { // In offline mode, we don't have access to the pricing data and it's not an error. if ( ! ( new Status() )->is_offline_mode() ) { Analytics::record_user_event( 'upgrade_price_missing', array( 'error_message' => 'Missing pricing information on benefits interstitial page.' ) ); } - return $constants; + return null; } - $constants['pricing']['yearly'] = array( + return array( 'priceBefore' => $yearly_pricing['full_price'], 'priceAfter' => $yearly_pricing['discount_price'], 'currencyCode' => $yearly_pricing['currency_code'], 'isIntroductoryOffer' => $yearly_pricing['is_introductory_offer'] === true, ); - return $constants; } } diff --git a/projects/plugins/boost/app/lib/class-cli.php b/projects/plugins/boost/app/lib/class-cli.php index c253db0ee371d..25cd3c99ba1ff 100644 --- a/projects/plugins/boost/app/lib/class-cli.php +++ b/projects/plugins/boost/app/lib/class-cli.php @@ -9,7 +9,7 @@ namespace Automattic\Jetpack_Boost\Lib; -use Automattic\Jetpack_Boost\Admin\Config; +use Automattic\Jetpack_Boost\Data_Sync\Getting_Started_Entry; use Automattic\Jetpack_Boost\Jetpack_Boost; /** @@ -96,7 +96,7 @@ public function getting_started( $args ) { ); } - Config::set_getting_started( 'true' === $status ); + ( new Getting_Started_Entry() )->set( 'true' === $status ); \WP_CLI::success( /* translators: %s refers to 'true' or 'false' */ diff --git a/projects/plugins/boost/app/lib/class-connection.php b/projects/plugins/boost/app/lib/class-connection.php index 45fe23c558611..b91f69c5f2597 100644 --- a/projects/plugins/boost/app/lib/class-connection.php +++ b/projects/plugins/boost/app/lib/class-connection.php @@ -27,30 +27,16 @@ class Connection { */ private $manager; - /** - * Constructor. - */ public function __construct() { $this->manager = new Manager( 'jetpack-boost' ); + } + public function init() { add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) ); - add_filter( 'jetpack_boost_js_constants', array( $this, 'add_connection_config_data' ) ); - $this->initialize_deactivate_disconnect(); } - /** - * Add connection data to the array of constants - * - * @param array $constants The associative array of constants. - */ - public function add_connection_config_data( $constants ) { - $constants['connection'] = $this->get_connection_api_response(); - - return $constants; - } - /** * Initialize the plugin deactivation hook. */ @@ -106,7 +92,7 @@ public function deactivate_disconnect_network() { * Get the WordPress.com blog ID of this site, if it's connected */ public static function wpcom_blog_id() { - return defined( 'IS_WPCOM' ) && IS_WPCOM ? get_current_blog_id() : \Jetpack_Options::get_option( 'id' ); + return defined( 'IS_WPCOM' ) && IS_WPCOM ? get_current_blog_id() : (int) \Jetpack_Options::get_option( 'id' ); } /** diff --git a/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php b/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php index fe7a4a409775d..f8b385e9365df 100644 --- a/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php +++ b/projects/plugins/boost/app/modules/optimizations/render-blocking-js/class-render-blocking-js.php @@ -218,8 +218,9 @@ protected function ignore_exclusion_scripts( $buffer ) { // Scripts inside HTML comments. '~<!--.*?-->~si', - // Scripts with application/json type - '~<script\s+[^\>]*type=(?<q>["\']*)application/json\k<q>.*?>.*?</script>~si', + // Scripts with types that do not execute complex code. Moving them down can be dangerous + // and does not benefit performance. Includes types: application/json and importmap. + '~<script\s+[^\>]*type=(?<q>["\']*)(application/json|importmap)\k<q>.*?>.*?</script>~si', ); return preg_replace_callback( diff --git a/projects/plugins/boost/changelog/boost-react-main b/projects/plugins/boost/changelog/boost-react-main new file mode 100644 index 0000000000000..7fd7aa47316cd --- /dev/null +++ b/projects/plugins/boost/changelog/boost-react-main @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Refactored Main.svelte to react + + diff --git a/projects/plugins/boost/changelog/boost-react-module b/projects/plugins/boost/changelog/boost-react-module new file mode 100644 index 0000000000000..f0c952fdb3e07 --- /dev/null +++ b/projects/plugins/boost/changelog/boost-react-module @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Refactored Module component to react + + diff --git a/projects/plugins/boost/changelog/migrate-settings-page-tips b/projects/plugins/boost/changelog/migrate-settings-page-tips new file mode 100644 index 0000000000000..a85602a21b916 --- /dev/null +++ b/projects/plugins/boost/changelog/migrate-settings-page-tips @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Migrate Settings Page Tips to react. + + diff --git a/projects/plugins/boost/changelog/renovate-storybook-monorepo b/projects/plugins/boost/changelog/renovate-storybook-monorepo new file mode 100644 index 0000000000000..c47cb18e82997 --- /dev/null +++ b/projects/plugins/boost/changelog/renovate-storybook-monorepo @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/boost/changelog/update-boost-react-settings-page b/projects/plugins/boost/changelog/update-boost-react-settings-page new file mode 100644 index 0000000000000..ec0e3397552d8 --- /dev/null +++ b/projects/plugins/boost/changelog/update-boost-react-settings-page @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Update Settings Page to react. + + diff --git a/projects/plugins/boost/package.json b/projects/plugins/boost/package.json index c93babf413ae9..091605fc9ad9e 100644 --- a/projects/plugins/boost/package.json +++ b/projects/plugins/boost/package.json @@ -19,6 +19,7 @@ "history": "5.3.0", "jetpack-boost-critical-css-gen": "github:automattic/jetpack-boost-critical-css-gen#release-0.0.11", "prettier": "npm:wp-prettier@3.0.3", + "react-router-dom": "6.21.0", "svelte-navigator": "3.2.2", "zod": "3.22.3" }, @@ -37,7 +38,7 @@ "@rollup/plugin-replace": "5.0.2", "@rollup/plugin-terser": "0.4.3", "@rollup/plugin-typescript": "8.3.3", - "@storybook/react": "7.4.6", + "@storybook/react": "7.6.5", "@types/jquery": "3.5.25", "@wordpress/i18n": "4.47.0", "concurrently": "7.6.0", diff --git a/projects/plugins/boost/readme.txt b/projects/plugins/boost/readme.txt index 00ffe51fde9b5..c2e0f69765a44 100644 --- a/projects/plugins/boost/readme.txt +++ b/projects/plugins/boost/readme.txt @@ -5,7 +5,7 @@ Tags: performance, speed, pagespeed, web vitals, critical css, optimize, defer Requires at least: 5.5 Tested up to: 6.4 Requires PHP: 7.0 -Stable tag: 2.1.1 +Stable tag: 2.2.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -187,19 +187,9 @@ If you run into compatibility issues, please do let us know. You can drop us a l 2. Jetpack Boost Speed Improvement == Changelog == -### 2.2.0-beta - 2023-10-26 -#### Changed -- General: Indicate full compatibility with the latest version of WordPress, 6.4. -- Getting Started: Improved how features are sorted in the getting started page. -- Performance History: Improvements in design. - -#### Deprecated -- Lazy Images: Added deprecation notice. -- Lazy Images: Force disable feature to avoid conflict with new version of Gutenberg and WordPress 6.4. - +### 2.2.1 - 2023-12-21 #### Fixed -- Concatenate JS/CSS: Fixed generating invalid html ID values for concatenated stylesheets. -- Image CDN: Update quality slider UI. +- Defer JS: added importmap to the exclusion list to fix compatibility issues. -------- diff --git a/projects/plugins/boost/tests/e2e/lib/pages/wp-admin/JetpackBoostPage.js b/projects/plugins/boost/tests/e2e/lib/pages/wp-admin/JetpackBoostPage.js index 429cc41db15e5..c163d91cf6d6e 100644 --- a/projects/plugins/boost/tests/e2e/lib/pages/wp-admin/JetpackBoostPage.js +++ b/projects/plugins/boost/tests/e2e/lib/pages/wp-admin/JetpackBoostPage.js @@ -2,7 +2,7 @@ import WpPage from 'jetpack-e2e-commons/pages/wp-page.js'; import { resolveSiteUrl } from 'jetpack-e2e-commons/helpers/utils-helper.js'; const apiEndpointsRegex = { - 'modules-state': /jetpack-boost-ds\/modules-state\/merge/, + 'modules-state': /jetpack-boost-ds\/modules-state\/set/, connection: /jetpack-boost\/v1\/connection/, }; @@ -65,14 +65,14 @@ export default class JetpackBoostPage extends WpPage { } async toggleModule( moduleName ) { - this.page.click( `#jb-feature-toggle-${ moduleName }` ); + this.page.click( `.jb-feature-toggle-${ moduleName }` ); await this.waitForApiResponse( 'modules-state' ); } async isModuleEnabled( moduleName ) { - const toggle = await this.page.waitForSelector( `#jb-feature-toggle-${ moduleName }` ); - const toggleParent = await toggle.waitForSelector( 'xpath=..' ); - const classNames = await toggleParent.getAttribute( 'class' ); + const toggle = await this.page.waitForSelector( `.jb-feature-toggle-${ moduleName }` ); + const toggleSwitch = await toggle.waitForSelector( '.components-form-toggle' ); + const classNames = await toggleSwitch.getAttribute( 'class' ); return classNames.includes( 'is-checked' ); } diff --git a/projects/plugins/boost/tsconfig.json b/projects/plugins/boost/tsconfig.json index 32fd3f7dd8363..a2db0696677bc 100644 --- a/projects/plugins/boost/tsconfig.json +++ b/projects/plugins/boost/tsconfig.json @@ -23,6 +23,6 @@ "sourceMap": true, "forceConsistentCasingInFileNames": true, "lib": [ "dom", "es2021" ], - "strict": true, + "strict": true } } diff --git a/projects/plugins/boost/wp-js-data-sync.php b/projects/plugins/boost/wp-js-data-sync.php index a8ac297841d5e..38ec91d8bd4e6 100644 --- a/projects/plugins/boost/wp-js-data-sync.php +++ b/projects/plugins/boost/wp-js-data-sync.php @@ -1,14 +1,19 @@ <?php +use Automattic\Jetpack\Status; use Automattic\Jetpack\WP_JS_Data_Sync\Contracts\Data_Sync_Entry; use Automattic\Jetpack\WP_JS_Data_Sync\Data_Sync; use Automattic\Jetpack\WP_JS_Data_Sync\Data_Sync_Readonly; use Automattic\Jetpack\WP_JS_Data_Sync\Schema\Schema; use Automattic\Jetpack_Boost\Data_Sync\Critical_CSS_Meta_Entry; +use Automattic\Jetpack_Boost\Data_Sync\Getting_Started_Entry; use Automattic\Jetpack_Boost\Data_Sync\Mergeable_Array_Entry; use Automattic\Jetpack_Boost\Data_Sync\Minify_Excludes_State_Entry; use Automattic\Jetpack_Boost\Data_Sync\Modules_State_Entry; use Automattic\Jetpack_Boost\Data_Sync\Premium_Features_Entry; +use Automattic\Jetpack_Boost\Lib\Connection; +use Automattic\Jetpack_Boost\Lib\Premium_Features; +use Automattic\Jetpack_Boost\Lib\Premium_Pricing; use Automattic\Jetpack_Boost\Modules\Optimizations\Minify\Minify_CSS; use Automattic\Jetpack_Boost\Modules\Optimizations\Minify\Minify_JS; @@ -285,6 +290,15 @@ function jetpack_boost_initialize_datasync() { function jetpack_boost_ui_config() { return array( 'plugin_dir_url' => untrailingslashit( JETPACK_BOOST_PLUGINS_DIR_URL ), + 'pricing' => Premium_Pricing::get_yearly_pricing(), + 'site' => array( + 'domain' => ( new Status() )->get_site_suffix(), + 'online' => ! ( new Status() )->is_offline_mode(), + ), + 'is_premium' => Premium_Features::has_any(), + 'connection' => ( new Connection() )->get_connection_api_response(), ); } jetpack_boost_register_readonly_option( 'config', 'jetpack_boost_ui_config' ); + +jetpack_boost_register_option( 'getting_started', Schema::as_boolean()->fallback( false ), new Getting_Started_Entry() ); diff --git a/projects/plugins/crm/CHANGELOG.md b/projects/plugins/crm/CHANGELOG.md index 20e780ce15089..1a863e64462a7 100644 --- a/projects/plugins/crm/CHANGELOG.md +++ b/projects/plugins/crm/CHANGELOG.md @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [6.3.2] - 2023-12-19 +### Changed +- Settings: Make support document links more consistent. [#34695] + +### Fixed +- Segments: Fixed an issue preventing segments from being deleted. [#34690] + ## [6.3.1] - 2023-12-14 ### Added - WooSync: New `jpcrm_woo_sync_order_data` hook. [#34212] @@ -263,6 +270,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved: Added a migration to remove outdated AKA lines [5.5.4-a.1]: https://github.com/Automattic/jetpack-crm/compare/v5.5.3...v5.5.4-a.1 +[6.3.2]: https://github.com/Automattic/jetpack-crm/compare/6.3.1...6.3.2 [6.3.1]: https://github.com/Automattic/jetpack-crm/compare/6.3.0...6.3.1 [6.3.0]: https://github.com/Automattic/jetpack-crm/compare/6.2.0...6.3.0 [6.2.0]: https://github.com/Automattic/jetpack-crm/compare/6.1.0...6.2.0 diff --git a/projects/plugins/crm/ZeroBSCRM.php b/projects/plugins/crm/ZeroBSCRM.php index 2f5fffc6eb188..373c2890de235 100644 --- a/projects/plugins/crm/ZeroBSCRM.php +++ b/projects/plugins/crm/ZeroBSCRM.php @@ -3,7 +3,7 @@ * Plugin Name: Jetpack CRM * Plugin URI: https://jetpackcrm.com * Description: Jetpack CRM is the simplest CRM for WordPress. Self host your own Customer Relationship Manager using WP. - * Version: 6.3.2-alpha + * Version: 6.3.3-alpha * Author: Automattic - Jetpack CRM team * Author URI: https://jetpackcrm.com * Text Domain: zero-bs-crm diff --git a/projects/plugins/crm/admin/settings/client-portal.page.php b/projects/plugins/crm/admin/settings/client-portal.page.php index 3155d0d3f59e7..0a0eb9b2ca55f 100644 --- a/projects/plugins/crm/admin/settings/client-portal.page.php +++ b/projects/plugins/crm/admin/settings/client-portal.page.php @@ -187,10 +187,12 @@ <tbody> <tr> - <td class="wfieldname"><label for="wpzbscrm_portalpage"><?php esc_html_e( 'Client Portal page', 'zero-bs-crm' ); ?></label><br /><?php esc_html_e( 'Select the page with your client portal shortcode.', 'zero-bs-crm' ); ?> + <td class="wfieldname"> + <?php ##WLREMOVE ?> - <a href="<?php echo esc_url( $zbs->urls['kbclientportal'] ); ?>" target="_blank"><?php esc_html_e( 'Learn More', 'zero-bs-crm' ); ?></a> + <div class="ui teal label right floated"><i class="circle info icon link"></i> <a href="<?php echo esc_url( $zbs->urls['kbclientportal'] ); ?>" target="_blank"><?php esc_html_e( 'Read more', 'zero-bs-crm' ); ?></a></div> <?php ##/WLREMOVE ?> + <label for="wpzbscrm_portalpage"><?php esc_html_e( 'Client Portal page', 'zero-bs-crm' ); ?></label><br /><?php esc_html_e( 'Select the page with your client portal shortcode.', 'zero-bs-crm' ); ?> </td> <td> <?php @@ -248,10 +250,11 @@ </tr> <tr> - <td class="wfieldname"><label for="wpzbscrm_easyaccesslinks"><?php esc_html_e( 'Allow Easy-Access links', 'zero-bs-crm' ); ?></label><br /><?php esc_html_e( 'Tick to allow logged-out users to view quotes and invoices via a secure hash URL.', 'zero-bs-crm' ); ?> + <td class="wfieldname"> <?php ##WLREMOVE ?> - <a href="<?php echo esc_url( $zbs->urls['kbeasyaccess'] ); ?>" target="_blank"><?php esc_html_e( 'Learn More', 'zero-bs-crm' ); ?></a> + <div class="ui teal label right floated"><i class="circle info icon link"></i> <a href="<?php echo esc_url( $zbs->urls['kbeasyaccess'] ); ?>" target="_blank"><?php esc_html_e( 'Read more', 'zero-bs-crm' ); ?></a></div> <?php ##/WLREMOVE ?> + <label for="wpzbscrm_easyaccesslinks"><?php esc_html_e( 'Allow Easy-Access links', 'zero-bs-crm' ); ?></label><br /><?php esc_html_e( 'Tick to allow logged-out users to view quotes and invoices via a secure hash URL.', 'zero-bs-crm' ); ?> </td> <td style="width:540px"><input type="checkbox" class="winput form-control" name="wpzbscrm_easyaccesslinks" id="wpzbscrm_easyaccesslinks" value="1" <?php @@ -302,10 +305,11 @@ <tr> - <td class="wfieldname"><label for="wpzbscrm_portalusers"><?php esc_html_e( 'Generate WordPress users for new contacts', 'zero-bs-crm' ); ?></label><br /><?php esc_html_e( "By default this will automatically email the new contact a welcome email as soon as they're added. If you prefer to not have this email sent, you can disable this email template.", 'zero-bs-crm' ); ?> + <td class="wfieldname"> <?php ##WLREMOVE ?> - <a href="<?php echo esc_url( $zbs->urls['kbdisablewelcome'] ); ?>" target="_blank"><?php esc_html_e( 'Learn More', 'zero-bs-crm' ); ?></a> + <div class="ui teal label right floated"><i class="circle info icon link"></i> <a href="<?php echo esc_url( $zbs->urls['kbdisablewelcome'] ); ?>" target="_blank"><?php esc_html_e( 'Read more', 'zero-bs-crm' ); ?></a></div> <?php ##/WLREMOVE ?> + <label for="wpzbscrm_portalusers"><?php esc_html_e( 'Generate WordPress users for new contacts', 'zero-bs-crm' ); ?></label><br /><?php esc_html_e( "By default this will automatically email the new contact a welcome email as soon as they're added. If you prefer to not have this email sent, you can disable this email template.", 'zero-bs-crm' ); ?> </td> <td style="width:540px"><input type="checkbox" class="winput form-control" name="wpzbscrm_portalusers" id="wpzbscrm_portalusers" value="1" <?php diff --git a/projects/plugins/crm/admin/settings/forms.page.php b/projects/plugins/crm/admin/settings/forms.page.php index 188c2fe43ddfc..e7c32b3ba0fbe 100644 --- a/projects/plugins/crm/admin/settings/forms.page.php +++ b/projects/plugins/crm/admin/settings/forms.page.php @@ -115,7 +115,7 @@ <tbody> <tr> - <td colspan="2" class="wmid"><button type="submit" class="ui button primary"><?php esc_html_e( 'Save Settings', 'zero-bs-crm' ); ?></button></td> + <td class="wmid"><button type="submit" class="ui button primary"><?php esc_html_e( 'Save Settings', 'zero-bs-crm' ); ?></button></td> </tr> </tbody> diff --git a/projects/plugins/crm/admin/settings/general.page.php b/projects/plugins/crm/admin/settings/general.page.php index dcf0c69a0b757..b9f0c5e7b59db 100644 --- a/projects/plugins/crm/admin/settings/general.page.php +++ b/projects/plugins/crm/admin/settings/general.page.php @@ -234,7 +234,7 @@ ?> - <p id="sbDescOLD"><?php echo wp_kses( sprintf( __( 'From this page you can choose global settings for your CRM, and using the tabs above you can set up different <a href="%s" target="_blank">Extensions</a>', 'zero-bs-crm' ), esc_url( $zbs->urls['products'] ) ), $zbs->acceptable_restricted_html ); ?></p> + <p id="sbDescOLD"><?php esc_html_e( 'From this page you can choose global settings for your CRM.', 'zero-bs-crm' ); ?></p> <?php if ( isset( $sbupdated ) ) { @@ -274,7 +274,12 @@ <tbody> <tr> - <td class="wfieldname"><label for="wpzbscrm_menulayout"><?php esc_html_e( 'Menu Layout', 'zero-bs-crm' ); ?>:</label><br /><?php esc_html_e( 'How do you want your WordPress Admin Menu to Display?', 'zero-bs-crm' ); ?></td> + <td class="wfieldname"> + <?php ##WLREMOVE ?> + <div class="ui teal label right floated"><i class="circle info icon link"></i> <a href="<?php echo esc_url( $zbs->urls['kbshowwpmenus'] ); ?>" target="_blank"><?php esc_html_e( 'Read more', 'zero-bs-crm' ); ?></a></div> + <?php ##/WLREMOVE ?> + <label for="wpzbscrm_menulayout"><?php esc_html_e( 'Menu Layout', 'zero-bs-crm' ); ?>:</label><br /><?php esc_html_e( 'How do you want your WordPress Admin Menu to Display?', 'zero-bs-crm' ); ?> + </td> <td style="width:540px"> <select class="winput" name="wpzbscrm_menulayout" id="wpzbscrm_menulayout"> <!-- common currencies first --> @@ -300,10 +305,7 @@ <br /> <div> <?php esc_html_e( 'Are you looking for your other WordPress menu items? (e.g.', 'zero-bs-crm' ); ?> <a href="<?php echo esc_url( admin_url( 'plugins.php' ) ); ?>"><?php esc_html_e( 'Plugins', 'zero-bs-crm' ); ?></a>, <?php esc_html_e( 'or', 'zero-bs-crm' ); ?> <a href="<?php echo esc_url( admin_url( 'users.php' ) ); ?>"><?php esc_html_e( 'Users', 'zero-bs-crm' ); ?></a>)?<br /> - <?php esc_html_e( "If you can't see these, (and you want to), select 'Slimline' or 'Full' from the above menu, then make sure 'Override WordPress (For All WP Users):' is disabled below", 'zero-bs-crm' ); ?> (<a href="#override-allusers"><?php esc_html_e( 'here', 'zero-bs-crm' ); ?></a>).<br /> - <?php ##WLREMOVE ?> - <a href="<?php echo esc_url( $zbs->urls['kbshowwpmenus'] ); ?>" target="_blank"><?php esc_html_e( 'View Guide', 'zero-bs-crm' ); ?></a> - <?php ##/WLREMOVE ?> + <?php esc_html_e( "If you can't see these, (and you want to), select 'Slimline' or 'Full' from the above menu, then make sure 'Override WordPress (For All WP Users):' is disabled below", 'zero-bs-crm' ); ?> (<a href="#override-allusers"><?php esc_html_e( 'here', 'zero-bs-crm' ); ?></a>). </div> </td> </tr> @@ -570,8 +572,11 @@ <?php ##WLREMOVE ?> <tr> - <td class="wfieldname"><label for="wpzbscrm_shareessentials"><?php esc_html_e( 'Usage Tracking', 'zero-bs-crm' ); ?>:</label><br /><?php esc_html_e( 'Share CRM usage with us. No contact or sensitive CRM data is shared.', 'zero-bs-crm' ); ?> - <a href="<?php echo esc_url( $zbs->urls['usageinfo'] ); ?>" target="_blank"><?php esc_html_e( 'Learn More', 'zero-bs-crm' ); ?>.</a> + <td class="wfieldname"> + <?php ##WLREMOVE ?> + <div class="ui teal label right floated"><i class="circle info icon link"></i> <a href="<?php echo esc_url( $zbs->urls['usageinfo'] ); ?>" target="_blank"><?php esc_html_e( 'Read more', 'zero-bs-crm' ); ?></a></div> + <?php ##/WLREMOVE ?> + <label for="wpzbscrm_shareessentials"><?php esc_html_e( 'Usage Tracking', 'zero-bs-crm' ); ?>:</label><br /><?php esc_html_e( 'Share CRM usage with us. No contact or sensitive CRM data is shared.', 'zero-bs-crm' ); ?> </td> <td style="width:540px"><input type="checkbox" class="winput form-control" name="wpzbscrm_shareessentials" id="wpzbscrm_shareessentials" value="1" <?php diff --git a/projects/plugins/crm/admin/settings/partials/menu.block.php b/projects/plugins/crm/admin/settings/partials/menu.block.php index e4b08e08f1f58..cff77eb799a0b 100644 --- a/projects/plugins/crm/admin/settings/partials/menu.block.php +++ b/projects/plugins/crm/admin/settings/partials/menu.block.php @@ -241,5 +241,5 @@ <?php ##WLREMOVE ?> <a class="item" href="<?php echo jpcrm_esc_link( $zbs->slugs['extensions'] ); ?>"><i class="ui orange puzzle piece icon"></i> <?php echo esc_html__( 'Extensions', 'zero-bs-crm' ); ?></a> <?php ##/WLREMOVE ?> - <a class="item" href="<?php echo jpcrm_esc_link( wp_nonce_url( $zbs->slugs['settings'] . '&resetsettings=1' ) ); ?> "></i> <?php echo esc_html__( 'Restore default settings', 'zero-bs-crm' ); ?></a> + <a class="item" href="<?php echo jpcrm_esc_link( wp_nonce_url( $zbs->slugs['settings'] . '&resetsettings=1' ) ); ?> "> <?php echo esc_html__( 'Restore default settings', 'zero-bs-crm' ); ?></a> </div> diff --git a/projects/plugins/crm/changelog/init-release-cycle b/projects/plugins/crm/changelog/init-release-cycle index 59aed3deec793..9ea13cdd8e18d 100644 --- a/projects/plugins/crm/changelog/init-release-cycle +++ b/projects/plugins/crm/changelog/init-release-cycle @@ -1,5 +1,5 @@ Significance: patch Type: changed -Comment: Init 6.3.2-alpha +Comment: Init 6.3.3-alpha diff --git a/projects/plugins/crm/composer.json b/projects/plugins/crm/composer.json index 2f930bfda29b4..2a8805cce704e 100644 --- a/projects/plugins/crm/composer.json +++ b/projects/plugins/crm/composer.json @@ -42,7 +42,7 @@ ] }, "config": { - "autoloader-suffix": "06c775433a83ed276f0a1d8ac25f93ba_crmⓥ6_3_2_alpha", + "autoloader-suffix": "06c775433a83ed276f0a1d8ac25f93ba_crmⓥ6_3_3_alpha", "allow-plugins": { "automattic/jetpack-autoloader": true, "automattic/jetpack-composer-plugin": true, diff --git a/projects/plugins/crm/includes/ZeroBSCRM.AJAX.php b/projects/plugins/crm/includes/ZeroBSCRM.AJAX.php index 0327c08dbef79..7fb8e2d5f3286 100644 --- a/projects/plugins/crm/includes/ZeroBSCRM.AJAX.php +++ b/projects/plugins/crm/includes/ZeroBSCRM.AJAX.php @@ -3741,7 +3741,11 @@ function zeroBSCRM_AJAX_enactListViewBulkAction() { // Check perms for given object $has_perms = zeroBSCRM_permsObjType( $zbs->DAL->objTypeID( $objtype ) ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase if ( ! $has_perms ) { - jpcrm_api_forbidden_request(); + $reply = array( + 'status' => __( 'Forbidden', 'zero-bs-crm' ), + 'message' => __( 'You do not have permission to access this resource.', 'zero-bs-crm' ), + ); + wp_send_json_error( $reply, 403 ); } // ret diff --git a/projects/plugins/crm/includes/ZeroBSCRM.Core.php b/projects/plugins/crm/includes/ZeroBSCRM.Core.php index 02d8020495c20..9dc8c07b1adfe 100644 --- a/projects/plugins/crm/includes/ZeroBSCRM.Core.php +++ b/projects/plugins/crm/includes/ZeroBSCRM.Core.php @@ -24,7 +24,7 @@ final class ZeroBSCRM { * * @var string */ - public $version = '6.3.1'; + public $version = '6.3.2'; /** * WordPress version tested with. @@ -971,6 +971,7 @@ private function setupUrlsSlugsEtc() { $this->urls['kb-pre-v5-migration-todo'] = 'https://kb.jetpackcrm.com/knowledge-base/upgrading-to-jetpack-crm-v5-0/'; $this->urls['kb-mailpoet'] = 'https://kb.jetpackcrm.com/knowledge-base/mailpoet-crm-sync/'; $this->urls['kb-automations'] = 'https://kb.jetpackcrm.com/knowledge-base/automations/'; + $this->urls['kb-contact-fields'] = 'https://kb.jetpackcrm.com/knowledge-base/contact-field-list/'; // coming soon $this->urls['soon'] = 'https://jetpackcrm.com/coming-soon/'; diff --git a/projects/plugins/crm/includes/ZeroBSCRM.Permissions.php b/projects/plugins/crm/includes/ZeroBSCRM.Permissions.php index 6368a8556b763..dba0d67f169f3 100644 --- a/projects/plugins/crm/includes/ZeroBSCRM.Permissions.php +++ b/projects/plugins/crm/includes/ZeroBSCRM.Permissions.php @@ -560,6 +560,7 @@ function zeroBSCRM_permsObjType( $obj_type_id = -1 ) { // phpcs:ignore WordPress switch ( $obj_type_id ) { case ZBS_TYPE_CONTACT: case ZBS_TYPE_COMPANY: + case ZBS_TYPE_SEGMENT: return zeroBSCRM_permsCustomers(); case ZBS_TYPE_QUOTE: @@ -577,6 +578,7 @@ function zeroBSCRM_permsObjType( $obj_type_id = -1 ) { // phpcs:ignore WordPress case ZBS_TYPE_TASK: return zeroBSCRM_perms_tasks(); + } return false; @@ -716,7 +718,6 @@ function zeroBSCRM_permsExport(){ return false; } - // LOGS diff --git a/projects/plugins/crm/modules/mailpoet/admin/settings/main.page.php b/projects/plugins/crm/modules/mailpoet/admin/settings/main.page.php index c1dd19af778a7..99ce727581723 100644 --- a/projects/plugins/crm/modules/mailpoet/admin/settings/main.page.php +++ b/projects/plugins/crm/modules/mailpoet/admin/settings/main.page.php @@ -143,18 +143,18 @@ function jpcrm_settings_page_html_mailpoet_main(){ </tbody> </table> - <table class="table table-bordered table-striped wtab"> - <tbody> + <table class="table table-bordered table-striped wtab"> + <tbody> - <tr> - <td colspan="2" class="wmid"><button type="submit" class="button button-primary button-large"><?php esc_html_e('Save Settings','zero-bs-crm'); ?></button></td> - </tr> - - </tbody> - </table> + <tr> + <td class="wmid"><button type="submit" class="button button-primary button-large"><?php esc_html_e( 'Save Settings', 'zero-bs-crm' ); ?></button></td> + </tr> - </form> + </tbody> + </table> - </div><?php + </form> -} \ No newline at end of file + </div> + <?php +} diff --git a/projects/plugins/crm/modules/woo-sync/admin/settings/main.page.php b/projects/plugins/crm/modules/woo-sync/admin/settings/main.page.php index 994c49e2c61ae..11bfac1d89867 100644 --- a/projects/plugins/crm/modules/woo-sync/admin/settings/main.page.php +++ b/projects/plugins/crm/modules/woo-sync/admin/settings/main.page.php @@ -285,11 +285,14 @@ function jpcrm_settings_page_html_woosync_main() { <tr> <td class="wfieldname"> + <?php ##WLREMOVE ?> + <div class="ui teal label right floated"><i class="circle info icon link"></i> <a href="<?php echo esc_url( $zbs->urls['kb-contact-fields'] ); ?>" target="_blank"><?php esc_html_e( 'Read more', 'zero-bs-crm' ); ?></a></div> + <?php ##/WLREMOVE ?> <label for="wpzbscrm_port"><?php esc_html_e( 'WooCommerce My Account', 'zero-bs-crm' ); ?>:</label><br /> - <?php esc_html_e( 'Enter a comma-separated list of Jetpack CRM custom fields to let customers edit these via WooCommerce My Account (e.g. custom-field-1,other-custom-field)', 'zero-bs-crm' ); ?> + <?php esc_html_e( 'Enter a comma-separated list of Jetpack CRM contact fields to let customers edit these via WooCommerce My Account.', 'zero-bs-crm' ); ?> </td> <td style="width:540px"> - <input type="text" class="winput form-control" name="wpzbscrm_wcport" id="wpzbscrm_port" value="<?php echo ( ! empty( $settings['wcport'] ) ? esc_attr( $settings['wcport'] ) : '' ); ?>" /> + <input type="text" class="winput form-control" name="wpzbscrm_wcport" id="wpzbscrm_port" value="<?php echo ( ! empty( $settings['wcport'] ) ? esc_attr( $settings['wcport'] ) : '' ); ?>" placeholder="e.g. addr1,custom-field-1" /> </td> </tr> <tr> @@ -384,7 +387,7 @@ function jpcrm_settings_page_html_woosync_main() { <tbody> <tr> - <td colspan="2" class="wmid"><button type="submit" class="button button-primary button-large"><?php esc_html_e( 'Save Settings', 'zero-bs-crm' ); ?></button></td> + <td class="wmid"><button type="submit" class="button button-primary button-large"><?php esc_html_e( 'Save Settings', 'zero-bs-crm' ); ?></button></td> </tr> </tbody> diff --git a/projects/plugins/crm/package.json b/projects/plugins/crm/package.json index 3372c11c09829..327a883e96d45 100644 --- a/projects/plugins/crm/package.json +++ b/projects/plugins/crm/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-crm", - "version": "6.3.2-alpha", + "version": "6.3.3-alpha", "description": "The CRM for WordPress", "author": "Automattic", "license": "GPL-2.0", @@ -41,8 +41,8 @@ "@babel/core": "7.23.5", "@babel/preset-env": "7.23.5", "@babel/runtime": "7.23.5", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@types/jest": "29.5.10", "@types/react": "18.2.33", "@types/react-dom": "18.2.14", diff --git a/projects/plugins/crm/readme.txt b/projects/plugins/crm/readme.txt index 5ac3c946401a6..4b8f890e98048 100644 --- a/projects/plugins/crm/readme.txt +++ b/projects/plugins/crm/readme.txt @@ -2,7 +2,7 @@ Contributors: automattic, kallehauge, cleacos, diegogarciarodrigues, bradshawtm, wpkaren, robertf4, woodyhayday, mikemayhem3030 Tags: CRM, Invoice, Woocommerce CRM, Clients, Lead Generation, contacts, customers, billing, email marketing, Marketing Automation, contact form, automations Tested up to: 6.4 -Stable tag: 6.3.1 +Stable tag: 6.3.2 Requires at least: 6.0 Requires PHP: 7.4 License: GPLv2 @@ -389,16 +389,10 @@ We offer a full, no-hassle refund within 14 days. You can read more about that, == Changelog == -### 6.3.1 - 2023-12-14 -#### Security -- Bulk actions: Stricter permissions checks. - -#### Added -- WooSync: New `jpcrm_woo_sync_order_data` hook. +### 6.3.2 - 2023-12-19 +#### Changed +- Settings: Make support document links more consistent. #### Fixed -- OAuth Connection: Updated typo to remove plural connection"s", and removed doc reference for whitelabel builds. -- Placeholders: Fixing quote placeholders on the quote template, client portal, pdf and emails. -- Quotes: Consistent rendering of dates in placeholders. -- Quotes: Consistent rendering of values and currency in placeholders. +- Segments: Fixed an issue preventing segments from being deleted. diff --git a/projects/plugins/jetpack/CHANGELOG.md b/projects/plugins/jetpack/CHANGELOG.md index 3edc6f69ff27f..b9e7efc638b41 100644 --- a/projects/plugins/jetpack/CHANGELOG.md +++ b/projects/plugins/jetpack/CHANGELOG.md @@ -2,6 +2,45 @@ ### This is a list detailing changes for all Jetpack releases. +## 13.0-a.7 - 2023-12-20 +### Enhancements +- Sharing Buttons Block: update the admin's setting screen when the sharing block is available. [#34673] + +### Improved compatibility +- Sharing Buttons: add the official X button to the list of supported services. [#34719] + +### Bug fixes +- My Plan: Fix JS errors due to nested anchor tags. [#34707] +- Payments Block: show an error message when unable to render payment button. [#34380] +- Subscribers: fix the subscriber count display if above 1000 subscribers. [#34689] + +### Other changes <!-- Non-user-facing changes go here. This section will not be copied to readme.txt. --> +- Add wpcom_ai_site_prompt option to the site settings endpoint [#34709] +- AI Assistant: handle new AI Control UI/UX improvements, fix DOM manipulation, remove "Try Again" toolbar button [#34383] +- Carousel: fix unresponsive navigation [#34678] +- Dashboard: avoid React warning when loading the VideoPress card. [#34713] +- Jetpack Google Fonts: Don't print font definition if the font is provided by the active theme. [#34608] +- Remove like block dependency on Like module and insert iframe once. [#34664] +- Small refactor Subscription services [#34635] +- Subscriptions: localize number format in access panel [#34691] +- Subscriptions: update "verify your email" wall copy [#34716] +- Updated package dependencies. [#34694] +- update feature not released yet [#34724] + +## 13.0-a.5 - 2023-12-15 +### Enhancements +- Subscriptions: adds toggle to disable email sending. [#34592] + +### Bug fixes +- Subscribers: pre/post-publish panel, show correct subscription count when using paywall. [#34643] + +### Other changes <!-- Non-user-facing changes go here. This section will not be copied to readme.txt. --> +- Add a flag for sites that have upgraded from the ecommerce trial. [#34597] +- Like block (beta): Make sure the block is not available when the Likes module or Likes / Reblog site options are disabled. [#34639] +- Like block (beta): remove the condition that decided whether to display Like block or Like widget. [#34650] +- Newsletter post-publish panel: closed initially [#34663] +- Refactor checkout modal to be more performant. [#34412] + ## 13.0-a.3 - 2023-12-14 ### Improved compatibility - Contact Form: avoid PHP warnings in the WordPress dashboard when used alongside other plugins making changes to admin pages. [#34576] diff --git a/projects/plugins/jetpack/_inc/client/at-a-glance/videopress.jsx b/projects/plugins/jetpack/_inc/client/at-a-glance/videopress.jsx index ad197283e3325..4b7ba2a4aa625 100644 --- a/projects/plugins/jetpack/_inc/client/at-a-glance/videopress.jsx +++ b/projects/plugins/jetpack/_inc/client/at-a-glance/videopress.jsx @@ -128,8 +128,7 @@ class DashVideoPress extends Component { className="jp-dash-item__is-inactive" noToggle={ ! hasConnectedOwner } overrideContent={ - ! hasConnectedOwner && - ! isOffline && ( + ! hasConnectedOwner && ! isOffline ? ( <JetpackBanner callToAction={ __( 'Connect', 'jetpack' ) } title={ __( @@ -143,7 +142,7 @@ class DashVideoPress extends Component { plan={ getJetpackProductUpsellByFeature( FEATURE_VIDEOPRESS ) } icon="video" /> - ) + ) : null } > <p className="jp-dash-item__description"> diff --git a/projects/plugins/jetpack/_inc/client/my-plan/my-plan-body.jsx b/projects/plugins/jetpack/_inc/client/my-plan/my-plan-body.jsx index 25f4c22d2da24..770ffd59e0088 100644 --- a/projects/plugins/jetpack/_inc/client/my-plan/my-plan-body.jsx +++ b/projects/plugins/jetpack/_inc/client/my-plan/my-plan-body.jsx @@ -106,13 +106,12 @@ class MyPlanBody extends React.Component { <div className="jp-landing__plan-features-text"> <h3 className="jp-landing__plan-features-title">{ title }</h3> <p>{ description }</p> - <Button - onClick={ this.handleButtonClickForTracking( 'view_backup_dash' ) } - href={ getRedirectUrl( 'calypso-activity-log', { site: this.props.siteRawUrl } ) } - compact - rna - > - <ExternalLink>{ __( 'View your backups', 'jetpack' ) }</ExternalLink> + <Button onClick={ this.handleButtonClickForTracking( 'view_backup_dash' ) } compact rna> + <ExternalLink + href={ getRedirectUrl( 'calypso-activity-log', { site: this.props.siteRawUrl } ) } + > + { __( 'View your backups', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> @@ -146,11 +145,14 @@ class MyPlanBody extends React.Component { </p> <Button onClick={ this.handleButtonClickForTracking( 'view_security_dash_rewind' ) } - href={ getRedirectUrl( 'calypso-activity-log', { site: this.props.siteRawUrl } ) } compact rna > - <ExternalLink>{ __( 'View your security activity', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-activity-log', { site: this.props.siteRawUrl } ) } + > + { __( 'View your security activity', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> @@ -200,23 +202,27 @@ class MyPlanBody extends React.Component { this.props.isPluginActive( 'vaultpress/vaultpress.php' ) ? ( <Button onClick={ this.handleButtonClickForTracking( 'view_security_dash' ) } - href={ getRedirectUrl( 'vaultpress-dashboard' ) } compact rna > - <ExternalLink> { __( 'View your security dashboard', 'jetpack' ) }</ExternalLink> + <ExternalLink href={ getRedirectUrl( 'vaultpress-dashboard' ) }> + { __( 'View your security dashboard', 'jetpack' ) } + </ExternalLink> </Button> ) : ( <Button onClick={ this.handleButtonClickForTracking( 'configure_vault' ) } - href={ getRedirectUrl( 'calypso-plugins-setup', { - site: this.props.siteRawUrl, - query: 'only=vaultpress', - } ) } compact rna > - <ExternalLink>{ __( 'View settings', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-plugins-setup', { + site: this.props.siteRawUrl, + query: 'only=vaultpress', + } ) } + > + { __( 'View settings', 'jetpack' ) } + </ExternalLink> </Button> ) } </div> @@ -365,14 +371,17 @@ class MyPlanBody extends React.Component { ) : ( <Button onClick={ this.handleButtonClickForTracking( 'configure_akismet' ) } - href={ getRedirectUrl( 'calypso-plugins-setup', { - site: this.props.siteRawUrl, - query: 'only=akismet', - } ) } compact rna > - <ExternalLink>{ __( 'View settings', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-plugins-setup', { + site: this.props.siteRawUrl, + query: 'only=akismet', + } ) } + > + { __( 'View settings', 'jetpack' ) } + </ExternalLink> </Button> ) } </div> @@ -447,11 +456,16 @@ class MyPlanBody extends React.Component { </p> <Button onClick={ this.handleButtonClickForTracking( 'view_site_activity' ) } - href={ getRedirectUrl( 'calypso-activity-log', { site: this.props.siteRawUrl } ) } compact rna > - <ExternalLink>{ __( 'View your site activity', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-activity-log', { + site: this.props.siteRawUrl, + } ) } + > + { __( 'View your site activity', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> @@ -478,13 +492,16 @@ class MyPlanBody extends React.Component { { this.props.isModuleActivated( 'wordads' ) ? ( <Button onClick={ this.handleButtonClickForTracking( 'view_earnings' ) } - href={ getRedirectUrl( 'wpcom-ads-earnings', { - site: this.props.siteRawUrl, - } ) } compact rna > - <ExternalLink>{ __( 'View your earnings', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'wpcom-ads-earnings', { + site: this.props.siteRawUrl, + } ) } + > + { __( 'View your earnings', 'jetpack' ) } + </ExternalLink> </Button> ) : ( <Button @@ -526,13 +543,14 @@ class MyPlanBody extends React.Component { { this.props.isModuleActivated( 'google-analytics' ) ? ( <Button onClick={ this.handleButtonClickForTracking( 'configure_ga' ) } - href={ getRedirectUrl( 'calypso-marketing-traffic', { - site: this.props.siteRawUrl, - } ) } compact rna > - <ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-marketing-traffic', { + site: this.props.siteRawUrl, + } ) } + > { __( 'Configure Google Analytics', 'jetpack' ) } </ExternalLink> </Button> @@ -573,13 +591,16 @@ class MyPlanBody extends React.Component { { this.props.isModuleActivated( 'publicize' ) ? ( <Button onClick={ this.handleButtonClickForTracking( 'schedule_posts' ) } - href={ getRedirectUrl( 'calypso-edit-posts', { - site: this.props.siteRawUrl, - } ) } compact rna > - <ExternalLink>{ __( 'Schedule posts', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-edit-posts', { + site: this.props.siteRawUrl, + } ) } + > + { __( 'Schedule posts', 'jetpack' ) } + </ExternalLink> </Button> ) : ( <Button @@ -635,13 +656,16 @@ class MyPlanBody extends React.Component { </p> <Button onClick={ this.handleButtonClickForTracking( 'free_security' ) } - href={ getRedirectUrl( 'calypso-settings-security', { - site: this.props.siteRawUrl, - } ) } compact rna > - <ExternalLink>{ __( 'Set up your site security', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-settings-security', { + site: this.props.siteRawUrl, + } ) } + > + { __( 'Set up your site security', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> @@ -693,13 +717,12 @@ class MyPlanBody extends React.Component { 'jetpack' ) } </p> - <Button - onClick={ this.handleButtonClickForTracking( 'free_themes' ) } - href={ getRedirectUrl( 'calypso-themes', { site: this.props.siteRawUrl } ) } - compact - rna - > - <ExternalLink>{ __( 'Explore themes', 'jetpack' ) }</ExternalLink> + <Button onClick={ this.handleButtonClickForTracking( 'free_themes' ) } compact rna> + <ExternalLink + href={ getRedirectUrl( 'calypso-themes', { site: this.props.siteRawUrl } ) } + > + { __( 'Explore themes', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> @@ -729,13 +752,16 @@ class MyPlanBody extends React.Component { { this.props.isModuleActivated( 'publicize' ) ? ( <Button onClick={ this.handleButtonClickForTracking( 'free_sharing' ) } - href={ getRedirectUrl( 'calypso-marketing-connections', { - site: this.props.siteRawUrl, - } ) } compact rna > - <ExternalLink>{ __( 'Start sharing', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-marketing-connections', { + site: this.props.siteRawUrl, + } ) } + > + { __( 'Start sharing', 'jetpack' ) } + </ExternalLink> </Button> ) : ( <Button @@ -774,11 +800,16 @@ class MyPlanBody extends React.Component { </p> <Button onClick={ this.handleButtonClickForTracking( 'view_site_activity' ) } - href={ getRedirectUrl( 'calypso-activity-log', { site: this.props.siteRawUrl } ) } compact rna > - <ExternalLink>{ __( 'View your site activity', 'jetpack' ) }</ExternalLink> + <ExternalLink + href={ getRedirectUrl( 'calypso-activity-log', { + site: this.props.siteRawUrl, + } ) } + > + { __( 'View your site activity', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> @@ -803,11 +834,12 @@ class MyPlanBody extends React.Component { </p> <Button onClick={ this.handleButtonClickForTracking( 'free_support_documentation' ) } - href={ getRedirectUrl( 'jetpack-support' ) } compact rna > - <ExternalLink>{ __( 'Search support docs', 'jetpack' ) }</ExternalLink> + <ExternalLink href={ getRedirectUrl( 'jetpack-support' ) }> + { __( 'Search support docs', 'jetpack' ) } + </ExternalLink> </Button> </div> </div> diff --git a/projects/plugins/jetpack/_inc/client/my-plan/my-plan-card/index.jsx b/projects/plugins/jetpack/_inc/client/my-plan/my-plan-card/index.jsx index 4b5b1e2eb62ea..93f150f1f8cdc 100644 --- a/projects/plugins/jetpack/_inc/client/my-plan/my-plan-card/index.jsx +++ b/projects/plugins/jetpack/_inc/client/my-plan/my-plan-card/index.jsx @@ -27,7 +27,7 @@ const MyPlanCard = ( { <div className={ cardClassNames }> <div className="my-plan-card__primary"> <div className="my-plan-card__icon"> - { productSlug && <PlanIcon plan={ productSlug } alt={ title } /> } + { productSlug && <PlanIcon plan={ productSlug } alt="" /> } </div> <div className="my-plan-card__header"> { title && <h2 className="my-plan-card__title">{ title }</h2> } diff --git a/projects/plugins/jetpack/_inc/client/my-plan/my-plan-header/index.js b/projects/plugins/jetpack/_inc/client/my-plan/my-plan-header/index.js index 914a9af1b1203..04370421b7dad 100644 --- a/projects/plugins/jetpack/_inc/client/my-plan/my-plan-header/index.js +++ b/projects/plugins/jetpack/_inc/client/my-plan/my-plan-header/index.js @@ -566,13 +566,10 @@ class MyPlanHeader extends React.Component { } ) } > { showPurchasesLink && ( - <Button - onClick={ this.trackAllPurchasesClick } - href={ getRedirectUrl( 'calypso-purchases' ) } - compact - rna - > - <ExternalLink>{ __( 'View all purchases', 'jetpack' ) }</ExternalLink> + <Button onClick={ this.trackAllPurchasesClick } compact rna> + <ExternalLink href={ getRedirectUrl( 'calypso-purchases' ) }> + { __( 'View all purchases', 'jetpack' ) } + </ExternalLink> </Button> ) } diff --git a/projects/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php b/projects/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php index 8efa287f61368..09814cfc52d05 100644 --- a/projects/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php +++ b/projects/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php @@ -281,7 +281,7 @@ public static function comment_added( $comment_id, $comment_approved, $commentda $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' ); $has_anti_spam_product = count( array_intersect( array( 'jetpack_anti_spam', 'jetpack_anti_spam_monthly' ), $site_products ) ) > 0; - if ( Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) { + if ( Jetpack_Plan::supports( 'akismet' ) || Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) { return; } diff --git a/projects/plugins/jetpack/changelog/update-forms-lead-capture-atomic b/projects/plugins/jetpack/changelog/add-contact-form-accessible-name similarity index 100% rename from projects/plugins/jetpack/changelog/update-forms-lead-capture-atomic rename to projects/plugins/jetpack/changelog/add-contact-form-accessible-name diff --git a/projects/plugins/jetpack/changelog/add-dont-email-to-subs-toggle b/projects/plugins/jetpack/changelog/add-dont-email-to-subs-toggle deleted file mode 100644 index 9dfc0770aedae..0000000000000 --- a/projects/plugins/jetpack/changelog/add-dont-email-to-subs-toggle +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: enhancement - -Subscriptions: adds toggle to disable email sending diff --git a/projects/plugins/boost/changelog/fix-z-index b/projects/plugins/jetpack/changelog/add-fix-typo similarity index 64% rename from projects/plugins/boost/changelog/fix-z-index rename to projects/plugins/jetpack/changelog/add-fix-typo index d95a7ef42d8cf..1ef8afea050a2 100644 --- a/projects/plugins/boost/changelog/fix-z-index +++ b/projects/plugins/jetpack/changelog/add-fix-typo @@ -1,4 +1,4 @@ Significance: patch -Type: fixed +Type: other diff --git a/projects/plugins/jetpack/changelog/add-flag-for-expired-plans b/projects/plugins/jetpack/changelog/add-flag-for-expired-plans deleted file mode 100644 index 527f9b20f83ac..0000000000000 --- a/projects/plugins/jetpack/changelog/add-flag-for-expired-plans +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: other - -Add a flag for sites that have upgraded from the ecommerce trial diff --git a/projects/plugins/jetpack/changelog/add-stats-passing-utm-parameters b/projects/plugins/jetpack/changelog/add-stats-passing-utm-parameters new file mode 100644 index 0000000000000..a1c1831fa1ef7 --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-stats-passing-utm-parameters @@ -0,0 +1,5 @@ +Significance: patch +Type: other +Comment: Updated composer.lock. + + diff --git a/projects/plugins/jetpack/changelog/boost-fix-importmap-deferral b/projects/plugins/jetpack/changelog/boost-fix-importmap-deferral new file mode 100644 index 0000000000000..a1c1831fa1ef7 --- /dev/null +++ b/projects/plugins/jetpack/changelog/boost-fix-importmap-deferral @@ -0,0 +1,5 @@ +Significance: patch +Type: other +Comment: Updated composer.lock. + + diff --git a/projects/plugins/jetpack/changelog/fix-admin-plan-icon-alt b/projects/plugins/jetpack/changelog/fix-admin-plan-icon-alt new file mode 100644 index 0000000000000..49e08efd2be83 --- /dev/null +++ b/projects/plugins/jetpack/changelog/fix-admin-plan-icon-alt @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +Admin Page: remove alt attribute from decorative icon. diff --git a/projects/plugins/jetpack/changelog/fix-correct-subs-count-with-paywall b/projects/plugins/jetpack/changelog/fix-correct-subs-count-with-paywall deleted file mode 100644 index a2cd9becfaefa..0000000000000 --- a/projects/plugins/jetpack/changelog/fix-correct-subs-count-with-paywall +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: bugfix - -Subscribers: pre/post-publish panel, correct subs count with paywall diff --git a/projects/plugins/jetpack/changelog/fix-like-block-disabled-case b/projects/plugins/jetpack/changelog/fix-like-block-disabled-case deleted file mode 100644 index 3c5765ea02b1c..0000000000000 --- a/projects/plugins/jetpack/changelog/fix-like-block-disabled-case +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: other - -Like block (beta): Make sure the block is not available when the Likes module or Likes / Reblog site options are disabled diff --git a/projects/plugins/jetpack/changelog/init-release-cycle b/projects/plugins/jetpack/changelog/init-release-cycle index 06b955f2f3d7b..6b09410041630 100644 --- a/projects/plugins/jetpack/changelog/init-release-cycle +++ b/projects/plugins/jetpack/changelog/init-release-cycle @@ -1,5 +1,5 @@ Significance: patch Type: other -Comment: Init 13.0-a.4 +Comment: Init 13.0-a.8 diff --git a/projects/plugins/jetpack/changelog/refactor-memberships-checkout-modal b/projects/plugins/jetpack/changelog/refactor-memberships-checkout-modal deleted file mode 100644 index a9cbe888c6ace..0000000000000 --- a/projects/plugins/jetpack/changelog/refactor-memberships-checkout-modal +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: other - -Refactor checkout modal to be more performant. diff --git a/projects/plugins/jetpack/changelog/remove-like-block-special-treatment b/projects/plugins/jetpack/changelog/remove-like-block-special-treatment deleted file mode 100644 index 98aa6794772fe..0000000000000 --- a/projects/plugins/jetpack/changelog/remove-like-block-special-treatment +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: other - -Like block (beta): remove the condition that decided whether to display Like block or Like widget diff --git a/projects/plugins/jetpack/changelog/update-newsletter-post-publish-initially-closed b/projects/plugins/jetpack/changelog/update-newsletter-post-publish-initially-closed deleted file mode 100644 index 0ba619ebccf52..0000000000000 --- a/projects/plugins/jetpack/changelog/update-newsletter-post-publish-initially-closed +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: other - -Newsletter post-publish panel: closed initially diff --git a/projects/plugins/jetpack/class.jetpack-admin.php b/projects/plugins/jetpack/class.jetpack-admin.php index f3bb3ea380a13..18ed1867c3a79 100644 --- a/projects/plugins/jetpack/class.jetpack-admin.php +++ b/projects/plugins/jetpack/class.jetpack-admin.php @@ -82,7 +82,7 @@ private function __construct() { $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' ); $has_anti_spam_product = count( array_intersect( array( 'jetpack_anti_spam', 'jetpack_anti_spam_monthly' ), $site_products ) ) > 0; - if ( Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) { + if ( Jetpack_Plan::supports( 'akismet' ) || Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) { // Prevent Akismet from adding a menu item. add_action( 'admin_menu', diff --git a/projects/plugins/jetpack/composer.json b/projects/plugins/jetpack/composer.json index af1530aaa72cb..6670052cd62aa 100644 --- a/projects/plugins/jetpack/composer.json +++ b/projects/plugins/jetpack/composer.json @@ -103,7 +103,7 @@ "platform": { "ext-intl": "0.0.0" }, - "autoloader-suffix": "f11009ded9fc4592b6a05b61ce272b3c_jetpackⓥ13_0_a_4", + "autoloader-suffix": "f11009ded9fc4592b6a05b61ce272b3c_jetpackⓥ13_0_a_8", "allow-plugins": { "automattic/jetpack-autoloader": true, "automattic/jetpack-composer-plugin": true diff --git a/projects/plugins/jetpack/composer.lock b/projects/plugins/jetpack/composer.lock index d84923ed64d7f..ae80500e7d77a 100644 --- a/projects/plugins/jetpack/composer.lock +++ b/projects/plugins/jetpack/composer.lock @@ -1167,7 +1167,7 @@ "dist": { "type": "path", "url": "../../packages/forms", - "reference": "91cdedeae6c8fc54fb18196d9465098efca69975" + "reference": "0d1ea60cf2c7a86d515ae071330395de358d3791" }, "require": { "automattic/jetpack-assets": "@dev", @@ -1193,7 +1193,7 @@ "link-template": "https://github.com/automattic/jetpack-forms/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "0.27.x-dev" + "dev-trunk": "0.29.x-dev" }, "textdomain": "jetpack-forms", "version-constants": { @@ -2519,7 +2519,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -2551,7 +2551,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json b/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json index 9e5713e2db039..4eac3cf686345 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json @@ -50,6 +50,14 @@ "customSystemPrompt": { "type": "string", "default": "" + }, + "userPrompt": { + "type": "string", + "default": "" + }, + "requestingState": { + "type": "string", + "default": "init" } }, "example": { diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/toolbar-controls/index.js b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/toolbar-controls/index.js index dc13c790e58c2..cea0738ed0816 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/toolbar-controls/index.js +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/toolbar-controls/index.js @@ -101,9 +101,9 @@ const ToolbarControls = ( { </> ) } - { ( showRetry || contentIsLoaded ) && ( + { ( showRetry || handleTryAgain ) && ( <ToolbarGroup> - { ! showRetry && contentIsLoaded && ( + { ! showRetry && contentIsLoaded && handleTryAgain && ( <ToolbarButton onClick={ handleTryAgain }> { __( 'Try Again', 'jetpack' ) } </ToolbarButton> diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js b/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js index 6d2c8880e0946..674dbfba58bd2 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js @@ -32,7 +32,6 @@ import { USAGE_PANEL_PLACEMENT_BLOCK_SETTINGS_SIDEBAR } from '../../plugins/ai-a import ConnectPrompt from './components/connect-prompt'; import FeedbackControl from './components/feedback-control'; import ImageWithSelect from './components/image-with-select'; -import { promptTemplates } from './components/prompt-templates-control'; import ToolbarControls from './components/toolbar-controls'; import UpgradePrompt from './components/upgrade-prompt'; import { getStoreBlockId } from './extensions/ai-assistant/with-ai-assistant'; @@ -52,7 +51,6 @@ const isPlaygroundVisible = window?.Jetpack_Editor_Initial_State?.[ 'ai-assistant' ]?.[ 'is-playground-visible' ]; export default function AIAssistantEdit( { attributes, setAttributes, clientId, isSelected } ) { - const [ userPrompt, setUserPrompt ] = useState(); const [ errorData, setError ] = useState( {} ); const [ loadingImages, setLoadingImages ] = useState( false ); const [ resultImages, setResultImages ] = useState( [] ); @@ -125,8 +123,9 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, content: attributes.content, setError, tracks, - userPrompt, + userPrompt: attributes.userPrompt, requireUpgrade, + requestingState: attributes.requestingState, } ); const connected = isUserConnected(); @@ -201,23 +200,14 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, replaceBlocks( clientId, storedInnerBlocks ); }, [ initialContent, clientId, replaceBlocks, getBlock, attributes?.useGutenbergSyntax ] ); - const [ promptPlaceholder, setPromptPlaceholder ] = useState( '' ); - const [ currentIndex, setCurrentIndex ] = useState( 0 ); - - // Loop through placeholder prompts for a nice UX effect. useEffect( () => { - const interval = setInterval( () => { - if ( currentIndex < promptTemplates.length ) { - setPromptPlaceholder( promptTemplates[ currentIndex ].label ); - setCurrentIndex( prevIndex => prevIndex + 1 ); - } else { - clearInterval( interval ); - setPromptPlaceholder( __( 'Ask Jetpack AI', 'jetpack' ) ); - } - }, 1600 ); + // we don't want to store "half way" states + if ( ! [ 'init', 'done' ].includes( requestingState ) ) { + return; + } - return () => clearInterval( interval ); - }, [ promptPlaceholder, currentIndex ] ); + setAttributes( { requestingState } ); + }, [ requestingState, setAttributes ] ); const saveImage = async image => { if ( loadingImages ) { @@ -311,7 +301,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, const handleChange = value => { setErrorDismissed( true ); - setUserPrompt( value ); + setAttributes( { userPrompt: value } ); }; const handleSend = () => { @@ -335,7 +325,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, * - Create blocks from HTML code */ const HTML = markdownConverter - .render( attributes.content ) + .render( attributes.content || '' ) // Fix list indentation .replace( /<li>\s+<p>/g, '<li>' ) .replace( /<\/p>\s+<\/li>/g, '</li>' ); @@ -362,7 +352,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, const handleAcceptTitle = () => { if ( isInBlockEditor ) { - editPost( { title: attributes.content.trim() } ); + editPost( { title: attributes.content ? attributes.content.trim() : '' } ); removeBlock( clientId ); } else { handleAcceptContent(); @@ -387,7 +377,9 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, setError( {} ); getImagesFromOpenAI( - userPrompt.trim() === '' ? __( 'What would you like to see?', 'jetpack' ) : userPrompt, + attributes.userPrompt.trim() === '' + ? __( 'What would you like to see?', 'jetpack' ) + : attributes.userPrompt, setAttributes, setLoadingImages, setResultImages, @@ -415,6 +407,8 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, const innerBlocks = useInnerBlocksProps( blockProps ); + const promptPlaceholder = __( 'Ask Jetpack AI…', 'jetpack' ); + const promptPlaceholderWithSamples = __( 'Write about… Make a table for…', 'jetpack' ); return ( <KeyboardShortcuts bindGlobal @@ -532,7 +526,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, handleAcceptTitle={ handleAcceptTitle } handleGetSuggestion={ handleGetSuggestion } handleImageRequest={ handleImageRequest } - handleTryAgain={ handleTryAgain } + handleTryAgain={ null } showRetry={ showRetry } contentBefore={ contentBefore } hasPostTitle={ !! postTitle?.length } @@ -548,12 +542,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, // Focus the text area userPromptInput.focus(); - // Add a typing effect in the text area - for ( let i = 0; i < prompt.length; i++ ) { - setTimeout( () => { - setUserPrompt( prompt.slice( 0, i + 1 ) ); - }, 25 * i ); - } + setAttributes( { userPrompt: prompt } ); } } recordEvent={ tracks.recordEvent } isGeneratingTitle={ isGeneratingTitle } @@ -562,19 +551,20 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, <AIControl ref={ aiControlRef } disabled={ requireUpgrade || ! connected } - value={ userPrompt } - placeholder={ promptPlaceholder || __( 'Ask Jetpack AI', 'jetpack' ) } + value={ attributes.userPrompt } + placeholder={ attributes?.content ? promptPlaceholder : promptPlaceholderWithSamples } onChange={ handleChange } onSend={ handleSend } onStop={ handleStopSuggestion } onAccept={ handleAccept } + onDiscard={ handleTryAgain } state={ requestingState } isTransparent={ requireUpgrade || ! connected } showButtonLabels={ ! isMobileViewport } - showAccept={ contentIsLoaded && ! isWaitingState } + showAccept={ requestingState !== 'init' && contentIsLoaded && ! isWaitingState } acceptLabel={ acceptLabel } - showClearButton={ ! isWaitingState } showGuideLine={ contentIsLoaded } + showRemove={ attributes?.content?.length > 0 } /> { ! loadingImages && resultImages.length > 0 && ( diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/index.tsx index 48532a4eb3f65..11cafff9fe237 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/index.tsx @@ -230,42 +230,44 @@ export default function AiAssistantBar( { // Assistant bar component. const AiAssistantBarComponent = ( - <KeyboardShortcuts - bindGlobal - shortcuts={ { - esc: () => { - if ( [ 'requesting', 'suggesting' ].includes( requestingState ) ) { - handleStopSuggestion(); - } - }, - } } - > - <div - ref={ wrapperRef } - className={ classNames( 'jetpack-ai-assistant__bar', { - [ className ]: className, - 'is-fixed': isAssistantBarFixed, - 'is-mobile-mode': isMobileMode, - } ) } - tabIndex={ -1 } + <div className="jetpack-ai-assistant__bar-wrapper"> + <KeyboardShortcuts + bindGlobal + shortcuts={ { + esc: () => { + if ( [ 'requesting', 'suggesting' ].includes( requestingState ) ) { + handleStopSuggestion(); + } + }, + } } > - { siteRequireUpgrade && <UpgradePrompt /> } - { ! connected && <ConnectPrompt /> } - <AIControl - ref={ inputRef } - disabled={ siteRequireUpgrade || ! connected } - value={ isLoading ? undefined : inputValue } - placeholder={ isLoading ? loadingPlaceholder : placeholder } - onChange={ setInputValue } - onSend={ handleSend } - onStop={ handleStopSuggestion } - state={ requestingState } - isTransparent={ siteRequireUpgrade || ! connected } - showButtonLabels={ ! isMobileMode } - showGuideLine={ showGuideLine } - /> - </div> - </KeyboardShortcuts> + <div + ref={ wrapperRef } + className={ classNames( 'jetpack-ai-assistant__bar', { + [ className ]: className, + 'is-fixed': isAssistantBarFixed, + 'is-mobile-mode': isMobileMode, + } ) } + tabIndex={ -1 } + > + { siteRequireUpgrade && <UpgradePrompt /> } + { ! connected && <ConnectPrompt /> } + <AIControl + ref={ inputRef } + disabled={ siteRequireUpgrade || ! connected } + value={ inputValue } + placeholder={ isLoading ? loadingPlaceholder : placeholder } + onChange={ setInputValue } + onSend={ handleSend } + onStop={ handleStopSuggestion } + state={ requestingState } + isTransparent={ siteRequireUpgrade || ! connected } + showButtonLabels={ ! isMobileMode } + showGuideLine={ showGuideLine } + /> + </div> + </KeyboardShortcuts> + </div> ); // Check if the Assistant bar should be rendered in the Assistant anchor (fixed mode) diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/style.scss b/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/style.scss index 8141a6c487a6f..9b6453879e6e2 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/style.scss +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-bar/style.scss @@ -1,16 +1,16 @@ .jetpack-ai-assistant__bar { - width: 100%; &:not(.is-fixed) { position: relative; z-index: 30; - margin-top: 10px; - background-color: white; } &.is-fixed { - border-bottom: 1px solid #e0e0e0; + .jetpack-components-ai-control__container-wrapper { + position: relative; + bottom: 0; + } .jetpack-components-ai-control__container { border-radius: 0; @@ -29,4 +29,15 @@ display: block; position: sticky; z-index: 31; + + .jetpack-ai-assistant__bar-wrapper { + position: relative; + bottom: 0; + } +} + +.jetpack-ai-assistant__bar-wrapper { + position: sticky; + z-index: 30; + bottom: 16px; } diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-toolbar-button/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-toolbar-button/index.tsx index 9cffc0ba89d41..08ee47fca6549 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-toolbar-button/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/extensions/jetpack-contact-form/components/ai-assistant-toolbar-button/index.tsx @@ -69,7 +69,10 @@ export default function AiAssistantToolbarButton( { let slot = toolbar.parentElement?.querySelector( `.${ AI_ASSISTANT_BAR_SLOT_CLASS }` ) as HTMLElement; + if ( slot ) { + // always move the slot right after the toolbar. + toolbar.after( slot ); return setAnchor( slot ); } @@ -81,11 +84,11 @@ export default function AiAssistantToolbarButton( { slot.setAttribute( 'aria-label', __( 'AI Assistant', 'jetpack' ) ); slot.setAttribute( 'aria-orientation', 'horizontal' ); slot.className = AI_ASSISTANT_BAR_SLOT_CLASS; - toolbar.after( slot ); // Set the top position based on the toolbar height. const toolbarHeight = toolbar.offsetHeight; slot.style.top = `${ toolbarHeight }px`; + toolbar.after( slot ); // Set the anchor where the Assistant Bar will be rendered. setAnchor( slot ); diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-suggestions-from-openai/index.js b/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-suggestions-from-openai/index.js index 6edc422c3708b..2b1db23bb016e 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-suggestions-from-openai/index.js +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-suggestions-from-openai/index.js @@ -32,6 +32,7 @@ const useSuggestionsFromOpenAI = ( { onUnclearPrompt, onModeration, requireUpgrade, + requestingState, } ) => { const [ isLoadingCategories, setIsLoadingCategories ] = useState( false ); const [ isLoadingCompletion, setIsLoadingCompletion ] = useState( false ); @@ -41,7 +42,7 @@ const useSuggestionsFromOpenAI = ( { const { updateBlockAttributes } = useDispatch( 'core/block-editor' ); const { dequeueAiAssistantFeatureAyncRequest, setAiAssistantFeatureRequireUpgrade } = useDispatch( 'wordpress-com/plans' ); - const [ requestingState, setRequestingState ] = useState( 'init' ); + const [ requestState, setRequestState ] = useState( requestingState || 'init' ); const source = useRef(); // Let's grab post data so that we can do something smart. @@ -139,7 +140,7 @@ const useSuggestionsFromOpenAI = ( { * let's set the error and return an `undefined` event source. */ if ( requireUpgrade ) { - setRequestingState( 'error' ); + setRequestState( 'error' ); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); setShowRetry( false ); @@ -226,7 +227,7 @@ const useSuggestionsFromOpenAI = ( { debugPrompt( '(%s/%s) %o\n%s', i + 1, prompt.length, `[${ role }]`, promptContent ) ); - setRequestingState( 'requesting' ); + setRequestState( 'requesting' ); source.current = await askQuestion( prompt, { postId, @@ -235,7 +236,7 @@ const useSuggestionsFromOpenAI = ( { functions: options?.functions, } ); - setRequestingState( 'suggesting' ); + setRequestState( 'suggesting' ); } catch ( err ) { if ( err.message ) { setError( { message: err.message, code: err?.code || 'unknown', status: 'error' } ); @@ -309,7 +310,7 @@ const useSuggestionsFromOpenAI = ( { const onDone = e => { const { detail } = e; - setRequestingState( 'done' ); + setRequestState( 'done' ); // Remove the delimiter from the suggestion. const assistantResponse = detail.replaceAll( delimiter, '' ); @@ -355,7 +356,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorUnclearPrompt = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -368,7 +369,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorContextTooLarge = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -384,7 +385,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorNetwork = ( { detail: error } ) => { - setRequestingState( 'error' ); + setRequestState( 'error' ); const { name: errorName, message: errorMessage } = error; if ( errorName === 'TypeError' && errorMessage === 'Failed to fetch' ) { /* @@ -430,7 +431,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorServiceUnavailable = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -446,7 +447,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorQuotaExceeded = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -463,7 +464,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorModeration = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -527,7 +528,7 @@ const useSuggestionsFromOpenAI = ( { onSuggestionDone?.(); // Set requesting state to done since the suggestion stopped. - setRequestingState( 'done' ); + setRequestState( 'done' ); } return { @@ -540,7 +541,7 @@ const useSuggestionsFromOpenAI = ( { postTitle: currentPostTitle, contentBefore: getPartialContentToBlock( clientId ), wholeContent: getContentFromBlocks(), - requestingState, + requestingState: requestState, getSuggestionFromOpenAI: getStreamedSuggestionFromOpenAI, stopSuggestion, diff --git a/projects/plugins/jetpack/extensions/blocks/like/like.php b/projects/plugins/jetpack/extensions/blocks/like/like.php index 5c31296c74247..340b5b9a77407 100644 --- a/projects/plugins/jetpack/extensions/blocks/like/like.php +++ b/projects/plugins/jetpack/extensions/blocks/like/like.php @@ -9,6 +9,7 @@ namespace Automattic\Jetpack\Extensions\Like; +use Automattic\Jetpack\Assets; use Automattic\Jetpack\Blocks; use Jetpack_Gutenberg; @@ -20,15 +21,6 @@ function register_block() { $is_wpcom = defined( 'IS_WPCOM' ) && IS_WPCOM; - $is_likes_module_inactive = ! \Jetpack::is_module_active( 'likes' ); - $is_disabled_on_wpcom = $is_wpcom && get_option( 'disabled_likes' ) && get_option( 'disabled_reblogs' ); - $is_disabled_on_non_wpcom = ! $is_wpcom && get_option( 'disabled_likes' ); - $disable_like_block = $is_likes_module_inactive || $is_disabled_on_wpcom || $is_disabled_on_non_wpcom; - - if ( $disable_like_block ) { - return; - } - Blocks::jetpack_register_block( __DIR__, array( @@ -61,6 +53,10 @@ function render_block( $attr, $content, $block ) { $post_id = $block->context['postId']; $title = esc_html__( 'Like or Reblog', 'jetpack' ); + if ( ! $post_id ) { + return; + } + /** * Enable an alternate Likes layout. * @@ -72,6 +68,20 @@ function render_block( $attr, $content, $block ) { */ $new_layout = apply_filters( 'likes_new_layout', true ) ? '&amp;n=1' : ''; + static $main_iframe_added = false; + + if ( ! $main_iframe_added && is_legacy_likes_disabled() ) { + if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { + add_action( 'wp_footer', array( 'Jetpack_Likes', 'likes_master' ), 21 ); + } else { + require_once JETPACK__PLUGIN_DIR . 'modules/likes.php'; + add_action( 'wp_footer', 'jetpack_likes_master_iframe', 21 ); + } + wp_enqueue_script( 'jetpack_likes_queuehandler' ); + wp_enqueue_style( 'jetpack_likes' ); + $main_iframe_added = true; + } + if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { $blog_id = get_current_blog_id(); $bloginfo = get_blog_details( (int) $blog_id ); @@ -106,7 +116,6 @@ function render_block( $attr, $content, $block ) { . "<div class='likes-widget-placeholder post-likes-widget-placeholder' style='height: 55px;'><span class='button'><span>" . esc_html__( 'Like', 'jetpack' ) . "</span></span> <span class='loading'>" . esc_html__( 'Loading...', 'jetpack' ) . '</span></div>' . "<span class='sd-text-color'></span><a class='sd-link-color'></a>" . '</div>'; - return sprintf( '<div class="%1$s">%2$s</div>', esc_attr( Blocks::classes( Blocks::get_block_feature( __DIR__ ), $attr ) ), @@ -115,13 +124,9 @@ function render_block( $attr, $content, $block ) { } /** - * Add the initial state for the Like block. + * Add the initial state for the Like block in the editor */ function add_like_block_data() { - if ( ! is_admin() ) { - return; - } - if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { $blog_id = get_current_blog_id(); } else { @@ -138,4 +143,50 @@ function add_like_block_data() { 'before' ); } -add_action( 'enqueue_block_assets', __NAMESPACE__ . '\add_like_block_data' ); + +add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\add_like_block_data' ); + +/** + * Helper function to determine whether the Like module has been disabled + */ +function is_legacy_likes_disabled() { + $is_wpcom = defined( 'IS_WPCOM' ) && IS_WPCOM; + $is_likes_module_inactive = ! \Jetpack::is_module_active( 'likes' ); + $is_disabled_on_wpcom = $is_wpcom && get_option( 'disabled_likes' ) && get_option( 'disabled_reblogs' ); + $is_disabled_on_non_wpcom = ! $is_wpcom && get_option( 'disabled_likes' ); + + return $is_likes_module_inactive || $is_disabled_on_wpcom || $is_disabled_on_non_wpcom; +} + +/** + * Registers and enqueues script and style for Jetpack Likes. + * + * This function conditionally registers and enqueues the Jetpack Likes + * CSS and JavaScript files based on the environment. It handles both + * WordPress.com and self-hosted WordPress environments. The function + * relies on `IS_WPCOM` to determine the environment and uses different + * paths for script and style files accordingly. + * + * @return void Early return if legacy likes are not disabled. + */ +function register_script_and_style() { + if ( ! is_legacy_likes_disabled() ) { + return; + } + + if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { + $style_url = content_url( 'mu-plugins/likes/jetpack-likes.css' ); + $script_url = content_url( 'mu-plugins/likes/queuehandler.js' ); + } else { + $style_url = plugins_url( 'modules/likes/style.css', dirname( __DIR__, 2 ) ); + $script_url = Assets::get_file_url_for_environment( + '_inc/build/likes/queuehandler.min.js', + 'modules/likes/queuehandler.js' + ); + } + + wp_register_style( 'jetpack_likes', $style_url, array(), JETPACK__VERSION ); + wp_register_script( 'jetpack_likes_queuehandler', $script_url, array(), JETPACK__VERSION, true ); +} + +add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\register_script_and_style' ); diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/access-check.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/access-check.php index 98bdebdb123a9..b0ca9c6e95866 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/access-check.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/access-check.php @@ -7,7 +7,7 @@ namespace Automattic\Jetpack\Extensions\Premium_Content; -use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; require_once __DIR__ . '/subscription-service/include.php'; @@ -99,7 +99,7 @@ function current_visitor_can_access( $attributes, $block ) { } $paywall = subscription_service(); - $access_level = Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS; // Only paid subscribers should be granted access to the premium content + $access_level = Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS; // Only paid subscribers should be granted access to the premium content $tier_ids = \Jetpack_Memberships::get_all_newsletter_plan_ids(); $tier_ids = array_intersect( $tier_ids, $selected_plan_ids ); if ( ! empty( $tier_ids ) ) { diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription-service.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-abstract-token-subscription-service.php similarity index 98% rename from projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription-service.php rename to projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-abstract-token-subscription-service.php index 2c125ecd3ded0..6d1d96895d07c 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription-service.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-abstract-token-subscription-service.php @@ -12,11 +12,11 @@ use const Automattic\Jetpack\Extensions\Subscriptions\META_NAME_FOR_POST_TIER_ID_SETTINGS; /** - * Class Token_Subscription_Service + * Class Abstract_Token_Subscription_Service * * @package Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service */ -abstract class Token_Subscription_Service implements Subscription_Service { +abstract class Abstract_Token_Subscription_Service implements Subscription_Service { const JWT_AUTH_TOKEN_COOKIE_NAME = 'jp-premium-content-session'; const DECODE_EXCEPTION_FEATURE = 'memberships'; @@ -167,11 +167,9 @@ public function is_current_user_subscribed() { /** * Returns true if the current authenticated user has a pending subscription to the current site. * - * @return boolean + * @return bool */ - public function is_current_user_pending_subscriber() { - return false; - } + abstract public function is_current_user_pending_subscriber(): bool; /** * Return if the user has access to the content depending on the access level and the user rights diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-jetpack-token-subscription-service.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-jetpack-token-subscription-service.php index 821942bcbd863..f7cde26f40feb 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-jetpack-token-subscription-service.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-jetpack-token-subscription-service.php @@ -16,7 +16,7 @@ * * @package Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service */ -class Jetpack_Token_Subscription_Service extends Token_Subscription_Service { +class Jetpack_Token_Subscription_Service extends Abstract_Token_Subscription_Service { /** * Is the Jetpack_Options class available? @@ -56,10 +56,10 @@ public function get_key() { /** * Returns true if the current authenticated user has a pending subscription to the current site. * - * @return boolean + * @return bool */ - public function is_current_user_pending_subscriber() { + public function is_current_user_pending_subscriber(): bool { - return $this->get_token_property( 'blog_sub' ) === 'pending'; + return self::BLOG_SUB_PENDING === $this->get_token_property( 'blog_sub' ); } } diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription.php deleted file mode 100644 index d9c81e8c5cbf0..0000000000000 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-token-subscription.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php -/** - * Token subscription management. - * - * @package Automattic\Jetpack\Extensions\Premium_Content - */ - -namespace Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service; - -/** - * Class Token_Subscription - * - * @package Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service - */ -class Token_Subscription { - - /** - * End date. - * - * @var string $end_date . - */ - public $end_date = ''; -} diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-unconfigured-subscription-service.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-unconfigured-subscription-service.php index 9b4cb01545c33..7ec96af9e3892 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-unconfigured-subscription-service.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-unconfigured-subscription-service.php @@ -48,10 +48,11 @@ public function visitor_can_view_content( $valid_plan_ids, $access_level ) { /** * is the current user a pending subscriber for the current site? - * - * @return boolean + * + * @return bool */ - public function is_current_user_pending_subscriber() { + public function is_current_user_pending_subscriber(): bool + { return false; } diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-wpcom-online-subscription-service.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-wpcom-online-subscription-service.php index 02cc14f4f8d44..f6b1166e09dbf 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-wpcom-online-subscription-service.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-wpcom-online-subscription-service.php @@ -65,9 +65,9 @@ public function get_subscriber_email() { /** * Returns true if the current authenticated user is subscribed to the current site. * - * @return boolean + * @return bool */ - public function is_current_user_subscribed() { + public function is_current_user_subscribed(): bool { include_once WP_CONTENT_DIR . '/mu-plugins/email-subscriptions/subscriptions.php'; $email = wp_get_current_user()->user_email; $subscriber_object = \Blog_Subscriber::get( $email ); @@ -85,9 +85,9 @@ public function is_current_user_subscribed() { /** * Returns true if the current authenticated user has a pending subscription to the current site. * - * @return boolean + * @return bool */ - public function is_current_user_pending_subscriber() { + public function is_current_user_pending_subscriber(): bool { include_once WP_CONTENT_DIR . '/mu-plugins/email-subscriptions/subscriptions.php'; $email = wp_get_current_user()->user_email; $subscriber_object = \Blog_Subscriber::get( $email ); @@ -96,7 +96,7 @@ public function is_current_user_pending_subscriber() { } $blog_id = $this->get_site_id(); $subscription_status = \Blog_Subscription::get_subscription_status_for_blog( $subscriber_object, $blog_id ); - if ( 'pending' !== $subscription_status ) { + if ( self::BLOG_SUB_PENDING !== $subscription_status ) { return false; } return true; diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/include.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/include.php index 9eb334641c328..26a15a2bdf191 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/include.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/include.php @@ -8,9 +8,8 @@ namespace Automattic\Jetpack\Extensions\Premium_Content; require_once __DIR__ . '/class-jwt.php'; -require_once __DIR__ . '/class-subscription-service.php'; -require_once __DIR__ . '/class-token-subscription.php'; -require_once __DIR__ . '/class-token-subscription-service.php'; +require_once __DIR__ . '/interface-subscription-service.php'; +require_once __DIR__ . '/class-abstract-token-subscription-service.php'; require_once __DIR__ . '/class-jetpack-token-subscription-service.php'; require_once __DIR__ . '/class-wpcom-online-subscription-service.php'; require_once __DIR__ . '/class-wpcom-offline-subscription-service.php'; diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-subscription-service.php b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/interface-subscription-service.php similarity index 91% rename from projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-subscription-service.php rename to projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/interface-subscription-service.php index 704f94a626615..fa6e5bdf50f16 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/class-subscription-service.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/_inc/subscription-service/interface-subscription-service.php @@ -18,7 +18,7 @@ interface Subscription_Service { /** * The subscription service can be used. * - * @return boolean + * @return bool */ public static function available(); @@ -42,18 +42,18 @@ public function initialize(); * can the visitor see the premium content? * * @param array $valid_plan_ids . - * @param string $access_level . + * @param string $access_level . * - * @return boolean + * @return bool */ public function visitor_can_view_content( $valid_plan_ids, $access_level ); /** * Is the current user a pending subscriber for the current site? * - * @return boolean + * @return bool */ - public function is_current_user_pending_subscriber(); + public function is_current_user_pending_subscriber(): bool; /** * The current visitor would like to obtain access. Where do they go? diff --git a/projects/plugins/jetpack/extensions/blocks/premium-content/login-button/login-button.php b/projects/plugins/jetpack/extensions/blocks/premium-content/login-button/login-button.php index 0c22cef701472..01e56ce40161a 100644 --- a/projects/plugins/jetpack/extensions/blocks/premium-content/login-button/login-button.php +++ b/projects/plugins/jetpack/extensions/blocks/premium-content/login-button/login-button.php @@ -8,7 +8,7 @@ namespace Automattic\Jetpack\Extensions\Premium_Content; use Automattic\Jetpack\Blocks; -use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; use Automattic\Jetpack\Status\Host; use Jetpack_Gutenberg; @@ -44,7 +44,7 @@ function render_login_button_block( $attributes, $content ) { return ''; } - $has_auth_cookie = isset( $_COOKIE[ Token_Subscription_Service::JWT_AUTH_TOKEN_COOKIE_NAME ] ); + $has_auth_cookie = isset( $_COOKIE[ Abstract_Token_Subscription_Service::JWT_AUTH_TOKEN_COOKIE_NAME ] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $has_token_parameter = isset( $_GET['token'] ); diff --git a/projects/plugins/jetpack/extensions/blocks/sharing-button/sharing-button.php b/projects/plugins/jetpack/extensions/blocks/sharing-button/sharing-button.php index e10d96d2c109a..0896990ed8773 100644 --- a/projects/plugins/jetpack/extensions/blocks/sharing-button/sharing-button.php +++ b/projects/plugins/jetpack/extensions/blocks/sharing-button/sharing-button.php @@ -42,18 +42,18 @@ function render_block( $attr, $content, $block ) { $post_id = $block->context['postId']; $title = $attr['label'] ?? $attr['service']; - $style_type = $block->context['styleType']; - $style = 'style-' . $style_type; - $data_shared = 'sharing-' . $attr['service'] . '-' . $post_id . $attr['service']; - $query = 'share=' . $attr['service'] . '&nb=1'; + $style_type = $block->context['styleType']; + $style = 'style-' . $style_type; + $query = 'share=' . $attr['service'] . '&nb=1'; + + $data_shared = 'sharing-' . $attr['service'] . '-' . $post_id; $services = get_services(); $service = new $services[ $attr['service'] ]( $attr['service'], array() ); $link_props = $service->get_link( $post, $query, $data_shared ); - $link_url = $link_props['url']; - - $icon = get_social_logo( $attr['service'] ); + $link_url = $link_props['url']; + $icon = get_social_logo( $attr['service'] ); $sharing_link_class = 'jetpack-sharing-button__button ' . $style . ' share-' . $attr['service']; $link_aria_label = sprintf( @@ -65,9 +65,10 @@ function render_block( $attr, $content, $block ) { Jetpack_Gutenberg::load_assets_as_required( __DIR__ ); $component = '<li class="jetpack-sharing-button__list-item">'; - $component .= '<a rel="nofollow noopener noreferrer" class="' . $sharing_link_class . '" href="' . $link_url . '" target="_blank" data-shared="' . $data_shared . '" aria-label="' . $link_aria_label . '" primary>'; + $component .= '<a rel="nofollow noopener noreferrer" class="' . esc_attr( $sharing_link_class ) . '" href="' . esc_attr( $link_url ) . '" target="_blank" '; + $component .= 'data-service="' . esc_attr( $attr['service'] ) . '" data-shared="' . esc_attr( $data_shared ) . '" aria-label="' . esc_attr( $link_aria_label ) . '" primary>'; $component .= $icon; - $component .= '<span class="jetpack-sharing-button__service-label" aria-hidden="true">' . $title . '</span>'; + $component .= '<span class="jetpack-sharing-button__service-label" aria-hidden="true">' . esc_html( $title ) . '</span>'; $component .= '</a>'; $component .= '</li>'; diff --git a/projects/plugins/jetpack/extensions/blocks/sharing-buttons/save.js b/projects/plugins/jetpack/extensions/blocks/sharing-buttons/save.js index cf4a6979b550e..97a358e3e539c 100644 --- a/projects/plugins/jetpack/extensions/blocks/sharing-buttons/save.js +++ b/projects/plugins/jetpack/extensions/blocks/sharing-buttons/save.js @@ -2,8 +2,9 @@ import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor'; export default function save() { const className = 'jetpack-sharing-buttons__services-list'; + const id = 'jetpack-sharing-serivces-list'; const blockProps = useBlockProps.save( { className } ); const innerBlocksProps = useInnerBlocksProps.save( blockProps ); - return <ul { ...innerBlocksProps } />; + return <ul { ...innerBlocksProps } id={ id } />; } diff --git a/projects/plugins/jetpack/extensions/blocks/sharing-buttons/view.js b/projects/plugins/jetpack/extensions/blocks/sharing-buttons/view.js index e5ff89260974b..35dfcd9a0cfff 100644 --- a/projects/plugins/jetpack/extensions/blocks/sharing-buttons/view.js +++ b/projects/plugins/jetpack/extensions/blocks/sharing-buttons/view.js @@ -1,38 +1,46 @@ +import domReady from '@wordpress/dom-ready'; import './style.scss'; -const services = window?.jetpack_sharing_buttons_services || []; -let windowOpen; - -( function () { - services.forEach( service => { - document.querySelectorAll( `a.share-${ service }` ).forEach( link => { - link.addEventListener( 'click', event => { - if ( service === 'mail' ) { - return; - } - event.preventDefault(); - event.stopPropagation(); - - if ( service === 'print' ) { - window.print(); - return; - } - - const el = event.target.closest( `a.share-${ service }` ); - if ( ! el ) { - return; - } - - if ( windowOpen !== undefined ) { - windowOpen.close(); - } - - const options = 'menubar=1,resizable=1,width=600,height=400'; - windowOpen = window.open( el.getAttribute( 'href' ), `wpcom${ service }`, options ); - if ( windowOpen ) { - windowOpen.focus(); - } - } ); +let sharingWindowOpen; + +if ( typeof window !== 'undefined' ) { + domReady( () => { + const servicesContainer = document.getElementById( 'jetpack-sharing-serivces-list' ); + if ( ! servicesContainer ) { + return; + } + servicesContainer.addEventListener( 'click', event => { + const link = event.target.closest( 'a' ); + const service = link?.dataset?.service; + + if ( ! link || ! link.classList.contains( `share-${ service }` ) ) { + return; + } + + if ( service === 'mail' ) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + if ( service === 'print' ) { + window.print(); + return; + } + if ( sharingWindowOpen ) { + sharingWindowOpen.close(); + } + + sharingWindowOpen = window.open( + link.getAttribute( 'href' ), + `wpcom${ service }`, + 'menubar=1,resizable=1,width=600,height=400' + ); + + if ( sharingWindowOpen ) { + sharingWindowOpen.focus(); + } } ); } ); -} )(); +} diff --git a/projects/plugins/jetpack/extensions/blocks/subscriptions/panel.js b/projects/plugins/jetpack/extensions/blocks/subscriptions/panel.js index 6ccaa523dffc9..1df163f11d40a 100644 --- a/projects/plugins/jetpack/extensions/blocks/subscriptions/panel.js +++ b/projects/plugins/jetpack/extensions/blocks/subscriptions/panel.js @@ -189,7 +189,7 @@ function NewsletterPrePublishSettingsPanel( { accessLevel, isModuleActive, showP { showMisconfigurationWarning && <MisconfigurationWarning /> } { ! isSendEmailEnabled || showMisconfigurationWarning ? ( - <p>{ __( 'Only publishing, not sending this post.', 'jetpack' ) }</p> + <p>{ __( 'Not sent via email.', 'jetpack' ) }</p> ) : ( <SubscribersAffirmation prePublish={ true } accessLevel={ accessLevel } /> ) } diff --git a/projects/plugins/jetpack/extensions/blocks/subscriptions/subscriptions.php b/projects/plugins/jetpack/extensions/blocks/subscriptions/subscriptions.php index 6bef56aca544b..1e460b04a1f36 100644 --- a/projects/plugins/jetpack/extensions/blocks/subscriptions/subscriptions.php +++ b/projects/plugins/jetpack/extensions/blocks/subscriptions/subscriptions.php @@ -9,8 +9,8 @@ use Automattic\Jetpack\Blocks; use Automattic\Jetpack\Connection\Manager as Connection_Manager; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Jetpack_Token_Subscription_Service; -use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; use Automattic\Jetpack\Status; use Automattic\Jetpack\Status\Host; use Jetpack; @@ -196,16 +196,16 @@ function render_newsletter_access_rows( $column_id, $post_id ) { $access_level = get_post_meta( $post_id, META_NAME_FOR_POST_LEVEL_ACCESS_SETTINGS, true ); switch ( $access_level ) { - case Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS: + case Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS: echo esc_html__( 'Paid Subscribers (all plans)', 'jetpack' ); break; - case Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS: + case Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS: echo esc_html__( 'Paid Subscribers', 'jetpack' ); break; - case Token_Subscription_Service::POST_ACCESS_LEVEL_SUBSCRIBERS: + case Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_SUBSCRIBERS: echo esc_html__( 'Subscribers', 'jetpack' ); break; - case Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY: + case Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY: echo esc_html__( 'Everybody', 'jetpack' ); break; default: @@ -610,7 +610,7 @@ function render_block( $attributes ) { function get_post_access_level_for_current_post() { if ( ! is_singular() ) { // There is no "actual" current post. - return Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; + return Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; } return Jetpack_Memberships::get_post_access_level(); @@ -812,7 +812,7 @@ function add_paywall( $the_content ) { $post_access_level = Jetpack_Memberships::get_post_access_level(); if ( Jetpack_Memberships::user_can_view_post() ) { - if ( $post_access_level !== Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY ) { + if ( $post_access_level !== Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY ) { do_action( 'earn_track_paywalled_post_view', array( @@ -1071,8 +1071,8 @@ function get_paywall_blocks( $newsletter_access_level ) { */ function get_paywall_access_question( $post_access_level ) { switch ( $post_access_level ) { - case Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS: - case Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS: + case Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS: + case Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS: $tier = Jetpack_Memberships::get_post_tier(); if ( $tier !== null ) { return sprintf( @@ -1114,9 +1114,18 @@ function is_user_auth() { * @return string */ function get_paywall_blocks_subscribe_pending() { - $access_heading = esc_html__( 'Verify your email to continue reading', 'jetpack' ); + $subscribe_email = Jetpack_Memberships::get_current_user_email(); + + /** This filter is documented in modules/contact-form/grunion-contact-form.php */ + if ( is_wpcom() || false !== apply_filters( 'jetpack_auto_fill_logged_in_user', false ) ) { + $current_user = wp_get_current_user(); + $subscribe_email = ! empty( $current_user->user_email ) ? $current_user->user_email : ''; + } + + $access_heading = esc_html__( 'Confirm your subscription to continue reading', 'jetpack' ); - $subscribe_text = esc_html__( 'Please check your inbox to confirm your subscription.', 'jetpack' ); + /* translators: %s: email address */ + $subscribe_text = sprintf( esc_html__( 'Head to your inbox and confirm your email address %s.', 'jetpack' ), $subscribe_email ); $lock_svg = plugins_url( 'images/lock-paywall.svg', JETPACK__PLUGIN_FILE ); diff --git a/projects/plugins/jetpack/extensions/index.json b/projects/plugins/jetpack/extensions/index.json index 187ba97b7da7f..5e2401582d0fd 100644 --- a/projects/plugins/jetpack/extensions/index.json +++ b/projects/plugins/jetpack/extensions/index.json @@ -53,7 +53,6 @@ "ai-assistant-support", "ai-assistant-form-support", "paywall", - "ai-content-lens", "blogroll", "blogroll-item", "nextdoor", @@ -72,7 +71,8 @@ "ai-assistant-backend-prompts", "sharing-button", "sharing-buttons", - "ai-logo-generator" + "ai-logo-generator", + "ai-content-lens" ], "experimental": [ "ai-image", "ai-paragraph" ], "no-post-editor": [ diff --git a/projects/plugins/jetpack/extensions/shared/memberships/settings.js b/projects/plugins/jetpack/extensions/shared/memberships/settings.js index 1a746c40b27b0..815b868129845 100644 --- a/projects/plugins/jetpack/extensions/shared/memberships/settings.js +++ b/projects/plugins/jetpack/extensions/shared/memberships/settings.js @@ -6,8 +6,11 @@ import { PanelRow, RadioControl, Spinner, - ToggleControl, VisuallyHidden, + // eslint-disable-next-line wpcalypso/no-unsafe-wp-apis + __experimentalToggleGroupControl as ToggleGroupControl, + // eslint-disable-next-line wpcalypso/no-unsafe-wp-apis + __experimentalToggleGroupControlOption as ToggleGroupControlOption, } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { useEntityProp } from '@wordpress/core-data'; @@ -168,7 +171,7 @@ export function NewsletterAccessRadioButtons( { accessLevel: accessOptions.subscribers.key, emailSubscribers, paidSubscribers, - } ) })`, + } ).toLocaleString() })`, value: accessOptions.subscribers.key, }, { @@ -176,7 +179,7 @@ export function NewsletterAccessRadioButtons( { accessLevel: accessOptions.paid_subscribers.key, emailSubscribers, paidSubscribers, - } ) })`, + } ).toLocaleString() })`, value: accessOptions.paid_subscribers.key, }, ] } @@ -312,12 +315,15 @@ export function NewsletterEmailDocumentSettings() { <PostVisibilityCheck render={ ( { canEdit } ) => { return ( - <ToggleControl - checked={ isSendEmailEnabled } + <ToggleGroupControl + value={ isSendEmailEnabled } disabled={ isPostPublished || ! canEdit } - label={ __( 'Send an email', 'jetpack' ) } onChange={ toggleSendEmail } - /> + isBlock + > + <ToggleGroupControlOption label={ __( 'Post & email', 'jetpack' ) } value={ true } /> + <ToggleGroupControlOption label={ __( 'Post only', 'jetpack' ) } value={ false } /> + </ToggleGroupControl> ); } } /> diff --git a/projects/plugins/jetpack/extensions/shared/memberships/subscribers-affirmation.js b/projects/plugins/jetpack/extensions/shared/memberships/subscribers-affirmation.js index 379b6c59d0329..dc139cd31b8a5 100644 --- a/projects/plugins/jetpack/extensions/shared/memberships/subscribers-affirmation.js +++ b/projects/plugins/jetpack/extensions/shared/memberships/subscribers-affirmation.js @@ -66,31 +66,32 @@ const getCopyForCategorySubscribers = ( { reachCount, } ) => { const formattedCategoryNames = getFormattedCategories( postCategories, newsletterCategories ); + const reachCountString = reachCount.toLocaleString(); if ( futureTense ) { return sprintf( // translators: %1s is the list of categories, %2d is subscriptions count _n( - 'This post will be sent to everyone subscribed to %1$s (%2$d subscriber).', - 'This post will be sent to everyone subscribed to %1$s (%2$d subscribers).', + 'This post will be sent to everyone subscribed to %1$s (%2$s subscriber).', + 'This post will be sent to everyone subscribed to %1$s (%2$s subscribers).', reachCount, 'jetpack' ), formattedCategoryNames, - reachCount + reachCountString ); } return sprintf( // translators: %1s is the list of categories, %2d is subscriptions count _n( - 'This post was sent to everyone subscribed to %1$s (%2$d subscriber).', - 'This post was sent to everyone subscribed to %1$s (%2$d subscribers).', + 'This post was sent to everyone subscribed to %1$s (%2$s subscriber).', + 'This post was sent to everyone subscribed to %1$s (%2$s subscribers).', reachCount, 'jetpack' ), formattedCategoryNames, - reachCount + reachCountString ); }; @@ -101,70 +102,72 @@ export const getCopyForSubscribers = ( { postHasPaywallBlock, reachCount, } ) => { + const reachCountString = reachCount.toLocaleString(); + // Schedulled post if ( futureTense ) { // Paid post without paywall: sent only to paid subscribers if ( isPaidPost && ! postHasPaywallBlock ) { return sprintf( - /* translators: %d is the number of subscribers */ + /* translators: %s is the number of subscribers */ _n( - 'This post will be sent to <strong>%d paid subscriber</strong>.', - 'This post will be sent to <strong>%d paid subscribers</strong>.', + 'This post will be sent to <strong>%s paid subscriber</strong>.', + 'This post will be sent to <strong>%s paid subscribers</strong>.', reachCount, 'jetpack' ), - reachCount + reachCountString ); } // Paid post with paywall or Free post, sent to all subscribers return sprintf( - /* translators: %d is the number of subscribers */ + /* translators: %s is the number of subscribers */ _n( - 'This post will be sent to <strong>%d subscriber</strong>.', - 'This post will be sent to <strong>%d subscribers</strong>.', + 'This post will be sent to <strong>%s subscriber</strong>.', + 'This post will be sent to <strong>%s subscribers</strong>.', reachCount, 'jetpack' ), - reachCount + reachCountString ); } // Paid post without paywall: sent only to paid subscribers if ( isPaidPost && ! postHasPaywallBlock ) { return sprintf( - /* translators: %d is the number of subscribers */ + /* translators: %s is the number of subscribers */ _n( - 'This post was sent to <strong>%d paid subscriber</strong>.', - 'This post was sent to <strong>%d paid subscribers</strong>.', + 'This post was sent to <strong>%s paid subscriber</strong>.', + 'This post was sent to <strong>%s paid subscribers</strong>.', reachCount, 'jetpack' ), - reachCount + reachCountString ); } // Paid post sent only to paid subscribers, post is already published if ( isPaidPost && ! postHasPaywallBlock ) { return sprintf( - /* translators: %d is the number of subscribers */ + /* translators: %s is the number of subscribers */ _n( - 'This post was sent to <strong>%d paid subscriber</strong> only.', - 'This post was sent to <strong>%d paid subscribers</strong> only.', + 'This post was sent to <strong>%s paid subscriber</strong> only.', + 'This post was sent to <strong>%s paid subscribers</strong> only.', reachCount, 'jetpack' ), - reachCount + reachCountString ); } // Paid post with paywall or Free post, sent to all subscribers, post is already published return sprintf( - /* translators: %d is the number of subscribers */ + /* translators: %s is the number of subscribers */ _n( - 'This post was sent to <strong>%d subscriber</strong>.', - 'This post was sent to <strong>%d subscribers</strong>.', + 'This post was sent to <strong>%s subscriber</strong>.', + 'This post was sent to <strong>%s subscribers</strong>.', reachCount, 'jetpack' ), - reachCount + reachCountString ); }; @@ -242,7 +245,7 @@ function SubscribersAffirmation( { accessLevel, prePublish = false } ) { emailSubscribers: emailSubscribersCount, paidSubscribers: paidSubscribersCount, postHasPaywallBlock, - } ).toLocaleString(); + } ); let text; diff --git a/projects/plugins/jetpack/jetpack.php b/projects/plugins/jetpack/jetpack.php index 3532590e34b71..2d57c7ea96252 100644 --- a/projects/plugins/jetpack/jetpack.php +++ b/projects/plugins/jetpack/jetpack.php @@ -4,7 +4,7 @@ * Plugin URI: https://jetpack.com * Description: Security, performance, and marketing tools made by WordPress experts. Jetpack keeps your site protected so you can focus on more important things. * Author: Automattic - * Version: 13.0-a.4 + * Version: 13.0-a.8 * Author URI: https://jetpack.com * License: GPL2+ * Text Domain: jetpack @@ -34,7 +34,7 @@ define( 'JETPACK__MINIMUM_WP_VERSION', '6.3' ); define( 'JETPACK__MINIMUM_PHP_VERSION', '7.0' ); -define( 'JETPACK__VERSION', '13.0-a.4' ); +define( 'JETPACK__VERSION', '13.0-a.8' ); /** * Constant used to fetch the connection owner token diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php index b64d8109a6c19..90bb2600b0f0e 100644 --- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php +++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php @@ -118,6 +118,7 @@ 'rss_use_excerpt' => '(bool) Whether the RSS feed will use post excerpts', 'launchpad_screen' => '(string) Whether or not launchpad is presented and what size it will be', 'sm_enabled' => '(bool) Whether the newsletter subscribe modal is enabled', + 'wpcom_ai_site_prompt' => '(string) User input in the AI site prompt', ), 'response_format' => array( diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php index 6f2d65ce71698..819a74e348b73 100644 --- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php +++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-v1-4-endpoint.php @@ -128,6 +128,7 @@ 'page_for_posts' => '(string) The page ID of the page to use as the site\'s posts page. It will apply only if \'show_on_front\' is set to \'page\'.', 'subscription_options' => '(array) Array of three options used in subscription email templates: \'invitation\', \'welcome\' and \'comment_follow\' strings.', 'jetpack_verbum_subscription_modal' => '(bool) Whether Subscription modal is enabled in Verbum comments', + 'wpcom_ai_site_prompt' => '(string) User input in the AI site prompt', ), 'response_format' => array( diff --git a/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js b/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js index 47928b34e5f9c..b6d5848345278 100644 --- a/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js +++ b/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js @@ -116,16 +116,19 @@ // Ensure the item is in the render tree, in its initial state. el.style.removeProperty( 'display' ); el.style.opacity = start; - el.style.transition = 'opacity 0.2s'; el.style.pointerEvents = 'none'; - var finished = function ( e ) { - if ( e.target === el && e.propertyName === 'opacity' ) { - el.style.removeProperty( 'transition' ); - el.style.removeProperty( 'opacity' ); + var animate = function ( t0, duration ) { + var t = performance.now(); + var diff = t - t0; + var ratio = diff / duration; + + if ( ratio < 1 ) { + el.style.opacity = start + ( end - start ) * ratio; + requestAnimationFrame( () => animate( t0, duration ) ); + } else { + el.style.opacity = end; el.style.removeProperty( 'pointer-events' ); - el.removeEventListener( 'transitionend', finished ); - el.removeEventListener( 'transitioncancel', finished ); callback(); } }; @@ -133,22 +136,19 @@ requestAnimationFrame( function () { // Double rAF for browser compatibility. requestAnimationFrame( function () { - el.addEventListener( 'transitionend', finished ); - el.addEventListener( 'transitioncancel', finished ); - // Trigger transition. - el.style.opacity = end; + animate( performance.now(), 200 ); } ); } ); } function fadeIn( el, callback ) { callback = callback || util.noop; - fade( el, '0', '1', callback ); + fade( el, 0, 1, callback ); } function fadeOut( el, callback ) { callback = callback || util.noop; - fade( el, '1', '0', function () { + fade( el, 1, 0, function () { if ( el ) { el.style.display = 'none'; } diff --git a/projects/plugins/jetpack/modules/google-fonts/current/class-jetpack-google-font-face.php b/projects/plugins/jetpack/modules/google-fonts/current/class-jetpack-google-font-face.php index f2add2938548b..c9860507bfa9b 100644 --- a/projects/plugins/jetpack/modules/google-fonts/current/class-jetpack-google-font-face.php +++ b/projects/plugins/jetpack/modules/google-fonts/current/class-jetpack-google-font-face.php @@ -138,7 +138,7 @@ public function get_fonts() { if ( ! empty( $raw_data['settings']['typography']['fontFamilies'] ) ) { foreach ( $raw_data['settings']['typography']['fontFamilies'] as $font ) { $font_family_name = $this->get_font_family_name( $font ); - $font_slug = isset( $font['slug'] ) ? $font['slug'] : ''; + $font_slug = $font['slug'] ?? ''; if ( $font_slug && ! array_key_exists( $font_slug, $fonts ) && array_key_exists( $font_family_name, $fonts ) ) { $fonts[ $font_slug ] = $fonts[ $font_family_name ]; } @@ -153,7 +153,7 @@ public function get_fonts() { * * @param array $font The font definition object. */ - public function get_font_family_name( $font ) { + public static function get_font_family_name( $font ) { $font_family = $font['fontFamily']; if ( str_contains( $font_family, ',' ) ) { $font_family = explode( ',', $font_family )[0]; diff --git a/projects/plugins/jetpack/modules/google-fonts/current/load-google-fonts.php b/projects/plugins/jetpack/modules/google-fonts/current/load-google-fonts.php index 7181d00549e2e..dc439bc4030de 100644 --- a/projects/plugins/jetpack/modules/google-fonts/current/load-google-fonts.php +++ b/projects/plugins/jetpack/modules/google-fonts/current/load-google-fonts.php @@ -5,6 +5,13 @@ * @package automattic/jetpack */ +if ( ! class_exists( 'Jetpack_Google_Font_Face' ) ) { + /** + * Load Jetpack Google Font Face + */ + require_once __DIR__ . '/class-jetpack-google-font-face.php'; +} + /** * Gets the Google Fonts data * @@ -94,8 +101,9 @@ function jetpack_get_theme_fonts_map() { $theme_fonts_map = array(); foreach ( $raw_data['settings']['typography']['fontFamilies'] as $font_family ) { - if ( isset( $font_family['name'] ) ) { - $theme_fonts_map[ $font_family['name'] ] = true; + $font_family_name = $font_family['name'] ?? Jetpack_Google_Font_Face::get_font_family_name( $font_family ); + if ( $font_family_name ) { + $theme_fonts_map[ $font_family_name ] = true; } } @@ -127,9 +135,7 @@ function ( $google_fonts_family ) use ( $available_google_fonts_map, $theme_font return false; } - return isset( $available_google_fonts_map[ $name ] ) - ? $available_google_fonts_map[ $name ] - : false; + return $available_google_fonts_map[ $name ] ?? false; } ) ); @@ -165,7 +171,7 @@ function ( $font_family ) { if ( isset( $font_family['fontFace'] ) ) { foreach ( $font_family['fontFace'] as $font_face ) { - $provider = isset( $font_face['provider'] ) ? $font_face['provider'] : ''; + $provider = $font_face['provider'] ?? ''; if ( $provider === 'jetpack-google-fonts' ) { $has_deprecated_google_fonts_data = true; break; @@ -203,13 +209,6 @@ function jetpack_unregister_deprecated_google_fonts_from_theme_json_data_user( $ add_filter( 'wp_theme_json_data_user', 'jetpack_unregister_deprecated_google_fonts_from_theme_json_data_user' ); -if ( ! class_exists( 'Jetpack_Google_Font_Face' ) ) { - /** - * Load Jetpack Google Font Face - */ - require_once __DIR__ . '/class-jetpack-google-font-face.php'; - - // Initialize Jetpack Google Font Face to avoid printing **ALL** google fonts provided by this module. - // See p1700040028362329-slack-C4GAQ900P and p7DVsv-jib-p2 - new Jetpack_Google_Font_Face(); -} +// Initialize Jetpack Google Font Face to avoid printing **ALL** google fonts provided by this module. +// See p1700040028362329-slack-C4GAQ900P and p7DVsv-jib-p2 +new Jetpack_Google_Font_Face(); diff --git a/projects/plugins/jetpack/modules/memberships/class-jetpack-memberships.php b/projects/plugins/jetpack/modules/memberships/class-jetpack-memberships.php index 385bd3081984f..51cdcf821f004 100644 --- a/projects/plugins/jetpack/modules/memberships/class-jetpack-memberships.php +++ b/projects/plugins/jetpack/modules/memberships/class-jetpack-memberships.php @@ -7,7 +7,7 @@ */ use Automattic\Jetpack\Blocks; -use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; use Automattic\Jetpack\Status\Host; use const Automattic\Jetpack\Extensions\Subscriptions\META_NAME_FOR_POST_LEVEL_ACCESS_SETTINGS; use const Automattic\Jetpack\Extensions\Subscriptions\META_NAME_FOR_POST_TIER_ID_SETTINGS; @@ -283,6 +283,19 @@ public function return_meta( $map ) { return $map['meta']; } + /** + * Show an error to the user (or embed a clue in the HTML) when the button does not get rendered properly. + * + * @param WP_Error $error The error message with error code. + * @return string The error message rendered as HTML. + */ + public function render_button_error( $error ) { + if ( $this->user_can_edit() ) { + return '<div><strong>Jetpack Memberships Error: ' . $error->get_error_code() . '</strong><br />' . $error->get_error_message() . '</div>'; + } + return '<div>Sorry! This product is not available for purchase at this time.</div><!-- Jetpack Memberships Error: ' . $error->get_error_code() . ' -->'; + } + /** * Renders a preview of the Recurring Payment button, which is not hooked * up to the subscription url. Used to preview the block on the frontend @@ -347,7 +360,7 @@ public function render_button( $attributes, $content = null, $block = null ) { } if ( empty( $attributes['planId'] ) ) { - return; + return $this->render_button_error( new WP_Error( 'jetpack-memberships-rb-npi', __( 'No plan was configured for this button.', 'jetpack' ) . ' ' . __( 'Edit this post and confirm that an existing payment plan is selected for this block.', 'jetpack' ) ) ); } // This is string of '+` separated plan ids. Loop through them and @@ -359,11 +372,17 @@ public function render_button( $attributes, $content = null, $block = null ) { continue; } $product = get_post( $plan_id ); - if ( ! $product || is_wp_error( $product ) ) { - continue; + if ( ! $product ) { + return $this->render_button_error( new WP_Error( 'jetpack-memberships-rb-npf', __( 'Could not find a plan for this button.', 'jetpack' ) . ' ' . __( 'Edit this post and confirm that the selected payment plan still exists and is available for purchase.', 'jetpack' ) ) ); } - if ( $product->post_type !== self::$post_type_plan || 'publish' !== $product->post_status ) { - continue; + if ( is_wp_error( $product ) ) { + return $this->render_button_error( new WP_Error( 'jetpack-memberships-rb-npf-we', __( 'Encountered an error when getting the plan associated with this button:', 'jetpack' ) . ' ' . $product->get_error_message() . '. ' . __( ' Edit this post and confirm that the selected payment plan still exists and is available for purchase.', 'jetpack' ) ) ); + } + if ( $product->post_type !== self::$post_type_plan ) { + return $this->render_button_error( new WP_Error( 'jetpack-memberships-rb-pnplan', __( 'The payment plan selected is not actually a payment plan.', 'jetpack' ) . ' ' . __( 'Edit this post and confirm that the selected payment plan still exists and is available for purchase.', 'jetpack' ) ) ); + } + if ( 'publish' !== $product->post_status ) { + return $this->render_button_error( new WP_Error( 'jetpack-memberships-rb-psnpub', __( 'The selected payment plan is not active.', 'jetpack' ) . ' ' . __( 'Edit this post and confirm that the selected payment plan still exists and is available for purchase.', 'jetpack' ) ) ); } $valid_plans[] = $plan_id; } @@ -501,12 +520,12 @@ public static function get_post_access_level( $post_id = null ) { $post_id = get_the_ID(); } if ( ! $post_id ) { - return Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; + return Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; } $post_access_level = get_post_meta( $post_id, self::$post_access_level_meta_name, true ); if ( empty( $post_access_level ) ) { - $post_access_level = Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; + $post_access_level = Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; } return $post_access_level; } @@ -558,7 +577,7 @@ public static function user_is_paid_subscriber() { require_once JETPACK__PLUGIN_DIR . 'extensions/blocks/premium-content/_inc/subscription-service/include.php'; $paywall = \Automattic\Jetpack\Extensions\Premium_Content\subscription_service(); - $is_paid_subscriber = $paywall->visitor_can_view_content( self::get_all_newsletter_plan_ids(), Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS ); + $is_paid_subscriber = $paywall->visitor_can_view_content( self::get_all_newsletter_plan_ids(), Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS ); self::$user_is_paid_subscriber_cache[ $user_id ] = $is_paid_subscriber; return $is_paid_subscriber; @@ -599,14 +618,14 @@ public static function user_can_view_post( $post_id = null ) { } $post_access_level = self::get_post_access_level(); - if ( Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY === $post_access_level ) { + if ( Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY === $post_access_level ) { self::$user_can_view_post_cache[ $cache_key ] = true; return true; } if ( $user_id === 0 ) { if ( defined( 'WPCOM_SENDING_POST_TO_SUBSCRIBERS' ) && WPCOM_SENDING_POST_TO_SUBSCRIBERS ) { - if ( Token_Subscription_Service::POST_ACCESS_LEVEL_SUBSCRIBERS === $post_access_level ) { + if ( Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_SUBSCRIBERS === $post_access_level ) { return true; } } @@ -618,17 +637,17 @@ public static function user_can_view_post( $post_id = null ) { $all_newsletters_plan_ids = self::get_all_newsletter_plan_ids(); if ( 0 === count( $all_newsletters_plan_ids ) && - Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS === $post_access_level || - Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS === $post_access_level + Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS === $post_access_level || + Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_PAID_SUBSCRIBERS_ALL_TIERS === $post_access_level ) { // The post is paywalled but there is no newsletter plans on the site. // We downgrade the post level to subscribers-only - $post_access_level = Token_Subscription_Service::POST_ACCESS_LEVEL_SUBSCRIBERS; + $post_access_level = Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_SUBSCRIBERS; } $can_view_post = $paywall->visitor_can_view_content( $all_newsletters_plan_ids, $post_access_level ); - if ( $can_view_post && $post_access_level !== Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY ) { + if ( $can_view_post && $post_access_level !== Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY ) { // Prevent batcache to cache paywalled content if ( function_exists( 'batcache_cancel' ) ) { batcache_cancel(); diff --git a/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.css b/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.css index 16a3862fdf423..8b9b364579b42 100644 --- a/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.css +++ b/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.css @@ -316,8 +316,9 @@ body.settings_page_sharing .advanced input[type=submit] { margin-left: -4px; } -.preview-twitter .option-smart-on { - background: url(images/smart-twitter.png?1) no-repeat top left; +.preview-twitter .option-smart-on, +.preview-x .option-smart-on { + background: url(images/smart-x.png?1) no-repeat top left; background-size: 60px 20px; width:60px; height:20px; @@ -370,8 +371,9 @@ body.settings_page_sharing .advanced input[type=submit] { background-image: url(images/smart-like@2x.png); } - .preview-twitter .option-smart-on { - background-image: url(images/smart-twitter@2x.png?1); + .preview-twitter .option-smart-on, + .preview-x .option-smart-on { + background-image: url(images/smart-x@2x.png?1); } .preview-linkedin .option-smart-on { @@ -438,3 +440,14 @@ body.settings_page_sharing .advanced input[type=submit] { width: 0; text-indent: 100%; } + +.sharing-block-message__items-wrapper { + display: flex; + flex-wrap: wrap; + column-gap: 6rem; +} + + +.sharing-block-message__buttons-wrapper .button { + margin-right:1rem; +} \ No newline at end of file diff --git a/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.js b/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.js index 93cb54fec3f9c..d8a4ee1421e94 100644 --- a/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.js +++ b/projects/plugins/jetpack/modules/sharedaddy/admin-sharing.js @@ -137,7 +137,7 @@ $( '.sharing-hidden ul li' ).remove(); // Add hidden items into the inner panel - $( 'ul.services-hidden li' ).each( function (/*pos, item*/) { + $( 'ul.services-hidden li' ).each( function ( /*pos, item*/ ) { if ( $( this ).hasClass( 'service' ) ) { var service = $( this ).attr( 'id' ); $( '.sharing-hidden .inner ul' ).append( @@ -161,7 +161,7 @@ $( '#live-preview div.sharedaddy' ).addClass( 'sd-social-icon' ); } else if ( 'official' === button_style ) { $( '#live-preview ul.preview .advanced, .sharing-hidden .inner ul .advanced' ).each( - function (/*i*/) { + function ( /*i*/ ) { if ( ! $( this ).hasClass( 'preview-press-this' ) && ! $( this ).hasClass( 'preview-email' ) && @@ -171,7 +171,6 @@ ! $( this ).hasClass( 'preview-reddit' ) && ! $( this ).hasClass( 'preview-telegram' ) && ! $( this ).hasClass( 'preview-jetpack-whatsapp' ) && - ! $( this ).hasClass( 'preview-x' ) && ! $( this ).hasClass( 'share-custom' ) && ! $( this ).hasClass( 'share-deprecated' ) ) { @@ -296,21 +295,21 @@ } $( '#enabled-services .services ul' ).sortable( { - receive: function (/*event, ui*/) { + receive: function ( /*event, ui*/ ) { save_services(); }, stop: function () { save_services(); $( 'li.service' ).enableSelection(); // Fixes a problem with Chrome }, - over: function (/*event, ui*/) { + over: function ( /*event, ui*/ ) { $( this ).find( 'ul' ).addClass( 'dropping' ); // Ensure the 'end-fix' is at the end $( '#enabled-services li.end-fix' ).remove(); $( '#enabled-services ul' ).append( '<li class="end-fix"></li>' ); }, - out: function (/*event, ui*/) { + out: function ( /*event, ui*/ ) { $( this ).find( 'ul' ).removeClass( 'dropping' ); // Ensure the 'end-fix' is at the end @@ -322,7 +321,7 @@ return ui.clone(); }, - start: function (/*event, ui*/) { + start: function ( /*event, ui*/ ) { // Make sure that the advanced section is closed $( '.advanced-form' ).hide(); $( 'li.service' ).disableSelection(); // Fixes a problem with Chrome @@ -487,7 +486,7 @@ .css( 'backgroundImage', 'url("' + sharing_loading_icon + '")' ); // Save - form.ajaxSubmit( function (/*response*/) { + form.ajaxSubmit( function ( /*response*/ ) { // Remove the item form.parents( 'li:first' ).fadeOut( function () { $( this ).remove(); diff --git a/projects/plugins/jetpack/modules/sharedaddy/images/smart-twitter.png b/projects/plugins/jetpack/modules/sharedaddy/images/smart-twitter.png deleted file mode 100644 index 299c7d88e0cd03bd8aa1a226928f6197850b7e24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1952 zcmV;R2VeM!P)<h;3K|Lk000e1NJLTq002Ay000yS1^@s6(F0y7000MPNkl<ZSi{{| zdu&u?7QdQoHbz-NgmyYpXccV~qd+vf>*EiNVvI)r*xdv*zM|oeO;A}y0kQ3!PQ_Mv z`rwT#1qFnnR33$84T=yJrSe#Obmq>TnRf0xIy0SVXQuP${dvCce%DTG2is^&bdr;M z@A;m;^E>B!=NqX_OIJM7q`iM_gC{bf)~#7(x4%qwYZj8S-?-T9s=tIVRW+!QC$<E( zGOW@=o3!nd8oDq}_Q7gbVXgC`>~|#PbsmhV^`fG&3$y<1Z<YkJy4CL1$ts2neJ>QD zFQ@m(b;gr@4;p{IIpiTvdyzGY%{O$cT;#hzY^1-uM#0nuwOb;veyiOBYJeC3QzqLD zF~7;pK`xI9(v7KBAT4xZJWX_U9ktiGQCd6Dm-QoKVA3#RD_G;#5{8km1|;t91%ORZ zOr%8w>SYC2))|A?MlA$NdP%{}%e{E4Ny81Vc_Gbnp_G7B+6~ZbYzgc4vNEiU6@7jQ zAQnN)6xw6C_#U<|!)RARg8)-!oiQ+uSR-p-_7)9)Th|Hc1t+GE{%VI|gzAq%h^G6& zejTwaT23V(@9RP-Ejp3LvPG|SsJMNp7k4isS#HS8WroanMdkBzFOUbo+vEZE*^}+1 ze8|R4y{*6trI%cgUUcE28spni46r-|a47+1mXeseE^y)CnFOMJ{g}Hw2x&e|`gA+~ z`nm`1NS1@`@7H1eHXe^dVnAhuFaGf60D?KAEtAuc&KL%wLD>AU2I)B`B@{OYZV^B( zBV%1!V}wkZ@DSz=l>#8sTWSq28BhAF*j^VXn7=cOmJ?C@V}(llR5;s~kpQ+B$%tE( z0iM4zh@8N5)Rn@5T_G$acH@HGya3EtzIRmzAHxks8@g?|4~~`)-aZh48p|Wun?cjT zFjgH1W6oMH4~t6bdwo4IM(Z&E*AeqG78{I>kyXqjuei=(gb)M3p5y5xnYqk^sSd&H zJU4c>C877{Q2Q>;`@9R+I7R_@l6@df7wrn7Gm%5#FH2ZWVs+hkQ9~I_Yw&P)H<KJ= zg?WVZf{Oq7ve2|%Os`SVaxR6F=c1%{Vdc>tMB{y!^OhU8t_{Ey&Eow%6h<2~xVsIb z_Vi@1W*3Fkvrf#}(FI>T&-Do!=V<cbndUHr!yyz-qk5x{=aeaqQ2@3IhU<u-ya1ZZ z>(B>07zN&p!`~($)fg_x08b=?Rn;3zm(+Xlr9X#AIElZ|ydRwFLr-@fo?PL<A&;@s z)jRxf?2jQqUhsBH5GSdBhbMu%mUz+Ho<=O1!s6y2{vXOiadqPk(*IZKL%chUe{Jl* z?z1WA`5ZR225~)KU*RXjPXcCHx|Fd)t~Qp%F)_C8NDS$`E*K>dAWe5>JT&YJbH*5} z<pMBIaCB@*b}vqJWYHZ<;fi_fnEPP_UA<Xs`?L$kyjk?6vN&`yioM??@twN|i+6_* z%INU=lGt`6iqoAL^pRURJ5mVr5@2r<TS<Q=z>KBijrTgS<X|^?(izNIO)>nei$Y`Y z5qVy~mVzuOEmTlLF`Ly*R`nm)HQo6uUm6vQRnBIGuxd#G;0vkRVJ_VrOXJ1`?U??i zAE&h(v6;n5XD^yRi&2c{5Q}HA=Wr1Jqy)*lxm}^QV==V0#j*8p1ba_Y0;R<FwTtve zW7yZ0z~19gJpP6k8$M4Uk;>qiHMEbpE=;W-1>nN7jVA?)o!RdNe#p$+wFSHWcn%M) z@8lW0(mrs!Fu+v;@C5|;3t~7PPvg!SC+Xa1K9}a>+s;Pt@H-kJe7YPKu2V5(g&%>G zj&Ht>Q7k&K@<<#`Es53t>4FmL$Jw(K|Ia(I>R1B)t`r_y?!lXf6U22MYj$hgGbhQz zob$y1^NzIPiS&G6gCB2w62%E6iELgUl)S#`NaOEoJ9(^MA;4PXA2a+10{pqV4_YvZ z`y4LLz@j}dWN5x!t$yzErvo_z1HHJvo@HGH_We;h4uv=6`*G-K*vKgdD9%NK%4PFt zJrbhhtsS$shd~DcQk3AT-|=yST;&)A!|YfZLkZ}Xl|HN|m;2J2#wmXWC+NBVOb=!6 z5I=JnAhQblQ7I>?GG>J7ud4Vn$z*!JT%4;nHK@EKoj}QM8nsQMurR7Lg`W^NG<xvl zhECkOROR0nR2%vkRM|a6iRzvuDqsJPG=3b7yOB<bnM*yW5@-8}87{17E@7o0S&J1C z5<9ABa{f+Y6Uogog7R-H8Si3}QZX+Bc1g8S&DnUnA=ZLgomG1*hp-~ZtjSrJU0OY$ zH!CqV=1(<7K{BCO*=m-S=es=EM2*VIN){ItvQgbIR!36{+vLF|qIt2f7HKaN?G*y3 zb%gq%x?wL5*Easd^-z3Ug%rDj71hhbUoX#lO&rPfP#)#=kTCM=;X|AJJIp@-Y~~*T z_TS$h0F{jq%zD@Vp>#@3S3cULZJXNYiA|_gLS&I3Nr(mbFC*?D&ylwMoVAR1a_?XX mVXA8I#Gcr!eQ-RGuKXUgHmw2qLqeMX0000<MNUMnLSTaQ!>m65 diff --git a/projects/plugins/jetpack/modules/sharedaddy/images/smart-twitter@2x.png b/projects/plugins/jetpack/modules/sharedaddy/images/smart-twitter@2x.png deleted file mode 100644 index 0be96c46ac133c8e86c3938f32ee9b5d6a4624f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1691 zcmV;M24wk(P)<h;3K|Lk000e1NJLTq004Oa001Zm1^@s6+9*{U000JJNkl<Zc-rlp z`%hbC7{~cHaA>^zph3faF;U#iqFYQfqEiz!{-QA?ni!+ec$*{^g(~1i%$mt?OklDL zEP^Ajp<FgWw}=xMj17TuT6&=^P<lD^a!McH_ngyn=>^VdOM0m9n|w#o^YmTM`SiKG z&)ahf0H6RX$V3b3uX!%)YqXBvT}@5gQMo|0!-TmZeiMje59S$T%l<>HG3}+tEYrv^ zfD|R#@d_ZGw-DD(7BVKz1KvOaqP$TQah=6{*$~ZpFu5@Kry%0nTYz&g@8aa5<e?DX zn+1H4MIh&?5Z{{xd}T%;=dTE40-1<FPFIgNTH)Q^75K1k6`noifTFJ`+3{Up5;&TH zyr;p604cYB;9E2F83PbMW|kRv;)D(EuQNmWFU#=bxSzn$3giJQ2+asckpj=VM^C{G zXBbkA@J1A(=&wH<g}unrx0<uG-V6s+s+d4lKY=F{WdU{0tiydZrcG@>A8^A~1J8D9 z(homP(s1D9Qp&jsE6p$x0+k~IhmXu_8c1QK37&7Xz^liR8co`QjK`dtVe@M$+cA4s z5ef!Pi9`107b6|WjOHQls$T(G__$su(-}1ot``#X>&3YMl;L73F5J3<8;Vf8*}1If z8{aS$fGIN#{}_3h83;>af<<}^)dBySz3_gmQPYr%>X*S4I|bUK4ahH@b*6;npf{jp z!Vm9VTxIR7-iRW|`+l&ccQSgHc!3b^FRHg2D8<$VrFB`fm!1RdhDUWd4%fJ<e&m=1 z>i+ORHpjyTOM0QMPT~b9H0$}$TyoM4R+<5)Cj!PvyX-wrb@;$ZhuLE@qgL6m*DkGt z8y}-1aD8}Dc>PX;0|pkQQ3H)Y82X2je>s)d<H&S=k^79&3dOk+2DgU>U5zn!o=l@k zcwvoUE8}d82%6@uDk`gxah?-PK0mxJ34wKUlFuFRz>~r;3QoJki+#3<d%dL9Bj(H` z!*6!UyicipVWkEBili<_Gpr>tgWNGqXVr_Z+e7IWEh!*lFX>(tFIX!NjJ>cy*&<GS zkIn&<0N)EQBlv~7C76|_BjXx;({6*B%U;R<3o!rZB0q;3dkPNqyP;!BQcW^J=p9~# z_Ny!KhCYX${1|G6gtFwtc<6^cS%-{OKEjBNm){qYcsMsM|IFF%KI0Q!Tb<^@YWWor zfMrY`nu`pQxfm{5sI}*EvQt|*Ii?rSIAJZckrl|egSH)ziwtfdY(^bi_5Q*oer3R* zyc^`csE!*PjE^S7*xA!&jEe>g7#bGfp*j;PqLAt-DAt+byd=E0G*PPTW6?!+4zl!- zW61aFO>nSn39gue83D%Kvy9f5n?PpQ)$795gSXJdi{)d#(FwKV9Mq_16?MfZ=<~*G z*I8Tn`?nr{_gYliQ`&}%3nhy$lCc->Z?bJ0WULCoJCWx!TVRlfaC^vv!t=WD1^D!+ z6Kt`<$mkHhB!h9#!l-MLC~p3qb1LoIHSWpmQl#0=R@&)~??-)^cZ;@wT+-?lbEMJF z+v3W3PO?6Y!sK*7SnkAfwA_;u=T6#@Q(>R<9JB@*3-2P0+Cphn)aWNF+YY%<XNB>E zfFp+E!G!P{fKMb1m8#of-7z_2PH1$9IhL!^)!HYVgO&=fcs<=>2b*76_{Lj|#fQz= z>HBU0IbmIlM#$k3cBZPP<i%si>XJ7#8rNiP)2qXFc&-)|QU)uu&5G4K&g&SCTKiaA z(=A!jox5O%LtRTymdhoSRJ*@hgs(?D;0q}W+r#D{yT6>Z=Dq^RdphLn`q-M5O*vh3 zTrrfm3sf<|Y`F<yXqZpiK6z6lhs}^@TJ3P;nwQ-coOXp3hi9C-E6}#1njageha64{ znQc%+#I48J(uI4!wD%oM*-Ct;-w*C2?C2FA=#FM?f3V9NXRkb`Z;L16Jd8IXloVZf zgQ6NWJF*p?b1Mq%``X}xjwSf)v=v^d&$j&nyQbcc^q}6Tjhu{s^?`Ho$G^E*@5bOy zjQQBji?_R1VDE8j9)Kl3<Rc=Gi3nsO0+}d7$mE8%|G^D!`0)b-a-QG1if>XTH=*bC zP3XVI9w%{&cys;<ah+!$C&51$rV~G30+S~fCqFzG14dlCg{S{W9`V$RV)ztJ*0?Go l+F8Qfa1KTs`=pO}`VX4f0W(AeEx`Z)002ovPDHLkV1h4tI&lC1 diff --git a/projects/plugins/jetpack/modules/sharedaddy/images/smart-x.png b/projects/plugins/jetpack/modules/sharedaddy/images/smart-x.png new file mode 100644 index 0000000000000000000000000000000000000000..d6ede143ae6049e7392db0723da40db010cacacc GIT binary patch literal 1365 zcmV-b1*-aqP)<h;3K|Lk000e1NJLTq002Ay000yS1^@s6(F0y700009a7bBm000XU z000XU0RWnu7ytkT2T4RhR9J=Om|sYgSs2D2#TlGYhjc<MWwKz*(f(LwOcyy4{lPH8 zAP_1l!YC#R3d;UK)P?Is1rdZ<T?B<2R8~Zb7ZGTPkRh~-5<)CRhK0=VO<p+J{`SIV z*3V|f*$ry9ec|xId7ty0=Q-!R=e*~n0Qx^!nk1#9q{Q;MCDlu+kyIopPg3f)BK8mL z4@tw4ewXx%q@N`Xeu0WH!x@rVBz=;^f4F@5tizE=aDk-0NTbZmOx$iaix)4(=ksB; zTH|(5Qc{A&V)@=8W0ihMg|P%@N&0m%c<$V}bai#n)6+w5Z!c%goQe6<ojZ4O=gu8$ zHe15ZQ&Lh)-)~rc`>f9-_);wJ$&)8}_Uswi+1U&a53_yyc9Y-d^AQLHsH&=p+o9EJ z<@W8{3=Iuo7zUwGh;TSeZ*MQPwY6U@C^t8k`ucii&YYPDcWJU<w-Utcy?giAv}qHC zg@qV~!R*<yk%Zgr#xM*vY}k;Hklk(vAQ%jC`t)g<nwq$H@gn2n;{YsQzWl2MS5{U6 zP+nf12=_@+aYS%aq8}C%6!7}>Yf@8FIez>&4<0-qD=Uk^!9flkIy5aIo6SZz9Ol}! zYo>aa%LTxdD_5d*rKP1DJa~{DJ9dzfkzvBmnl+2Pd-rnSzyV51N{~cOP7aNYjQ|`u za)hFyA{-7!JT5;)1V5dQbVEY}ot>T08GrNU4Sv5rsTr`@Y>bVKasB%BFML3BAPyfs z%w!7&gH%*hAc>lq8VtiQ`8RId$eJ~4Om*kZox|tz#pCicA~=`~@s5rTcJJPe)oKMG zJ3BjR!GS=4?(S}?s;a22uBNW8j>nH51K{;~nLmF%0C(@+#o=(UXwf1J!@w{MEEWp` z0|PKY7D;q=b`lDOuvjc?+qMmWJ$v@xbULxy?eVx65y45v%gD$Gd3kx%*VohC-JMjM z^z?LIym&z@Yi@2v5^Zg5gu`J|yR~cA0#H#=!P&EC0cdS)W!<`U<mcz(a=DO1d3iYi z3l}b&p3mQz;gu^_5(<T)OS_|^gJZ{zB_%i*4ARxrMP+3rKA(>jD^`%3n;XUS_4P40 zIB05@pPvsvLqh|SIC}JGbfW{<w{IWP#7O~AU0ppL7bEEy_IkaHjEvy%c({D|GEGfQ zNMdMc2#?2;R1Dv^aU(9Ky}g~Wu`yHK>eZ_OsH>~P=krAqo3gSpZr;2Zoz+M<l$MrG zC-`YnyR^&YVsvzr&6_tPO=Mv2-@m80xR~|p*Yo`O^JxVGJbd^tE+!(by}cc$)5+4M zO9=*p7>0q(X5;PKw~UUCMvp|l-w(io1q-5r8yg#$F=Ga4X=(BLX^sdkR-AL#X0!3~ z<x5VSIAN-<t*zzVyLU+9)TvVmm$uz*XMB8|`}glB9GI!QbRZBg?b07VegxpdhYtW; zy?PZ%I2;aMy?O<}`Sa)FB|)ZhSdv<&g67Pb!=p!!Oy}g}a^b=So;-O%OG^t7KY>V1 zO=ZcFCCr;QZ`yeGcs%(1ezt7cLS|;B$>(%B*}8Qr`}gn1>-Cy^IXOA3TD6L@va)y? zSF0qY0FmoqmZTm@rI8URDk{>lWy^Hy)-A=eUAuNEJw08)U{HO1ed_P;kBj||HXzBX zNt;&0Ot+;Uq{O`~MJz)TiT00hA8yr@`|#u?J=G#F9_#hji$_f0zr>LF#iLCzUOfH; XunwVk3e=)M00000NkvXXu0mjfMU9Vr literal 0 HcmV?d00001 diff --git a/projects/plugins/jetpack/modules/sharedaddy/images/smart-x@2x.png b/projects/plugins/jetpack/modules/sharedaddy/images/smart-x@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c36ac17d22400e8cd4d3cda15f8751f7b1eba0 GIT binary patch literal 3170 zcmV-o44w0dP)<h;3K|Lk000e1NJLTq004Oa001Zm1^@s6+9*{U00009a7bBm000XU z000XU0RWnu7ytka6iGxuRCt{2TzycK)f)f3d@g?Q5etci@)2J~Gy;-d1;ZdsZgyR# z!3l34jv^B!Vxx^tSdKH)7%G)f2;?6XiUT(4fLV%DDc<G+0!oTDia>#g<U$az3%~mZ z?76$_E}zSVuKZ>mhI!8OJnuQr?>*-|=e*}#i6kcR{|yTOkR)j&zK;WV8o=KGcmr?+ zFb#l}sVesXqYJ<v0BQkT2T%myEP%_y4Mei<&(JXqz!m_N05~cCbE)jh|Fpq~(qK3w zTL4G^&@=%WIw`$8B=qqzAcjh^7l7gk(6C9-m*PHtjAAGx{~dsG0yJh)j7v)&PX;j< z$uR&_6QB{3GPtM!tTja9KqRjOpq>DgpOm4Cx{o&<kc33C{}Rdvz`p@Z@9)qbGiJ=d z-o1O_;NSprb92aKG7-48wiesAZ9{#1{a|4PtgNh%l9B>nUtet9x)tT+<wN$J1OT8F zz<dBz8ik>rY=L1+vdqoR`R=>#k|aAiI#^Lr!ONE~^XAQ)B*~17j3M8N=H}+yw{IUw z^1y)uw6d}q@1F5jm11bkx()T@1OTZR2CS^CP*_+9KR-W&hKAzCjT^AFwZ)MmM-UMa zffrtQ0lB%kgT_fnNI+_8Dh?k$jF_01;jZ5WmMmF<x88coXt^Xw=<e=DQ&STf8X9o= z^l6+scWy-2n!rdzACLWe@-&Qa9qjAt%huLb78Dc+oxi_7TUuIJU0u!Dvu6+Jzh=!E zlH{2)XE=50)KT5ZufP5}hl9?}P98dRh>nhq<J|)ZfC`0zSy@@k%*^DRIdeuDr>T!m zJ(9PKrg9rMZX`**@x~iM7Z(>tl00(c2qj4}=(k|O0^YxWpVzNn=d4+?Mx7*0JxEfi zRPxfLORT7<5OVeERW>&_>ye$6l{M}J1K|Gs`$e6WELk#|SX&H{JgTiqNs^eKpHH<~ z&A`Awp+9{1FiG;&S6|ih@$vED?c2AhR4O@d-aL~eNt@*3$B)z2)|U46_O!RRr=6W0 z9UL6!;^M-vurPlA{rAFFrBaPHsV0#<d-jMrEnd8MG_flClN?}*3O@44Bdo8lXHiiR zZES1^fUd5ttf{GCQ&SVYyu5_1v$HeH%gfo`-p*&Aeb!`2(kA)n(W3*}+S=Ok%9Sg^ zJ~1(I+(}MOP8Ri<KY#vc;{}iuv#_Nw0qW}Nuw}~@WM^k%$BrFHN=ia)Z7mWK5^(I; zF{GxZA}T5hmX?;t$jCrIKmcN6V{z)#DN|ft4`ya&1D3b6wBW0+zCv<xG5}!i+_?tr zf`fw*6%_?fPfy5XGW`Dg?<gxP!-*3o@awO?8jbJd<b>tRmm@GR5H2n*=<Mu7V`C#O zT)2QAe)s{+&CLJ+8yg#hhlfKZlfmELU-(BwMZwL@4QjO-Cr_S)TCE;#3Z4c~q3Ov- zV8XjGJ3E_dwVF$pE)}{12M&-Vw{G3a)YMdx<lAq*ZStO=-IH^3a|g9ww{D%V&&kQr znLEhka%N^`8l13^WMg9^H*DBoFm7~oG^?wtjrv}@c8#H-p#;D=bLQ~&?b}9eRVo!d zJv~Q~j~wmcy4;kBmdoY5b?X+Zs;cPV;6MO$baZ4{Ss6+4&p-cUW@aWWEG)*I<gBbL zVV|6wEc7#H&SY_Mu}-p^o10l*U(dF-HXZ%GefxA`E?v5m?d|QNyrrduH*el#O-&8E zy1In^x8HuFhld9p9UaA^OQlkY@~*Bfwzs$Q&Ye4ScXuC2KFYO8Hu)>Wl`B`0Bo7`u zD0B-KE~HAO;{E&g>EhyIa)SGloRgC?pzZU|KhKVi4q?A`?OIWG@ZdqAzjyB*w{6=- zXJ=<hlEk2(AZBN0i}LR7ZZ2QGT=;7D{=B?AF&B{}iOZHPV?{-UDBrYc69MpvC!Sz% za4^68@=H+`A0N+<kPwE1gwWE`awPd^(k8jn)X6qCHy4dvwQ7~nzw^#JB*~<tq%kMC zxVV@xF)@7Ql~;tUU%#G7Nl83<^r%jcymjlASeHKe<dgj4k3UHE4wY-xtkJuUg@pyb z_~HxU|LwQma@w?M1fVl(f9|>G^n6#WSi!coHum)NFgrV2r|iA=-V?qdAt9s9N9UN5 z41iOoPUV#=S6E+PPd7I=0-#JL<Jq%k+1=gEMT-`VDak`cTU(nBkvn(p6lGt3{k73+ zd3boRv9Xb4@6bAT?py-ksZ*zf|HX?J84(d7ZU6u@Gc#joXed{#SRwMF5fd(<^hh4F z6CY7gQ6zhxk7j0O1i;50dyGn@lEuZvw6(PzH<CL$J9+x_X@-Y~>%>S;PZu^XzWAci zYe|yCyu3VN8x|Hu0E~@|)wzyZt>*dj=lRJepD->ijvgK!Mq`?oWS!yKq!TZVSX*1O zprAlhIxa3wlx^6sfh4(q|Nb!}`KO<LVpLQV6$*ur)vH%ip-?a|Fpy48PI}KeOG``U z=jV$UK|w(SUT^Q-y}~v&Hdg54<KtOZS7-3%YH4X<QBe`2qoeh90!>V^&crLn)C5bC z#7{r{lq9)(_imm)f1b_F%?t<#5aqeKxg^PFo_S_WNFHqBWk}4-%y{zTNfBeP4T+SL z6k)q@<3^n_A0HoX-n^N4d3mg_uQy2eu3fvvl4PAFRHCU#PD)B5Nv5Tx5dedNg4o^N z%?lSU(AwIX0O;=S&W45tR#sM0E|;5}<e@B~42ky4IyyRfz#Cb6xPI!XrwrPeo11gS zj2R3H3Svr13Tta?g^x<5qK}WySdpAaQ*Uc(Bqk<?B$=O|Pnk?6^xL;@*SmWa3I$2> z^Upt@FeGbFyz=t$jM}-oyNe#GQmN?e?M*v7JMP@MlOKKbkzUW%$gEkjbk^YO*RMB7 zvI!=p0W{?c3XMcYMzW`;hh=4DeE8vqb;>L(ELd1rs5i4tOG_h3u3o)*LXf;@(IT<D zQmIr1>t$wUrn4SCckUdmtgI-P%LVaDrPAmt%$%GY;rsH-FAMz#AABJ6qg+Diy`TVq zH%FUbKR-X-y?d7p4Gr}6_BLqa@9$5gQpp=PZipe;$;pXTRaLC1sTuX_MpKXsfEgJX zB2H^-D-#nF>F4K1XJ=<FUc6XmjjUFyxop`o;j2AyJA3vlBO@c}=;%mmYiqi>xiLOI zUcBz?>guAatE=$cy?eLt{p_>P7#SJK1q&98qz!KxB6-Az1_02-#f4>MWmK!xjEIOB z(Dt?0UL#3<{PD*^7akr?viHrAv3JkIC3&Esb}(^ub!BO3DYa2oSI2ADu2HE}>gZEb zQ+4Vb9v-f<(bCb;!OF@?mX?-^qfr_hI&?_qy8V}59UUF4tE=P8nKOq||9dcUXaE2< zk0c>7nT+3j^9{*?*Ol6G{P=N_q(Y$(x*a=qkR)Gv>7@~qvuV>Nk)RVNPK-DX(7WHB zmX@ZopRA3Vni{TKx6YuiLZM(uNr^!}lDvEOE<gP6Lr$48MaNGrm-D;tzSFbUo}3Lq zHfso_fiqqf0R9Ca2*W^ndOBibW3hevcD(=o`$O{a^76vPix<(=)rEx%7vj#HJD4(M z3JMAe@aUtDA~ZA<SFc_jPBj1k?(XiGH*X#Qpt`ymrKP3Aj?o`sVPOag3WArH7i?^7 z(A?aN%a<>ssHh0nuU|Ln=jiB&(9lr$`ubw_?AfrgvO;5HBYyei7nGEg7(I<@Z*Py_ z;9yLjJ{^)IL8Vfmu&@wqZEZuT?j-;r=sluq^xU-%dQasKddJw<*obvvdV2b>dy3|4 zmj>P4-QxcrfBcblc6Ouci4UN(_VFh`twRIas6y{){9^#j4U`KwIXOX+B<$L?3w!qL z8OYQia&mGYm&@Vl>4~169sod3PY+1K($W$SJ@gQiO69QQKA`AE?^iEXdL;&WvIc80 z$X67az3539cTofQry&xJ4cFTE2YQEq@ovPV7?)N6tBmkB<WE<<0hCOD#!QO7l=Sgq z6hkE$`0q#P%@d$ulhVsW0!;W3x;E_4yOZ+s1Ze1kC_ne*-)=CXG%&PI9u6J{5CLEz z{`<o)(*anHB-kW$phEAnR`bI!7Xh5X2!9wx8fH(P#9t8q0e#0T!dfFi761SM07*qo IM6N<$f?p~Rwg3PC literal 0 HcmV?d00001 diff --git a/projects/plugins/jetpack/modules/sharedaddy/sharing-sources.php b/projects/plugins/jetpack/modules/sharedaddy/sharing-sources.php index 05714ac1881f3..be1c1803de480 100644 --- a/projects/plugins/jetpack/modules/sharedaddy/sharing-sources.php +++ b/projects/plugins/jetpack/modules/sharedaddy/sharing-sources.php @@ -1346,6 +1346,22 @@ class Share_X extends Sharing_Source { */ public $short_url_length = 24; + /** + * Constructor. + * + * @param int $id Sharing source ID. + * @param array $settings Sharing settings. + */ + public function __construct( $id, array $settings ) { + parent::__construct( $id, $settings ); + + if ( 'official' === $this->button_style ) { + $this->smart = true; + } else { + $this->smart = false; + } + } + /** * Service name. * @@ -1363,13 +1379,47 @@ public function get_name() { * @return string */ public function get_display( $post ) { - return $this->get_link( - $this->get_process_request_url( $post->ID ), - _x( 'X', 'share to', 'jetpack' ), - __( 'Click to share on X', 'jetpack' ), - 'share=x', - 'sharing-x-' . $post->ID - ); + $via = static::sharing_x_via( $post ); + + if ( $via ) { + $via = 'data-via="' . esc_attr( $via ) . '"'; + } else { + $via = ''; + } + + $related = static::get_related_accounts( $post ); + if ( ! empty( $related ) && $related !== $via ) { + $related = 'data-related="' . esc_attr( $related ) . '"'; + } else { + $related = ''; + } + + if ( $this->smart ) { + $share_url = $this->get_share_url( $post->ID ); + $post_title = $this->get_share_title( $post->ID ); + return sprintf( + '<a href="https://x.com/share" class="twitter-share-button" data-url="%1$s" data-text="%2$s" %3$s %4$s>%5$s</a>', + esc_url( $share_url ), + esc_attr( $post_title ), + $via, + $related, + esc_html__( 'Post', 'jetpack' ) + ); + } else { + if ( + /** This filter is documented in modules/sharedaddy/sharing-sources.php */ + apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'x' ) + ) { + sharing_register_post_for_share_counts( $post->ID ); + } + return $this->get_link( + $this->get_process_request_url( $post->ID ), + _x( 'X', 'share to', 'jetpack' ), + __( 'Click to share on X', 'jetpack' ), + 'share=x', + 'sharing-x-' . $post->ID + ); + } } /** @@ -1435,7 +1485,13 @@ public static function get_related_accounts( $post ) { * Add content specific to a service in the footer. */ public function display_footer() { - $this->js_dialog( $this->shortname, array( 'height' => 350 ) ); + if ( $this->smart ) { + ?> + <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script> + <?php + } else { + $this->js_dialog( $this->shortname, array( 'height' => 350 ) ); + } } /** @@ -1491,6 +1547,15 @@ public function process_request( $post, array $post_data ) { parent::redirect_request( $twitter_url ); } + + /** + * Does this sharing source have a custom style. + * + * @return bool + */ + public function has_custom_button_style() { + return $this->smart; + } } /** diff --git a/projects/plugins/jetpack/modules/sharedaddy/sharing.css b/projects/plugins/jetpack/modules/sharedaddy/sharing.css index 607d6eb8a5989..6eb9705a62df6 100644 --- a/projects/plugins/jetpack/modules/sharedaddy/sharing.css +++ b/projects/plugins/jetpack/modules/sharedaddy/sharing.css @@ -285,8 +285,7 @@ body .sd-content ul li.share-custom.no-icon a span { .sd-social-icon .sd-content ul li.share-x a:before, .sd-social-text .sd-content ul li.share-x a:before, .sd-content ul li.share-x div.option.option-smart-off a:before, -.sd-social-icon-text .sd-content li.share-x a:before, -.sd-social-official .sd-content li.share-x a:before { +.sd-social-icon-text .sd-content li.share-x a:before { content: '\f10e'; } .sd-social-icon .sd-content ul li.share-reddit a:before, diff --git a/projects/plugins/jetpack/modules/sharedaddy/sharing.php b/projects/plugins/jetpack/modules/sharedaddy/sharing.php index 81e40359be497..6a0396f253d4d 100644 --- a/projects/plugins/jetpack/modules/sharedaddy/sharing.php +++ b/projects/plugins/jetpack/modules/sharedaddy/sharing.php @@ -8,6 +8,7 @@ // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files. use Automattic\Jetpack\Assets; +use Automattic\Jetpack\Redirect; use Automattic\Jetpack\Status; if ( ! defined( 'WP_SHARING_PLUGIN_URL' ) ) { @@ -53,7 +54,7 @@ public function sharing_head() { 'modules/sharedaddy/admin-sharing.js' ), array( 'jquery', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable', 'jquery-form' ), - 2, + JETPACK__VERSION, false ); @@ -327,12 +328,6 @@ public function wrapper_admin_page() { * @return void */ public function management_page() { - $sharer = new Sharing_Service(); - $enabled = $sharer->get_blog_services(); - $global = $sharer->get_global_options(); - - $shows = array_values( get_post_types( array( 'public' => true ) ) ); - array_unshift( $shows, 'index' ); if ( ! function_exists( 'mb_stripos' ) ) { echo '<div id="message" class="updated fade"><h3>' . esc_html__( 'Warning! Multibyte support missing!', 'jetpack' ) . '</h3>'; @@ -355,10 +350,6 @@ public function management_page() { if ( isset( $_GET['update'] ) && 'saved' === $_GET['update'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only used to display a message. echo '<div class="updated"><p>' . esc_html__( 'Settings have been saved', 'jetpack' ) . '</p></div>'; } - - if ( ! isset( $global['sharing_label'] ) ) { - $global['sharing_label'] = __( 'Share this:', 'jetpack' ); - } ?> <div class="wrap"> @@ -376,8 +367,57 @@ public function management_page() { do_action( 'pre_admin_screen_sharing' ); ?> - <?php if ( current_user_can( 'manage_options' ) ) : ?> + <?php + $block_availability = Jetpack_Gutenberg::get_cached_availability(); + $is_block_available = (bool) isset( $block_availability['sharing-buttons'] ) && $block_availability['sharing-buttons']['available']; + $is_block_theme = wp_is_block_theme(); + $show_block_message = $is_block_available && $is_block_theme; + + // We either show old services config or the sharing block message. + if ( current_user_can( 'manage_options' ) ) : + $show_block_message ? $this->sharing_block_display() : $this->services_config_display(); + endif; + ?> + </div> + + <script type="text/javascript"> + var sharing_loading_icon = '<?php echo esc_js( admin_url( '/images/loading.gif' ) ); ?>'; + <?php + // phpcs:disable WordPress.Security.NonceVerification.Recommended -- we handle the nonce on the PHP side. + if ( + isset( $_GET['create_new_service'] ) && isset( $_GET['name'] ) && isset( $_GET['url'] ) && isset( $_GET['icon'] ) + && 'true' == $_GET['create_new_service'] // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual + ) : + ?> + jQuery(document).ready(function() { + // Prefill new service box and then open it + jQuery( '#new_sharing_name' ).val( '<?php echo esc_js( sanitize_text_field( wp_unslash( $_GET['name'] ) ) ); ?>' ); + jQuery( '#new_sharing_url' ).val( '<?php echo esc_js( sanitize_text_field( wp_unslash( $_GET['url'] ) ) ); ?>' ); + jQuery( '#new_sharing_icon' ).val( '<?php echo esc_js( sanitize_text_field( wp_unslash( $_GET['icon'] ) ) ); ?>' ); + jQuery( '#add-a-new-service' ).click(); + }); + <?php endif; ?> + </script> + <?php + // phpcs:enable WordPress.Security.NonceVerification.Recommended + } + + /** + * Display services admin UI for settings. + * + * @return void + */ + public function services_config_display() { + $sharer = new Sharing_Service(); + $enabled = $sharer->get_blog_services(); + $global = $sharer->get_global_options(); + $shows = array_values( get_post_types( array( 'public' => true ) ) ); + array_unshift( $shows, 'index' ); + if ( ! isset( $global['sharing_label'] ) ) { + $global['sharing_label'] = __( 'Share this:', 'jetpack' ); + } + ?> <div class="share_manage_options"> <h2><?php esc_html_e( 'Sharing Buttons', 'jetpack' ); ?></h2> <p><?php esc_html_e( 'Add sharing buttons to your blog and allow your visitors to share posts with their friends.', 'jetpack' ); ?></p> @@ -674,33 +714,55 @@ public function management_page() { <input type="hidden" name="_wpnonce" value="<?php echo esc_attr( wp_create_nonce( 'sharing-new_service' ) ); ?>" /> </form> </div> - </div> - - <?php endif; ?> - - - </div> - - <script type="text/javascript"> - var sharing_loading_icon = '<?php echo esc_js( admin_url( '/images/loading.gif' ) ); ?>'; <?php - // phpcs:disable WordPress.Security.NonceVerification.Recommended -- we handle the nonce on the PHP side. - if ( - isset( $_GET['create_new_service'] ) && isset( $_GET['name'] ) && isset( $_GET['url'] ) && isset( $_GET['icon'] ) - && 'true' == $_GET['create_new_service'] // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual - ) : - ?> - jQuery(document).ready(function() { - // Prefill new service box and then open it - jQuery( '#new_sharing_name' ).val( '<?php echo esc_js( sanitize_text_field( wp_unslash( $_GET['name'] ) ) ); ?>' ); - jQuery( '#new_sharing_url' ).val( '<?php echo esc_js( sanitize_text_field( wp_unslash( $_GET['url'] ) ) ); ?>' ); - jQuery( '#new_sharing_icon' ).val( '<?php echo esc_js( sanitize_text_field( wp_unslash( $_GET['icon'] ) ) ); ?>' ); - jQuery( '#add-a-new-service' ).click(); - }); - <?php endif; ?> - </script> + } + + /** + * Display sharing block admin UI for settings. + * + * @return void + */ + public function sharing_block_display() { + $showcase_services = array( + new Share_Tumblr( 'tumblr', array() ), + new Share_Facebook( 'facebook', array() ), + new Share_Email( 'email', array() ), + new Share_Reddit( 'reddit', array() ), + ); + ?> + + <div class="share_manage_options"> + <br class="clearing" /> + <h2><?php esc_html_e( 'Sharing Buttons', 'jetpack' ); ?></h2> + <div class="sharing-block-message__items-wrapper"> + <div> + <p><?php esc_html_e( 'Add sharing buttons to your blog and allow your visitors to share posts with their friends.', 'jetpack' ); ?></p> + + <div class="sharing-block-message__buttons-wrapper"> + <a href="<?php echo esc_url( admin_url( 'site-editor.php?path=%2Fwp_template' ) ); ?>" class="button button-primary"> + <?php esc_html_e( 'Go to the site editor', 'jetpack' ); ?> + </a> + <a href="<?php echo esc_url( Redirect::get_url( 'jetpack-support-sharing-block' ) ); ?>" class="button" target="_blank" rel="noopener noreferrer"> + <?php esc_html_e( 'Learn how to add Sharing Buttons', 'jetpack' ); ?> + </a> + </div> + </div> + <div> + <p><?php esc_html_e( 'Sharing Buttons example:', 'jetpack' ); ?></p> + <div class="sharedaddy sd-sharing-enabled"> + <div class="sd-content"> + <ul class="preview"> + <?php foreach ( $showcase_services as $service ) : ?> + <?php $this->output_preview( $service ); ?> + <?php endforeach; ?> + </ul> + </div> + </div> + </div> + </div> + <br class="clearing" /> + </div> <?php - // phpcs:enable WordPress.Security.NonceVerification.Recommended } } diff --git a/projects/plugins/jetpack/modules/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php b/projects/plugins/jetpack/modules/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php index b3e01a04f3677..6fe06b59e9f97 100644 --- a/projects/plugins/jetpack/modules/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php +++ b/projects/plugins/jetpack/modules/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php @@ -6,7 +6,7 @@ * @since 12.4 */ -use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; use const Automattic\Jetpack\Extensions\Subscriptions\META_NAME_FOR_POST_LEVEL_ACCESS_SETTINGS; /** @@ -191,7 +191,7 @@ public function should_user_see_modal() { $access_level = get_post_meta( $post->ID, '_jetpack_newsletter_access', true ); } require_once JETPACK__PLUGIN_DIR . 'extensions/blocks/premium-content/_inc/subscription-service/include.php'; - $is_accessible_by_everyone = Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY === $access_level || empty( $access_level ); + $is_accessible_by_everyone = Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY === $access_level || empty( $access_level ); if ( ! $is_accessible_by_everyone ) { return false; } diff --git a/projects/plugins/jetpack/package.json b/projects/plugins/jetpack/package.json index ebf7aac2050b1..f188c6877d348 100644 --- a/projects/plugins/jetpack/package.json +++ b/projects/plugins/jetpack/package.json @@ -1,6 +1,6 @@ { "name": "Jetpack", - "version": "13.0.0-a.4", + "version": "13.0.0-a.8", "private": true, "description": "[Jetpack](https://jetpack.com/) is a WordPress plugin that supercharges your self-hosted WordPress site with the awesome cloud power of [WordPress.com](https://wordpress.com).", "homepage": "https://jetpack.com", @@ -123,8 +123,8 @@ "@babel/preset-env": "7.23.5", "@babel/runtime": "7.23.5", "@svgr/webpack": "7.0.0", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.1", "@types/jest": "29.5.10", "@types/react": "18.2.33", diff --git a/projects/plugins/jetpack/readme.txt b/projects/plugins/jetpack/readme.txt index 8bf2374a5a8e6..e148c45e40886 100644 --- a/projects/plugins/jetpack/readme.txt +++ b/projects/plugins/jetpack/readme.txt @@ -1,7 +1,7 @@ === Jetpack - WP Security, Backup, Speed, & Growth === Contributors: automattic, adamkheckler, adrianmoldovanwp, aduth, akirk, allendav, alternatekev, andy, annamcphee, annezazu, apeatling, arcangelini, azaozz, barry, batmoo, beaulebens, bindlegirl, biskobe, bjorsch, blobaugh, brbrr, cainm, cena, cfinke, cgastrell, chaselivingston, chellycat, clickysteve, csonnek, danielbachhuber, daniloercoli, davoraltman, delawski, designsimply, dllh, drawmyface, dsmart, dzver, ebinnion, egregor, eliorivero, enej, eoigal, erania-pinnera, ethitter, fgiannar, gcorne, georgestephanis, gibrown, goldsounds, hew, hugobaeta, hypertextranch, iammattthomas, iandunn, jasmussen, jblz, jeffgolenski, jeherve, jenhooks, jenia, jessefriedman, jgs, jkudish, jmdodd, joanrho, johnjamesjacoby, jshreve, kbrownkd, keoshi, koke, kraftbj, lancewillett, leogermani, lhkowalski, lschuyler, macmanx, martinremy, matt, mattwiebe, matveb, maverick3x6, mcsf, mdawaffe, mdbitz, MichaelArestad, migueluy, mikeyarce, mkaz, nancythanki, nickmomrik, nunyvega, obenland, oskosk, pento, professor44, rachelsquirrel, rdcoll, renatoagds, retrofox, richardmtl, richardmuscat, robertbpugh, roccotripaldi, ryancowles, samhotchkiss, samiff, scarstocea, scottsweb, sdixon194, sdquirk, sermitr, simison, stephdau, thehenridev, tmoorewp, tyxla, Viper007Bond, westi, williamvianas, wpkaren, yoavf, zinigor Tags: Security, backup, Woo, malware, scan, spam, CDN, search, social -Stable tag: 12.7 +Stable tag: 12.9.1 Requires at least: 6.3 Requires PHP: 7.0 Tested up to: 6.4 @@ -293,72 +293,17 @@ Jetpack Backup can do a full website migration to a new host, migrate theme file == Changelog == -### 12.9-beta - 2023-12-03 +### 13.0-a.7 - 2023-12-20 #### Enhancements -- Added subscribers count to pre- and post- publish panels when publishing posts in Newsletter Categories. -- AI Assistant: Updated AI Assistant to display an upgrade banner when the feature endpoint returns with 'quota exceeded'. -- AI Assistant: Updated the AI Assistant block to display the upgrade banner only once a block is selected. -- Blocks: Added capability for editing Subscription block placeholder text and button label. -- Blocks: Added the Jetpack Sharing Buttons block. -- Blogroll: Allowed non-WP.com sites to be suggested. -- CSS Concatenation: Avoid optimizing CSS loading when less than 2 modules that require it are active. -- Jetpack AI: Enabled the AI Assistant usage panel. -- Likes: Updated the likes popover design and added RTL support. -- My Jetpack: Added Creator to My Jetpack overview. -- Newsletters: Updated the pre-publish and post-publish panels to display the newsletter categories that the post will be sent to. -- Paid Content Block: Added support for selecting multiple plans. -- Subscribe Block: Improved the redirect logic after confirming a subscriptions. -- Subscribe Modal: Added a subscribe modal toggle to the Newsletter settings. -- Subscribe Modal: The modal is not shown at all after being dismissed, not just limited to the post it was dismissed on. -- Subscribe modal: Updated the modal to not show when previewing post or theme. -- VideoPress: Added support for gated content. -- WoA: Added "Subscribers" and "My profile" under the "Users" menu in the Calypso sidebar. -- WoA: Updated the wording on the profile menu for WoA sites using the classic style. +- Sharing Buttons Block: update the admin's setting screen when the sharing block is available. #### Improved compatibility -- Added a check for connected plugins before cleaning up plugin options or uninstalling Jetpack. -- Block Editor: Dequeued editor assets when they aren't in use. -- Blocks: Fixed lack of spacing for the Paywall block in some themes. -- Google Fonts: Resolved occasional bug resulting in fatal errors on PHP 8 with latest Gutenberg. -- Improved the consistency of the "Users" admin menu across all environments. -- Subscribe Modal: Fixed lack of spacing in the modal for some themes. -- Updated PHP version reqirements to PHP 7.0 or newer. -- Updated WordPress version requirements to WordPress 6.3. +- Sharing Buttons: add the official X button to the list of supported services. #### Bug fixes -- Added missing BLOCK_NAME constant to SimplePayments block. -- AI Assistant: Fixed an AI error sometimes being rendered for prompts marked unclear. -- Block Editor: Fixed console errors being thrown for Jetpack blocks inside the Full Site Editor. -- Contact Form: Prevented errors when a saved submitted contact form is requested but does not exist anymore. -- Custom-CSS: Disabled loading `@import` directives from the filesystem. `@import` of CSS from URLs can still be done. -- Dashboard: Fixed the display of Subscriptions and WordPress.com Toolbar controls when the user is not connected to WordPress.com. -- Dashboard: Fixed the display of the Auto-sharing feature toggle when the user is not connected to WordPress.com. -- Dashboard: Fixed the display of the settings for Markdown for comments. -- EU Cookie Widget: Moved away from deprecated jQuery methods. -- Fixed all Google font definitions being printed in the head, instead only printing fonts that are used in global styles or required by block settings. -- Fixed a PHP Warning triggered when WooCommerce templates were not found due to a name change. -- Fixed fatal error triggered by not checking get_product_list() result correctly. -- Fixed sending email preview when content in the editor is different from the latest version in the database. -- Fixed wrong like count in the like dialog after liking. -- Font Library: Fixed PHP warnings that happen when the font name is not defined. -- Google Fonts: Added filtering for old google fonts data in the user's global styles. -- Media: Fixed VideoPress videos and media length not being displayed when available. -- Mobile: Ensured text is always visible in Contact Info block on mobile. -- Mobile: Fix a regression preventing correct block registration on mobile. -- Mobile: Prevented converted video blocks from displaying empty thumbnails on mobile. -- Monetize: Fixed membership products resolver not filtering tiers correctly. -- Monetize: Updated the link to the plans page. -- Related Posts: Ensured the Related Posts Block can be displayed properly. -- Related Posts Block: Fixed thumbnails opening in the same tab. -- Shortcode embeds: Fixed and updated the display of Gravatars and Gravatar profiles. -- Subscribe Block: Fix display in the editor. -- Subscribe Block: Fixed incorrect redirects from the block when shown outside of a post page. -- Subscribe Block: Fixed the button in a new line option not working. -- Subscribe Modal: Fixed the issue with the block being shown to subscribers. -- Subscribe Widget: Fixed nonce validation. -- VaultPress: Fixed an issue with the VaultPress submenu not being registered when the standalone plugin is inactive and the product is active. -- WoA: Added back the "Stats" menu item for WoA sites in Calypso. -- WoA: Restored Woo Express free trial upgrade JITM. +- My Plan: Fix JS errors due to nested anchor tags. +- Payments Block: show an error message when unable to render payment button. +- Subscribers: fix the subscriber count display if above 1000 subscribers. -------- diff --git a/projects/plugins/jetpack/tests/php/modules/subscriptions/test_class.jetpack-subscriptions.php b/projects/plugins/jetpack/tests/php/modules/subscriptions/test_class.jetpack-subscriptions.php index 45158e9f014a9..11338c1874a0f 100644 --- a/projects/plugins/jetpack/tests/php/modules/subscriptions/test_class.jetpack-subscriptions.php +++ b/projects/plugins/jetpack/tests/php/modules/subscriptions/test_class.jetpack-subscriptions.php @@ -6,7 +6,7 @@ require_once JETPACK__PLUGIN_DIR . 'extensions/blocks/subscriptions/subscriptions.php'; use Automattic\Jetpack\Extensions\Premium_Content\JWT; -use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service; +use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Abstract_Token_Subscription_Service; use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\WPCOM_Offline_Subscription_Service; use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\WPCOM_Online_Subscription_Service; use Tests\Automattic\Jetpack\Extensions\Premium_Content\Test_Jetpack_Token_Subscription_Service; @@ -439,7 +439,7 @@ public function test_posts_in_loop_have_the_right_access() { setup_postdata( $post ); $level = get_post_meta( $current_post_id, META_NAME_FOR_POST_LEVEL_ACCESS_SETTINGS, true ); if ( empty( $level ) ) { - $level = Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; + $level = Abstract_Token_Subscription_Service::POST_ACCESS_LEVEL_EVERYBODY; } $this->assertEquals( $level, Jetpack_Memberships::get_post_access_level() ); diff --git a/projects/plugins/jetpack/tests/php/sync/test_class.jetpack-sync-options.php b/projects/plugins/jetpack/tests/php/sync/test_class.jetpack-sync-options.php index 8fdde865efc62..1bc8b4a7f8a49 100644 --- a/projects/plugins/jetpack/tests/php/sync/test_class.jetpack-sync-options.php +++ b/projects/plugins/jetpack/tests/php/sync/test_class.jetpack-sync-options.php @@ -243,6 +243,7 @@ public function test_sync_default_options() { 'wpcom_reader_views_enabled' => true, 'wpcom_site_setup' => '', 'jetpack_verbum_subscription_modal' => true, + 'wpcom_ai_site_prompt' => '', ); $theme_mod_key = 'theme_mods_' . get_option( 'stylesheet' ); diff --git a/projects/plugins/jetpack/to-test.md b/projects/plugins/jetpack/to-test.md index e6b5294dbc806..558a0f0f8267d 100644 --- a/projects/plugins/jetpack/to-test.md +++ b/projects/plugins/jetpack/to-test.md @@ -1,4 +1,4 @@ -## Jetpack 12.8 +## Jetpack 13.0 ### Before you start: @@ -6,106 +6,21 @@ - Use the "Debug Bar" or "Query Monitor" WordPress plugins to help make PHP notices and warnings more noticeable and report anything of note you see. ### AI Assistant - -[Beta extension] -- Inside the editor, click the 'Jetpack' icon and open the 'AI Assistant' section. -- There should be a usage meter indicating how many requests you've used. -- Add/use an AI block, save the post/draft, and refresh the page. -- The usage counter should increase. -- If you're not on an AI plan, a visual usage bar should be shown along with an 'Upgrade' button. -- Clicking the 'Upgrade' button should take you to the appropriate upgrade page. -- After completing the flow and purchasing the upgrade, you should no longer see the visual usage indicator or the upgrade button. Instead a message should be displayed about you having unlimited requests. - -AI Extensions are now disabled for empty blocks preventing unnecessary requests. - -- Add an empty paragraph block. Adding a few spaces will work too. -- Click the AI Extension button on the block toolbar. -- There should be a notice indicating you need to add content before the options become enabled. - -You can use the new `jetpack_ai_enabled` filter to register the plugin. - -- Add the following filter to your site: `add_filter( 'jetpack_ai_enabled', '__return_false' );`. -- AI features should now become unavailable on your site. - -### SEO/Sharing - -Character counts for SEO Title and SEO Description are now also displayed when over limit, instead of just getting a warning message. - -- Edit a post. -- In the editor, click the 'Jetpack' icon and expand the 'SEO' section. -- Click 'Activate Jetpack SEO' button if not already activated. -- Type into the 'SEO Title' field. -- Once you go past 70 characters, ensure you continue to see the current character count at the end '(xx used)', in addition to the warning. -- Verify the same is true for 'SEO Description'. - -### Subscriptions - -Site administrators can now see the subscribe modal/popup for demo/debugging purposes. - -- Go to Jetpack > Settings > Newsletters and ensure the subscriber modal is enabled. -- While logged in as an admin, go to a frontend post without a paywall or limited access, scroll, and confirm the modal loads. - -Not logged users shoudl see a 'retrieve subscriptions' link. [33656] - -### WordAds - -You should now be able to use Ad block before the module is enabled. - -- Navigate to `/wp-admin/admin.php?page=jetpack_modules` and make sure the Ads module is disabled. -- Make sure you don't have a plan that supports Ads. -- Create a new post. -- You should not see the Ad block in the blocks inserter. -- Purchase the 'Jetpack Complete' plan but make sure the Ads module remains disabled. -- Create a new post. You should now see the Ad block in the inserter. -- Add the Ad block to your post. It should contain an 'Activate WordAds' button. -- Activate the module and check that the form works as expected. - -### Scan - -The scan module can now be disabled using a dedicated filter. - -- Add the following filter to your site: `add_filter( 'jetpack_disable_scan', '__return_true' );`. -- Scan module should be distabled on your site. - -### Add additional properties to WooCommerce analytics checkout and purchase events - -#### New properties - - - To the `woocommerceanalytics_product_checkout` event: - `shipping_option`: the selected shipping option - `products_count`: number of products included in the cart - `coupon_used`: if the coupon was used (boolean) - `order_value`: the order value/total - `template_used`: if the proceed from cart to checkout action has happened on a regular cart page or powered by the template - `additional_blocks`: if there are additional blocks on the cart page - `store_currency`: the currency used in the store - - - To the `woocommerceanalytics_product_purchase` event - `products_count`: number of products included in the cart - `coupon_used`: if the coupon was used (boolean) - `order_value`: the order value/total - `template_used`: if the proceed from cart to checkout action has happened on a regular cart page or powered by the template - `additional_blocks`: if there are additional blocks on the cart page - `store_currency`: the currency used in the store - -#### Testing instructions - -- Ensure your store is set up so it can be tracked. -- Ensure your site is using the Checkout block. -- Set up multiple shipping methods on your store. -- Install [Multiple Packages for WooCommerce](https://wordpress.org/plugins/multiple-packages-for-woocommerce/). Go to the settings (WooCommerce -> Settings -> Multiple Packages) and set the grouping option to "Product (individual)". -- Install the Tracks Vigilante extension (optional) -- For each of the following scenarios, view the Checkout page also complete the checkout process, ensuring the `woocommerceanalytics_product_checkout` and `woocommerceanalytics_product_purchase` events fire with the correct properties (Except `shipping_option` on the purchase event) -- Add multiple items to your cart (including a virtual item), go to the Checkout page and change the shipping option on each of them. -- Check out and check the events are correct and the correct shipping option is tracked, ensure a shipping option is not tracked for the virtual item. -- Do this again, this time check out with a coupon. -- Go to Appearance -> Editor and edit the Checkout template. Add some extra blocks to the template. -- Go to the Checkout page again and ensure the extra blocks you added are in the `additional_blocks` property. -- Downgrade your WooCommerce version to 7.8.2 and ensure WooCommerce Blocks is disabled. -- Add products to your cart and check out. Ensure the `template_used` value is false (Cart/Checkout templates were not in use in this version). -- Go to the Checkout page (Pages -> Checkout) and add extra blocks to the Checkout page. -- Go to the Checkout block and ensure the additional blocks you added are in the `additional_blocks` property. -- Change the checkout page to use the shortcode (`[woocommerce_checkout]`) and repeat these steps. Ensure the correct value is tracked for each event. **Note that the `checkout_page_contains_cart_shortcode` property is stored in a transient so this will be incorrect if changing, but it has been tested in another PR and is known to be working.** +NOTE: keep in mind, all the following should be tested on mobile views as well. + +- Have AI enabled on your site +- Insert an AI Assistant block, confirm: + - Initially it shows a single "Cancel" button, clicking it will remove the block + - Once text is typed in the input, "Cancel" button will toggle for main prompt action "Generate" + - Once AI has responded, suggestion actions (icon buttons) show: + - "Back to edit": focus back at the text input (also triggered by simply editing the input text) + - "Discard": rejects the AI suggestion and removes the AI Assistant block + - "Regenerate": requests the same prompt to the AI + - "Accept": accepts the suggestion (turning it into its own block) and removes the AI Assistant +- Invoke the AI Assistant on already existing content, see that it behaves consistently with the above +- Use some of the one-click AI actions on already existing content (translate, summarize, etc) + - Once action is done the described suggestion actions show, but there is no "Back to edit" and "Regenerate" is disabled +- When content is larger than viewport, AI Assistant block will remain floating at the bottom of the viewport (desktop only, on mobile it remains fixed at the top) ### And More! diff --git a/projects/plugins/migration/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/migration/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/migration/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/migration/composer.lock b/projects/plugins/migration/composer.lock index afb440b25aa18..281738012625f 100644 --- a/projects/plugins/migration/composer.lock +++ b/projects/plugins/migration/composer.lock @@ -1405,7 +1405,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1437,7 +1437,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/mu-wpcom-plugin/CHANGELOG.md b/projects/plugins/mu-wpcom-plugin/CHANGELOG.md index 38b0e91af3ddc..a48277eb998ed 100644 --- a/projects/plugins/mu-wpcom-plugin/CHANGELOG.md +++ b/projects/plugins/mu-wpcom-plugin/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 2.0.8 - 2023-12-20 +### Changed +- Internal updates. + +## 2.0.7 - 2023-12-15 +### Changed +- Version bump [#34648] + ## 2.0.6 - 2023-12-14 ### Changed - Updated package dependencies. [#34559] diff --git a/projects/plugins/mu-wpcom-plugin/composer.json b/projects/plugins/mu-wpcom-plugin/composer.json index 45eb52ac2c286..04afbbfaf1ef3 100644 --- a/projects/plugins/mu-wpcom-plugin/composer.json +++ b/projects/plugins/mu-wpcom-plugin/composer.json @@ -46,6 +46,6 @@ ] }, "config": { - "autoloader-suffix": "d9d132a783958a00a2c7cccff60ca42d_jetpack_mu_wpcom_pluginⓥ2_0_6" + "autoloader-suffix": "d9d132a783958a00a2c7cccff60ca42d_jetpack_mu_wpcom_pluginⓥ2_0_8" } } diff --git a/projects/plugins/mu-wpcom-plugin/composer.lock b/projects/plugins/mu-wpcom-plugin/composer.lock index 84949e110cb0e..e7ea3e8b2b0f9 100644 --- a/projects/plugins/mu-wpcom-plugin/composer.lock +++ b/projects/plugins/mu-wpcom-plugin/composer.lock @@ -12,7 +12,7 @@ "dist": { "type": "path", "url": "../../packages/jetpack-mu-wpcom", - "reference": "208bc96ac854f49e4793bc0d3665ee5d1ed970f7" + "reference": "67196edaad741f50bdaa56fbe52cb9c61a583c04" }, "require": { "php": ">=7.0" @@ -33,7 +33,7 @@ }, "autotagger": true, "branch-alias": { - "dev-trunk": "5.4.x-dev" + "dev-trunk": "5.5.x-dev" }, "textdomain": "jetpack-mu-wpcom", "version-constants": { diff --git a/projects/plugins/mu-wpcom-plugin/mu-wpcom-plugin.php b/projects/plugins/mu-wpcom-plugin/mu-wpcom-plugin.php index 046a6847d8bec..552b49b1eceb4 100644 --- a/projects/plugins/mu-wpcom-plugin/mu-wpcom-plugin.php +++ b/projects/plugins/mu-wpcom-plugin/mu-wpcom-plugin.php @@ -3,7 +3,7 @@ * * Plugin Name: WordPress.com Features * Description: Test plugin for the jetpack-mu-wpcom package - * Version: 2.0.6 + * Version: 2.0.8 * Author: Automattic * License: GPLv2 or later * Text Domain: jetpack-mu-wpcom-plugin diff --git a/projects/plugins/mu-wpcom-plugin/package.json b/projects/plugins/mu-wpcom-plugin/package.json index 58f3a87f6d9cd..3517cbabf805b 100644 --- a/projects/plugins/mu-wpcom-plugin/package.json +++ b/projects/plugins/mu-wpcom-plugin/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@automattic/jetpack-mu-wpcom-plugin", - "version": "2.0.6", + "version": "2.0.8", "description": "Test plugin for the jetpack-mu-wpcom package", "homepage": "https://jetpack.com", "bugs": { diff --git a/projects/plugins/protect/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/protect/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/protect/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/protect/composer.lock b/projects/plugins/protect/composer.lock index 38fa45a74fd2e..10b0a760de977 100644 --- a/projects/plugins/protect/composer.lock +++ b/projects/plugins/protect/composer.lock @@ -1318,7 +1318,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1350,7 +1350,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/search/changelog/add-stats-passing-utm-parameters b/projects/plugins/search/changelog/add-stats-passing-utm-parameters new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/search/changelog/add-stats-passing-utm-parameters @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/search/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/search/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/search/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/search/composer.lock b/projects/plugins/search/composer.lock index 64e8f37a9107a..e2fdf34153ffc 100644 --- a/projects/plugins/search/composer.lock +++ b/projects/plugins/search/composer.lock @@ -1407,7 +1407,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1439,7 +1439,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/social/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/social/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/social/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/social/changelog/renovate-major-js-unit-testing-packages b/projects/plugins/social/changelog/renovate-major-js-unit-testing-packages new file mode 100644 index 0000000000000..c47cb18e82997 --- /dev/null +++ b/projects/plugins/social/changelog/renovate-major-js-unit-testing-packages @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/social/composer.lock b/projects/plugins/social/composer.lock index f31d5a979e6a7..bd395c1ca65ab 100644 --- a/projects/plugins/social/composer.lock +++ b/projects/plugins/social/composer.lock @@ -1338,7 +1338,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1370,7 +1370,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/social/package.json b/projects/plugins/social/package.json index 9aae71fb56843..374e16ae7a9fc 100644 --- a/projects/plugins/social/package.json +++ b/projects/plugins/social/package.json @@ -49,8 +49,8 @@ "@babel/core": "7.23.5", "@babel/preset-env": "7.23.5", "@babel/runtime": "7.23.5", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@types/react": "18.2.33", "@types/react-dom": "18.2.14", "@wordpress/browserslist-config": "5.30.0", diff --git a/projects/plugins/starter-plugin/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/starter-plugin/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/starter-plugin/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/starter-plugin/changelog/renovate-major-js-unit-testing-packages b/projects/plugins/starter-plugin/changelog/renovate-major-js-unit-testing-packages new file mode 100644 index 0000000000000..c47cb18e82997 --- /dev/null +++ b/projects/plugins/starter-plugin/changelog/renovate-major-js-unit-testing-packages @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/starter-plugin/composer.lock b/projects/plugins/starter-plugin/composer.lock index 2d13c47f63983..20b85c88841e2 100644 --- a/projects/plugins/starter-plugin/composer.lock +++ b/projects/plugins/starter-plugin/composer.lock @@ -1261,7 +1261,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1293,7 +1293,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/projects/plugins/starter-plugin/package.json b/projects/plugins/starter-plugin/package.json index df58c69e79b49..902f5431891f5 100644 --- a/projects/plugins/starter-plugin/package.json +++ b/projects/plugins/starter-plugin/package.json @@ -41,8 +41,8 @@ "@babel/core": "7.23.5", "@babel/preset-env": "7.23.5", "@babel/runtime": "7.23.5", - "@testing-library/dom": "8.20.1", - "@testing-library/react": "13.4.0", + "@testing-library/dom": "9.3.3", + "@testing-library/react": "14.1.2", "@wordpress/browserslist-config": "5.30.0", "babel-jest": "29.4.3", "concurrently": "7.6.0", diff --git a/projects/plugins/videopress/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint b/projects/plugins/videopress/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/videopress/changelog/add-wpcom_ai_site_prompt-option-settings-endpoint @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + + diff --git a/projects/plugins/videopress/composer.lock b/projects/plugins/videopress/composer.lock index 000823237d652..a319c4190b8d2 100644 --- a/projects/plugins/videopress/composer.lock +++ b/projects/plugins/videopress/composer.lock @@ -1261,7 +1261,7 @@ "dist": { "type": "path", "url": "../../packages/sync", - "reference": "1336c2b2d1ca4b780142c047150ec14b00372167" + "reference": "7a318d1c460f1b36704856054e5a83455dc434d7" }, "require": { "automattic/jetpack-connection": "@dev", @@ -1293,7 +1293,7 @@ "link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}" }, "branch-alias": { - "dev-trunk": "2.2.x-dev" + "dev-trunk": "2.3.x-dev" } }, "autoload": { diff --git a/tools/cli/package.json b/tools/cli/package.json index 852960dd4a908..9a67fc4f4de68 100644 --- a/tools/cli/package.json +++ b/tools/cli/package.json @@ -46,6 +46,6 @@ }, "devDependencies": { "jest": "29.7.0", - "jest-extended": "2.0.0" + "jest-extended": "4.0.2" } } diff --git a/tools/jetpack-live-branches/jetpack-live-branches.user.js b/tools/jetpack-live-branches/jetpack-live-branches.user.js index 627cdbd60b7ea..d75c947b5b5e8 100644 --- a/tools/jetpack-live-branches/jetpack-live-branches.user.js +++ b/tools/jetpack-live-branches/jetpack-live-branches.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Jetpack Live Branches // @namespace https://wordpress.com/ -// @version 1.30 +// @version 1.31 // @description Adds links to PRs pointing to Jurassic Ninja sites for live-testing a changeset // @grant GM_xmlhttpRequest // @connect jurassic.ninja @@ -89,7 +89,6 @@ const host = 'https://jurassic.ninja'; const currentBranch = jQuery( '.head-ref:first' ).text(); - const branchIsForked = currentBranch.includes( ':' ); const branchStatus = $( '.gh-header-meta .State' ).text().trim(); const repo = determineRepo(); @@ -101,11 +100,6 @@ </a></p> `; appendHtml( markdownBody, contents ); - } else if ( branchIsForked ) { - appendHtml( - markdownBody, - "<p><strong>This branch can't be tested live because it comes from a forked version of this repo.</strong></p>" - ); } else if ( ! repo ) { appendHtml( markdownBody, diff --git a/tools/js-tools/package.json b/tools/js-tools/package.json index 9a9ac95bfcaf7..0ccb18ee6e410 100644 --- a/tools/js-tools/package.json +++ b/tools/js-tools/package.json @@ -19,7 +19,7 @@ "@octokit/auth-token": "4.0.0", "@octokit/rest": "19.0.13", "@rushstack/eslint-patch": "1.3.3", - "@testing-library/jest-dom": "5.17.0", + "@testing-library/jest-dom": "6.1.5", "@typescript-eslint/eslint-plugin": "6.7.5", "@typescript-eslint/parser": "6.7.5", "@wordpress/eslint-plugin": "17.4.0", diff --git a/tools/release-plugin.sh b/tools/release-plugin.sh index 13c63582779c5..6d294f3fed549 100755 --- a/tools/release-plugin.sh +++ b/tools/release-plugin.sh @@ -200,9 +200,27 @@ done read -r -s -p $'Edit all the changelog entries you want (in a separate terminal or your text editor of choice (make sure to save)), then press enter when finished to continue the release process.' echo "" +for PLUGIN in "${!PROJECTS[@]}"; do + # check if the plugin even has a readme.txt file. + if [[ ! -e "$BASE/projects/$PLUGIN/readme.txt" ]]; then + yellow "$PLUGIN has no readme.txt file, skipping." + continue + fi + yellow "Updating the readme.txt file for $PLUGIN." + ARGS=() + # Add alpha and beta flags. + VERSION="${PROJECTS[$PLUGIN]}" + case $VERSION in + *-a* ) ARGS+=('-a');; + *-beta ) ARGS+=('-b');; + * ) ARGS+=('-s');; + esac + pnpm jetpack release "$PLUGIN" readme "${ARGS[@]}" +done + yellow "Committing changes." git add --all -git commit -am "Changelog edits." +git commit -am "Changelog and readme.txt edits." # If we're releasing Jetpack and it's a beta, amend the readme.txt if [[ -v PROJECTS["plugins/jetpack"] && "${PROJECTS[plugins/jetpack]}" == *-beta ]]; then @@ -281,7 +299,7 @@ rm .github/files/TEMP_BACKPORT_RELEASE_CHANGES.md yellow "Release script complete! Next steps: " echo -e "\t1. Merge the above PR into trunk." -echo -e "\t2. On trunk, start a new branch and make any changes you want to CHANGELOG.md." -echo -e "\t3. After merging the changelog edit PR, cherry pick that to the release branch." -echo -e "\t4. After the changes make it to the mirror repo, conduct a GitHub release." -echo -e "\t5. Then run ./tools/deploy-to-svn.sh <plugin-name> <tag> to deploy to SVN." +echo -e "\t2. If this is NOT the Jetpack core plugin, the release will shortly be tagged to GitHub and released to SVN." +echo -e "\t3. You can then smoke test the release and use .tools/stable-tag.sh <plugin> to update the stable tag, and you're done!" +echo -e "\t4. If you are releasing Jetpack-the-plugin, after the changes make it to the mirror repo, conduct a GitHub release." +echo -e "\t5. Then run ./tools/deploy-to-svn.sh <plugin-name> <tag> to deploy to SVN, smoke test, and flip stable tag."