diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aff7200c..2ac9ee1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [4.0.0] (UPCOMING) +## [4.0.0] (2026-10-12) ### Added * Stats page for viewing snippet totals and various snippet breakdowns. diff --git a/package-lock.json b/package-lock.json index 29dbebaca..503890f93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "code-snippets", - "version": "4.0.0-beta.3", + "version": "4.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "code-snippets", - "version": "4.0.0-beta.3", + "version": "4.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@codemirror/fold": "^0.19.4", diff --git a/package.json b/package.json index f20cc6920..d1265a56b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "code-snippets", "description": "Manage code snippets running on a WordPress-powered site through a graphical interface.", "homepage": "https://codesnippets.pro", - "version": "4.0.0-beta.3", + "version": "4.0.0", "main": "src/dist/edit.js", "directories": { "test": "tests" diff --git a/src/code-snippets.php b/src/code-snippets.php index d4e59c8c9..940595a10 100644 --- a/src/code-snippets.php +++ b/src/code-snippets.php @@ -8,11 +8,11 @@ * License: GPL-2.0-or-later * License URI: license.txt * Text Domain: code-snippets - * Version: 4.0.0-beta.3 + * Version: 4.0.0 * Requires PHP: 7.4 * Requires at least: 5.5 * - * @version 4.0.0-beta.3 + * @version 4.0.0 * @package Code_Snippets * @author Shea Bunge * @copyright 2012-2026 Code Snippets Pro @@ -37,7 +37,7 @@ * * @const string */ - define( 'CODE_SNIPPETS_VERSION', '4.0.0-beta.3' ); + define( 'CODE_SNIPPETS_VERSION', '4.0.0' ); /** * The full path to the main file of this plugin. diff --git a/src/css/common/_demo.scss b/src/css/common/_demo.scss index b5ce9765e..1bbc005fc 100644 --- a/src/css/common/_demo.scss +++ b/src/css/common/_demo.scss @@ -77,6 +77,18 @@ } } +.wp-core-ui .button.demo-callout__close { + position: absolute; + inset-block-start: 8px; + inset-inline-end: 8px; + color: var(--cs-color-text-secondary); + text-decoration: none; + + &:hover:not(:disabled) { + color: var(--cs-color-text); + } +} + .demo-callout__step { display: block; margin-block-end: 6px; diff --git a/src/js/components/FeedbackReporter/FeedbackForm.tsx b/src/js/components/FeedbackReporter/FeedbackForm.tsx index 3dd3c7e76..d6395e925 100644 --- a/src/js/components/FeedbackReporter/FeedbackForm.tsx +++ b/src/js/components/FeedbackReporter/FeedbackForm.tsx @@ -9,8 +9,8 @@ import type { FeedbackConfig, FeedbackDraft } from '../../types/Feedback' const TYPE_OPTIONS = [ { label: __('Choose one…', 'code-snippets'), value: '' }, - { label: __('Bug — something is broken', 'code-snippets'), value: 'bug' }, - { label: __('Feature request — something is missing', 'code-snippets'), value: 'feature' }, + { label: __('Bug: something is broken', 'code-snippets'), value: 'bug' }, + { label: __('Feature request: something is missing', 'code-snippets'), value: 'feature' }, { label: __('General feedback', 'code-snippets'), value: 'feedback' } ] diff --git a/src/js/components/ManageMenu/AiAgentDemo/AiAgentDemo.tsx b/src/js/components/ManageMenu/AiAgentDemo/AiAgentDemo.tsx index c36bd7794..5dd9ade30 100644 --- a/src/js/components/ManageMenu/AiAgentDemo/AiAgentDemo.tsx +++ b/src/js/components/ManageMenu/AiAgentDemo/AiAgentDemo.tsx @@ -100,7 +100,7 @@ const AiAgentDemoPage: React.FC = () => {
{STAGE_ANNOUNCEMENTS[stage]}
- + diff --git a/src/js/components/ManageMenu/AiAgentDemo/DemoUpsell.tsx b/src/js/components/ManageMenu/AiAgentDemo/DemoUpsell.tsx index bfc8ad75b..69d3a849e 100644 --- a/src/js/components/ManageMenu/AiAgentDemo/DemoUpsell.tsx +++ b/src/js/components/ManageMenu/AiAgentDemo/DemoUpsell.tsx @@ -4,9 +4,9 @@ import { DemoUpsell } from '../../common/demo/DemoUpsell' export const AiAgentDemoUpsell: React.FC<{ onReplay: VoidFunction }> = ({ onReplay }) =>

{__('The whole walkthrough was scripted and ran inside this plugin. No prompt or snippet left your site, and none were added to it.', 'code-snippets')}

-

{__('In Code Snippets Pro the AI Agent does all of this for whatever you ask it to build, and the snippets it writes are real — saved to your site inactive, until you have read them and switched them on.', 'code-snippets')}

+

{__('In Code Snippets Pro, the AI Agent does all of this for whatever you ask it to build, and the snippets it writes are real. They are saved to your site switched off, so nothing runs until you have read them and turned them on.', 'code-snippets')}

diff --git a/src/js/components/ManageMenu/AiAgentDemo/callouts.ts b/src/js/components/ManageMenu/AiAgentDemo/callouts.ts index c9884711d..8433fb500 100644 --- a/src/js/components/ManageMenu/AiAgentDemo/callouts.ts +++ b/src/js/components/ManageMenu/AiAgentDemo/callouts.ts @@ -12,12 +12,12 @@ const STEPS: Record = { ask: { step: __('Step 1 of 5', 'code-snippets'), title: __('Ask in plain English', 'code-snippets'), - body: __('No syntax to learn and no boilerplate to copy — describe what you want the site to do, and the agent works out what that means in code.', 'code-snippets') + body: __('No syntax to learn and no boilerplate to copy. Describe what you want the site to do, and the agent works out what that means in code.', 'code-snippets') }, plan: { step: __('Step 2 of 5', 'code-snippets'), title: __('Sent for planning', 'code-snippets'), - body: __('Your request goes to Code Snippets Cloud, which works out what needs building — and whether that is one snippet or several — before writing anything.', 'code-snippets') + body: __('Your request goes to Code Snippets Cloud, which works out what needs building, whether that is one snippet or several, before writing anything.', 'code-snippets') }, approve: { step: __('Step 3 of 5', 'code-snippets'), diff --git a/src/js/components/ManageMenu/AiAgentDemo/demoScript.ts b/src/js/components/ManageMenu/AiAgentDemo/demoScript.ts index 8f5c98f0b..800216e85 100644 --- a/src/js/components/ManageMenu/AiAgentDemo/demoScript.ts +++ b/src/js/components/ManageMenu/AiAgentDemo/demoScript.ts @@ -52,7 +52,7 @@ export const getRefinementPrompt = (siteName: string): string => siteName ) -export const DEMO_REFINEMENT_REPLY = __('Done — the banner now greets visitors by name and uses a warmer gradient.', 'code-snippets') +export const DEMO_REFINEMENT_REPLY = __('Done. The banner now greets visitors by name and uses a warmer gradient.', 'code-snippets') /** * Escape a value for embedding inside a single-quoted PHP string literal. diff --git a/src/js/components/ManageMenu/BlueprintsDemo/BlueprintsDemo.tsx b/src/js/components/ManageMenu/BlueprintsDemo/BlueprintsDemo.tsx index fc1a9d7c9..4f2eed02b 100644 --- a/src/js/components/ManageMenu/BlueprintsDemo/BlueprintsDemo.tsx +++ b/src/js/components/ManageMenu/BlueprintsDemo/BlueprintsDemo.tsx @@ -102,7 +102,7 @@ const BlueprintsDemoPage: React.FC = () => {
{STAGE_ANNOUNCEMENTS[stage]}
- + @@ -124,11 +124,11 @@ const BlueprintsDemoPage: React.FC = () => { {showGenerated && } {isFinished &&

{__('The whole walkthrough was scripted and ran inside this plugin. No code was generated and nothing was saved.', 'code-snippets')}

-

{__('Code Snippets Pro ships blueprints for shortcodes, post types, taxonomies, settings pages, and more — fill in the form and it writes the snippet for you.', 'code-snippets')}

+

{__('Code Snippets Pro ships blueprints for shortcodes, post types, taxonomies, settings pages, and more. Fill in the form and it writes the snippet for you.', 'code-snippets')}

}
diff --git a/src/js/components/ManageMenu/BlueprintsDemo/callouts.ts b/src/js/components/ManageMenu/BlueprintsDemo/callouts.ts index fce392802..83aef337d 100644 --- a/src/js/components/ManageMenu/BlueprintsDemo/callouts.ts +++ b/src/js/components/ManageMenu/BlueprintsDemo/callouts.ts @@ -10,7 +10,7 @@ const CALLOUTS: Partial> = { general: { step: __('Step 1 of 3', 'code-snippets'), title: __('Name the shortcode', 'code-snippets'), - body: __('Every blueprint starts with the basics — the tag you type into a post, and the function that powers it.', 'code-snippets') + body: __('Every blueprint starts with the basics: the tag you type into a post, and the function that powers it.', 'code-snippets') }, attributes: { step: __('Step 2 of 3', 'code-snippets'), @@ -25,7 +25,7 @@ const CALLOUTS: Partial> = { generating: { step: __('Generating', 'code-snippets'), title: __('Building the snippet', 'code-snippets'), - body: __('Pro turns the whole form into a finished, working snippet — no boilerplate to write yourself.', 'code-snippets') + body: __('Pro turns the whole form into a finished, working snippet, with no boilerplate for you to write.', 'code-snippets') }, generated: { step: __('Done', 'code-snippets'), diff --git a/src/js/components/ManageMenu/CloudLibraryDemo/CloudLibraryDemo.tsx b/src/js/components/ManageMenu/CloudLibraryDemo/CloudLibraryDemo.tsx index 8c77f8d3e..8d574781c 100644 --- a/src/js/components/ManageMenu/CloudLibraryDemo/CloudLibraryDemo.tsx +++ b/src/js/components/ManageMenu/CloudLibraryDemo/CloudLibraryDemo.tsx @@ -76,7 +76,7 @@ export const CloudLibraryDemo: React.FC = () => {
{STAGE_ANNOUNCEMENTS[stage]}
- + @@ -93,7 +93,7 @@ export const CloudLibraryDemo: React.FC = () => { {isFinished &&

{__('The whole walkthrough was scripted and ran inside this plugin. These snippets are examples, and nothing was downloaded or saved.', 'code-snippets')}

diff --git a/src/js/components/ManageMenu/CloudLibraryDemo/callouts.ts b/src/js/components/ManageMenu/CloudLibraryDemo/callouts.ts index b426df099..baf9a4b9e 100644 --- a/src/js/components/ManageMenu/CloudLibraryDemo/callouts.ts +++ b/src/js/components/ManageMenu/CloudLibraryDemo/callouts.ts @@ -6,7 +6,7 @@ const STEPS: Partial> = { library: { step: __('Step 1 of 4', 'code-snippets'), title: __('Your whole cloud, in one place', 'code-snippets'), - body: __('Every snippet and bundle saved to your Code Snippets Cloud account is listed here, on every site you connect — so work you did once is never more than a click away.', 'code-snippets') + body: __('Every snippet and bundle saved to your Code Snippets Cloud account is listed here, on every site you connect. Work you did once is never more than a click away.', 'code-snippets') }, preview: { step: __('Step 2 of 4', 'code-snippets'), @@ -16,7 +16,7 @@ const STEPS: Partial> = { download: { step: __('Step 3 of 4', 'code-snippets'), title: __('Download in one click', 'code-snippets'), - body: __('The snippet lands in your snippets table straight away — and inactive, so nothing runs until you have looked it over and switched it on.', 'code-snippets') + body: __('The snippet lands in your snippets table straight away, switched off, so nothing runs until you have looked it over and switched it on.', 'code-snippets') }, synced: { step: __('Step 4 of 4', 'code-snippets'), diff --git a/src/js/components/common/demo/DemoCallout.tsx b/src/js/components/common/demo/DemoCallout.tsx index 4df0a8c14..69f2746ac 100644 --- a/src/js/components/common/demo/DemoCallout.tsx +++ b/src/js/components/common/demo/DemoCallout.tsx @@ -1,4 +1,6 @@ import React from 'react' +import { __ } from '@wordpress/i18n' +import { Button } from '../Button' export interface CalloutContent { step: string @@ -10,17 +12,24 @@ export interface CalloutContent { * Commentary on what a walkthrough is doing at the current stage, floating in * the corner of the viewport so it stays out of the page's flow. * - * The demo pages announce each stage through their own live region, so this is - * hidden from assistive technology rather than repeating it. + * The demo pages announce each stage through their own live region, so the + * commentary is hidden from assistive technology rather than repeating it. The + * close button stays exposed, since it is the walkthrough's exit. */ -export const DemoCallout: React.FC<{ callout?: CalloutContent }> = ({ callout }) => +export const DemoCallout: React.FC<{ callout?: CalloutContent, onClose: VoidFunction }> = ({ callout, onClose }) => callout // Keyed on the content rather than the stage: consecutive stages can // share a callout, and remounting between them replays the entrance // animation as a flicker. - ?