From 5682b928356f624f6ed820d066689423d08d5d88 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 10 Sep 2024 12:25:13 +0200 Subject: [PATCH 01/12] Page view: Add link field control --- .../src/components/post-edit/index.js | 9 +- .../src/components/post-fields/index.js | 165 +++++++++++++++++- .../src/components/post-fields/style.scss | 19 ++ packages/edit-site/src/style.scss | 1 + 4 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 packages/edit-site/src/components/post-fields/style.scss diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 0ec63589d97673..f19fc9456c0b53 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -60,7 +60,14 @@ function PostEditForm( { postType, postId } ) { ); const form = { type: 'panel', - fields: [ 'title', 'status', 'date', 'author', 'comment_status' ], + fields: [ + 'title', + 'status', + 'date', + 'author', + 'slug', + 'comment_status', + ], }; const onChange = ( edits ) => { for ( const id of ids ) { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 9e59b23d61922d..9591f007f54357 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -12,6 +12,9 @@ import { createInterpolateElement, useMemo, useState, + useCallback, + useRef, + useEffect, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; import { @@ -22,10 +25,22 @@ import { pending, notAllowed, commentAuthorAvatar as authorIcon, + copySmall, } from '@wordpress/icons'; -import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __experimentalInputControl as InputControl, + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, + ExternalLink, + Icon, + Button, +} from '@wordpress/components'; +import { useSelect, useDispatch } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; +import { useCopyToClipboard } from '@wordpress/compose'; +import { safeDecodeURIComponent } from '@wordpress/url'; +import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -175,6 +190,21 @@ function PostAuthorField( { item } ) { ); } +function LinkField( { item } ) { + const slug = item.slug; + const originalSlug = useRef( slug ); + + useEffect( () => { + if ( slug && originalSlug.current === undefined ) { + originalSlug.current = slug; + } + }, [ slug ] ); + + const slugToDisplay = slug || originalSlug.current; + + return `/${ slugToDisplay ?? '' }`; +} + function usePostFields( viewType ) { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); @@ -369,6 +399,137 @@ function usePostFields( viewType ) { return ; }, }, + { + label: __( 'Link' ), + id: 'slug', + getValue: ( { item } ) => item.slug, + render: LinkField, + Edit: ( { field, onChange, data } ) => { + const { id } = field; + + const slug = field.getValue( { item: data } ) ?? ''; + const permalinkTemplate = data.permalink_template || ''; + const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/; + const [ prefix, suffix ] = permalinkTemplate.split( + PERMALINK_POSTNAME_REGEX + ); + const permalinkPrefix = prefix; + const permalinkSuffix = suffix; + const isEditable = + PERMALINK_POSTNAME_REGEX.test( permalinkTemplate ); + const originalSlug = useRef( slug ); + const slugToDisplay = slug || originalSlug.current; + const permalink = isEditable + ? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }` + : safeDecodeURIComponent( data.link || '' ); + + useEffect( () => { + if ( slug && originalSlug.current === undefined ) { + originalSlug.current = slug; + } + }, [ slug ] ); + + const onChangeControl = useCallback( + ( newValue ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const { createNotice } = useDispatch( noticesStore ); + + const copyButtonRef = useCopyToClipboard( permalink, () => { + createNotice( + 'info', + __( 'Copied URL to clipboard.' ), + { + isDismissible: true, + type: 'snackbar', + } + ); + } ); + + return ( +
+ { isEditable && ( + + + + { __( + 'Customize the last part of the URL.' + ) } + + + { __( 'Learn more' ) } + + + + / + + } + suffix={ +
+ ); + }, + }, { id: 'comment_status', label: __( 'Discussion' ), diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss new file mode 100644 index 00000000000000..c1eb06791ca320 --- /dev/null +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -0,0 +1,19 @@ +.edit-site-dataviews-controls__slug { + .edit-site-dataviews-controls__slug-external-icon { + margin-left: 5ch; + } + + .edit-site-dataviews-controls__slug-input + input.components-input-control__input { + padding-inline-start: 0 !important; + } + + .edit-site-dataviews-controls__slug-help { + color: $gray-700; + + .edit-site-dataviews-controls__slug-help-slug, + .edit-site-dataviews-controls__slug-help-suffix { + font-weight: 600; + } + } +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 473deaeedc5908..5b57cbeb319807 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -29,6 +29,7 @@ @import "./components/style-book/style.scss"; @import "./components/editor-canvas-container/style.scss"; @import "./components/post-edit/style.scss"; +@import "./components/post-fields/style.scss"; @import "./components/post-list/style.scss"; @import "./components/resizable-frame/style.scss"; @import "./hooks/push-changes-to-global-styles/style.scss"; From 395cc2512da0a9dd9049ca40937b618b691dd830 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 09:54:30 +0200 Subject: [PATCH 02/12] Add @wordpress/fields package --- docs/manifest.json | 6 +++ package-lock.json | 26 +++++++++++++ package.json | 1 + packages/fields/.npmrc | 1 + packages/fields/CHANGELOG.md | 5 +++ packages/fields/README.md | 23 ++++++++++++ packages/fields/package.json | 41 +++++++++++++++++++++ packages/fields/src/index.ts | 8 ++++ packages/fields/src/lock-unlock.ts | 10 +++++ packages/fields/tsconfig.json | 24 ++++++++++++ packages/private-apis/src/implementation.js | 1 + tsconfig.json | 1 + 12 files changed, 147 insertions(+) create mode 100644 packages/fields/.npmrc create mode 100644 packages/fields/CHANGELOG.md create mode 100644 packages/fields/README.md create mode 100644 packages/fields/package.json create mode 100644 packages/fields/src/index.ts create mode 100644 packages/fields/src/lock-unlock.ts create mode 100644 packages/fields/tsconfig.json diff --git a/docs/manifest.json b/docs/manifest.json index e4eba19d99fa29..d7f74d47995b63 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1697,6 +1697,12 @@ "markdown_source": "../packages/eslint-plugin/README.md", "parent": "packages" }, + { + "title": "@wordpress/fields", + "slug": "packages-fields", + "markdown_source": "../packages/fields/README.md", + "parent": "packages" + }, { "title": "@wordpress/format-library", "slug": "packages-format-library", diff --git a/package-lock.json b/package-lock.json index b9e116f15388be..4ca6d143acd4be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "@wordpress/editor": "file:packages/editor", "@wordpress/element": "file:packages/element", "@wordpress/escape-html": "file:packages/escape-html", + "@wordpress/fields": "file:packages/fields", "@wordpress/format-library": "file:packages/format-library", "@wordpress/hooks": "file:packages/hooks", "@wordpress/html-entities": "file:packages/html-entities", @@ -17028,6 +17029,10 @@ "resolved": "packages/eslint-plugin", "link": true }, + "node_modules/@wordpress/fields": { + "resolved": "packages/fields", + "link": true + }, "node_modules/@wordpress/format-library": { "resolved": "packages/format-library", "link": true @@ -53890,6 +53895,21 @@ } } }, + "packages/fields": { + "name": "@wordpress/fields", + "version": "0.0.1", + "license": "GPL-2.0-or-later", + "dependencies": { + "@babel/runtime": "^7.16.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "packages/format-library": { "name": "@wordpress/format-library", "version": "5.7.0", @@ -68447,6 +68467,12 @@ "requireindex": "^1.2.0" } }, + "@wordpress/fields": { + "version": "file:packages/fields", + "requires": { + "@babel/runtime": "^7.16.0" + } + }, "@wordpress/format-library": { "version": "file:packages/format-library", "requires": { diff --git a/package.json b/package.json index 22cdf2ce7acc88..63d42613c31978 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@wordpress/editor": "file:packages/editor", "@wordpress/element": "file:packages/element", "@wordpress/escape-html": "file:packages/escape-html", + "@wordpress/fields": "file:packages/fields", "@wordpress/format-library": "file:packages/format-library", "@wordpress/hooks": "file:packages/hooks", "@wordpress/html-entities": "file:packages/html-entities", diff --git a/packages/fields/.npmrc b/packages/fields/.npmrc new file mode 100644 index 00000000000000..43c97e719a5a82 --- /dev/null +++ b/packages/fields/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md new file mode 100644 index 00000000000000..e04ce921cdfdc4 --- /dev/null +++ b/packages/fields/CHANGELOG.md @@ -0,0 +1,5 @@ + + +## Unreleased + +Initial release. diff --git a/packages/fields/README.md b/packages/fields/README.md new file mode 100644 index 00000000000000..c69c11e566c757 --- /dev/null +++ b/packages/fields/README.md @@ -0,0 +1,23 @@ +# Fields + +This package includes a set of field controls for the DataView library, designed for creating and managing data display elements within WordPress. + +## Installation + +Install the module + +```bash +npm install @wordpress/fields --save +``` + +## Usage + + + +## Contributing to this package + +This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. + +To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md). + +

Code is Poetry.

diff --git a/packages/fields/package.json b/packages/fields/package.json new file mode 100644 index 00000000000000..4d5d33a10e5ed5 --- /dev/null +++ b/packages/fields/package.json @@ -0,0 +1,41 @@ +{ + "name": "@wordpress/fields", + "version": "0.0.1", + "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "gutenberg", + "dataviews" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/fields/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/fields" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "types": "build-types", + "sideEffects": [ + "build-style/**", + "src/**/*.scss" + ], + "dependencies": { + "@babel/runtime": "^7.16.0" + }, + "peerDependencies": { + "react": "^18.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts new file mode 100644 index 00000000000000..82c30d5290c28a --- /dev/null +++ b/packages/fields/src/index.ts @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import { lock } from './lock-unlock'; + +export const privateApis = {}; + +lock( privateApis, {} ); diff --git a/packages/fields/src/lock-unlock.ts b/packages/fields/src/lock-unlock.ts new file mode 100644 index 00000000000000..c87e7bbcd1ebf2 --- /dev/null +++ b/packages/fields/src/lock-unlock.ts @@ -0,0 +1,10 @@ +/** + * WordPress dependencies + */ +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; + +export const { lock, unlock } = + __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/fields' + ); diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json new file mode 100644 index 00000000000000..10faef0372ae24 --- /dev/null +++ b/packages/fields/tsconfig.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "checkJs": false + }, + "references": [ + { "path": "../components" }, + { "path": "../compose" }, + { "path": "../data" }, + { "path": "../element" }, + { "path": "../i18n" }, + { "path": "../icons" }, + { "path": "../primitives" }, + { "path": "../private-apis" }, + { "path": "../warning" }, + { "path": "../url" }, + { "path": "../notices" }, + { "path": "../dataviews" } + ], + "include": [ "src" ] +} diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index c268e46f669cbf..13ee9873e899de 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -31,6 +31,7 @@ const CORE_MODULES_USING_PRIVATE_APIS = [ '@wordpress/reusable-blocks', '@wordpress/router', '@wordpress/dataviews', + '@wordpress/fields', ]; /** diff --git a/tsconfig.json b/tsconfig.json index 6be31e9b61bef8..3ab54f66019bca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,7 @@ { "path": "packages/element" }, { "path": "packages/escape-html" }, { "path": "packages/eslint-plugin" }, + { "path": "packages/fields" }, { "path": "packages/hooks" }, { "path": "packages/html-entities" }, { "path": "packages/html-entities" }, From b00ec035d6f0c6ea57359fe61a13f55186ce5d9b Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 11:32:06 +0200 Subject: [PATCH 03/12] remove not used references --- packages/fields/tsconfig.json | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index 10faef0372ae24..79aa09d0ad56e3 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -6,19 +6,6 @@ "declarationDir": "build-types", "checkJs": false }, - "references": [ - { "path": "../components" }, - { "path": "../compose" }, - { "path": "../data" }, - { "path": "../element" }, - { "path": "../i18n" }, - { "path": "../icons" }, - { "path": "../primitives" }, - { "path": "../private-apis" }, - { "path": "../warning" }, - { "path": "../url" }, - { "path": "../notices" }, - { "path": "../dataviews" } - ], + "references": [], "include": [ "src" ] } From 6e71a98bba09cb47462fd67d34be7e177d93136c Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 11:38:56 +0200 Subject: [PATCH 04/12] add marker to generate API documentation --- packages/fields/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/fields/README.md b/packages/fields/README.md index c69c11e566c757..bf98e483404f0d 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -12,6 +12,10 @@ npm install @wordpress/fields --save ## Usage + + +`. + ## Contributing to this package From 43b8a93203f6e55d6d5b1f3f7f7268283700ebb2 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 12:03:12 +0200 Subject: [PATCH 05/12] improve package description --- packages/fields/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fields/README.md b/packages/fields/README.md index bf98e483404f0d..c0a2f899156fe0 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -1,6 +1,6 @@ # Fields -This package includes a set of field controls for the DataView library, designed for creating and managing data display elements within WordPress. +This package provides core elements for the DataView library, designed to simplify the creation and management of data display elements in WordPress. ## Installation From 7e04069cef9dd0740119e8abf16f9d19e58f1bb5 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 12:05:27 +0200 Subject: [PATCH 06/12] not use lock/unlock api --- .../dependency-extraction-webpack-plugin/lib/util.js | 1 + packages/fields/src/index.ts | 8 -------- packages/fields/src/lock-unlock.ts | 10 ---------- tools/webpack/packages.js | 1 + 4 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 packages/fields/src/index.ts delete mode 100644 packages/fields/src/lock-unlock.ts diff --git a/packages/dependency-extraction-webpack-plugin/lib/util.js b/packages/dependency-extraction-webpack-plugin/lib/util.js index ee5c2face1b9d1..fcc6e5a0ed1731 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/util.js +++ b/packages/dependency-extraction-webpack-plugin/lib/util.js @@ -9,6 +9,7 @@ const BUNDLED_PACKAGES = [ '@wordpress/interface', '@wordpress/sync', '@wordpress/undo-manager', + '@wordpress/fields', ]; /** diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts deleted file mode 100644 index 82c30d5290c28a..00000000000000 --- a/packages/fields/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Internal dependencies - */ -import { lock } from './lock-unlock'; - -export const privateApis = {}; - -lock( privateApis, {} ); diff --git a/packages/fields/src/lock-unlock.ts b/packages/fields/src/lock-unlock.ts deleted file mode 100644 index c87e7bbcd1ebf2..00000000000000 --- a/packages/fields/src/lock-unlock.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * WordPress dependencies - */ -import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; - -export const { lock, unlock } = - __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', - '@wordpress/fields' - ); diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 055665c2feb1c8..a1610d0a5ba54e 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -34,6 +34,7 @@ const BUNDLED_PACKAGES = [ '@wordpress/interface', '@wordpress/sync', '@wordpress/undo-manager', + '@wordpress/fields', ]; // PHP files in packages that have to be copied during build. From e5fd36182c66b4002177f78f79b3a3c973f78ed8 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 12:10:18 +0200 Subject: [PATCH 07/12] remove apostrophe --- packages/fields/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fields/README.md b/packages/fields/README.md index c0a2f899156fe0..71ba9e882595d0 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,7 +14,7 @@ npm install @wordpress/fields --save -`. + From 9bfd08fff59ff8c2526eac2930239f1dc87a8d4c Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 14:44:56 +0200 Subject: [PATCH 08/12] fix build --- packages/fields/README.md | 4 ++-- packages/fields/src/index.ts | 0 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 packages/fields/src/index.ts diff --git a/packages/fields/README.md b/packages/fields/README.md index 71ba9e882595d0..c5044d1e9fdd2f 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,9 +14,9 @@ npm install @wordpress/fields --save - - +Nothing to document. + ## Contributing to this package diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts new file mode 100644 index 00000000000000..e69de29bb2d1d6 From 0855668e475c145b7dc9df6de9bd085d3273cdd5 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 11 Sep 2024 15:11:26 +0200 Subject: [PATCH 09/12] move slug field control to @wordpress/fields package --- package-lock.json | 26 ++- packages/edit-site/package.json | 1 + .../src/components/post-fields/index.js | 163 +----------------- packages/edit-site/src/style.scss | 2 +- packages/fields/README.md | 8 +- packages/fields/package.json | 13 +- packages/fields/src/fields/index.ts | 2 + packages/fields/src/fields/slug/slug.edit.tsx | 141 +++++++++++++++ packages/fields/src/fields/slug/slug.view.tsx | 26 +++ .../src/fields/slug}/style.scss | 0 packages/fields/src/fields/slug/types.ts | 5 + packages/fields/src/index.ts | 1 + packages/fields/src/styles.scss | 1 + packages/fields/tsconfig.json | 15 +- 14 files changed, 240 insertions(+), 164 deletions(-) create mode 100644 packages/fields/src/fields/index.ts create mode 100644 packages/fields/src/fields/slug/slug.edit.tsx create mode 100644 packages/fields/src/fields/slug/slug.view.tsx rename packages/{edit-site/src/components/post-fields => fields/src/fields/slug}/style.scss (100%) create mode 100644 packages/fields/src/fields/slug/types.ts create mode 100644 packages/fields/src/styles.scss diff --git a/package-lock.json b/package-lock.json index 4ca6d143acd4be..f426b04847bf72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53539,6 +53539,7 @@ "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/escape-html": "file:../escape-html", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", @@ -53900,7 +53901,17 @@ "version": "0.0.1", "license": "GPL-2.0-or-later", "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "^7.16.0", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning" }, "engines": { "node": ">=18.12.0", @@ -68209,6 +68220,7 @@ "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/escape-html": "file:../escape-html", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", @@ -68470,7 +68482,17 @@ "@wordpress/fields": { "version": "file:packages/fields", "requires": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "^7.16.0", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/warning": "file:../warning" } }, "@wordpress/format-library": { diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 43bcf68aa68e68..a7b22e9c314300 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -48,6 +48,7 @@ "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/escape-html": "file:../escape-html", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 9591f007f54357..15c135cd331250 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -12,9 +12,6 @@ import { createInterpolateElement, useMemo, useState, - useCallback, - useRef, - useEffect, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; import { @@ -25,22 +22,11 @@ import { pending, notAllowed, commentAuthorAvatar as authorIcon, - copySmall, } from '@wordpress/icons'; -import { - __experimentalHStack as HStack, - __experimentalVStack as VStack, - __experimentalInputControl as InputControl, - __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, - ExternalLink, - Icon, - Button, -} from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; -import { useCopyToClipboard } from '@wordpress/compose'; -import { safeDecodeURIComponent } from '@wordpress/url'; -import { store as noticesStore } from '@wordpress/notices'; +import { SlugView, SlugEdit } from '@wordpress/fields'; /** * Internal dependencies @@ -190,21 +176,6 @@ function PostAuthorField( { item } ) { ); } -function LinkField( { item } ) { - const slug = item.slug; - const originalSlug = useRef( slug ); - - useEffect( () => { - if ( slug && originalSlug.current === undefined ) { - originalSlug.current = slug; - } - }, [ slug ] ); - - const slugToDisplay = slug || originalSlug.current; - - return `/${ slugToDisplay ?? '' }`; -} - function usePostFields( viewType ) { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); @@ -403,132 +374,8 @@ function usePostFields( viewType ) { label: __( 'Link' ), id: 'slug', getValue: ( { item } ) => item.slug, - render: LinkField, - Edit: ( { field, onChange, data } ) => { - const { id } = field; - - const slug = field.getValue( { item: data } ) ?? ''; - const permalinkTemplate = data.permalink_template || ''; - const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/; - const [ prefix, suffix ] = permalinkTemplate.split( - PERMALINK_POSTNAME_REGEX - ); - const permalinkPrefix = prefix; - const permalinkSuffix = suffix; - const isEditable = - PERMALINK_POSTNAME_REGEX.test( permalinkTemplate ); - const originalSlug = useRef( slug ); - const slugToDisplay = slug || originalSlug.current; - const permalink = isEditable - ? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }` - : safeDecodeURIComponent( data.link || '' ); - - useEffect( () => { - if ( slug && originalSlug.current === undefined ) { - originalSlug.current = slug; - } - }, [ slug ] ); - - const onChangeControl = useCallback( - ( newValue ) => - onChange( { - [ id ]: newValue, - } ), - [ id, onChange ] - ); - - const { createNotice } = useDispatch( noticesStore ); - - const copyButtonRef = useCopyToClipboard( permalink, () => { - createNotice( - 'info', - __( 'Copied URL to clipboard.' ), - { - isDismissible: true, - type: 'snackbar', - } - ); - } ); - - return ( -
- { isEditable && ( - - - - { __( - 'Customize the last part of the URL.' - ) } - - - { __( 'Learn more' ) } - - - - / - - } - suffix={ -
- ); - }, + render: SlugView, + Edit: SlugEdit, }, { id: 'comment_status', diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 5b57cbeb319807..27b3167b977677 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,4 +1,5 @@ @import "../../dataviews/src/style.scss"; +@import "../../fields/src/styles.scss"; @import "./components/add-new-template/style.scss"; @import "./components/block-editor/style.scss"; @@ -29,7 +30,6 @@ @import "./components/style-book/style.scss"; @import "./components/editor-canvas-container/style.scss"; @import "./components/post-edit/style.scss"; -@import "./components/post-fields/style.scss"; @import "./components/post-list/style.scss"; @import "./components/resizable-frame/style.scss"; @import "./hooks/push-changes-to-global-styles/style.scss"; diff --git a/packages/fields/README.md b/packages/fields/README.md index c5044d1e9fdd2f..57d2229c0fabf0 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -14,7 +14,13 @@ npm install @wordpress/fields --save -Nothing to document. +### SlugEdit + +Undocumented declaration. + +### SlugView + +Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index 4d5d33a10e5ed5..c1a4f0b704ef1d 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -30,7 +30,18 @@ "src/**/*.scss" ], "dependencies": { - "@babel/runtime": "^7.16.0" + "@babel/runtime": "^7.16.0", + "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", + "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", + "@wordpress/i18n": "file:../i18n", + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/primitives": "file:../primitives", + "@wordpress/private-apis": "file:../private-apis", + "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning" }, "peerDependencies": { "react": "^18.0.0" diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts new file mode 100644 index 00000000000000..1b04c857b1a1e7 --- /dev/null +++ b/packages/fields/src/fields/index.ts @@ -0,0 +1,2 @@ +export { default as SlugEdit } from './slug/slug.edit'; +export { default as SlugView } from './slug/slug.view'; diff --git a/packages/fields/src/fields/slug/slug.edit.tsx b/packages/fields/src/fields/slug/slug.edit.tsx new file mode 100644 index 00000000000000..31d3df975cfbee --- /dev/null +++ b/packages/fields/src/fields/slug/slug.edit.tsx @@ -0,0 +1,141 @@ +/** + * WordPress dependencies + */ +import { + Button, + ExternalLink, + __experimentalInputControl as InputControl, + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import { copySmall } from '@wordpress/icons'; +import { useCopyToClipboard } from '@wordpress/compose'; +import { useDispatch } from '@wordpress/data'; +import { useCallback, useEffect, useRef } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { safeDecodeURIComponent } from '@wordpress/url'; +import type { DataFormControlProps } from '@wordpress/dataviews'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import type { SlugItem } from './types'; + +const SlugEdit = ( { + field, + onChange, + data, +}: DataFormControlProps< SlugItem > ) => { + const { id } = field; + + const slug = field.getValue( { item: data } ) ?? ''; + const permalinkTemplate = data.permalink_template || ''; + const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/; + const [ prefix, suffix ] = permalinkTemplate.split( + PERMALINK_POSTNAME_REGEX + ); + const permalinkPrefix = prefix; + const permalinkSuffix = suffix; + const isEditable = PERMALINK_POSTNAME_REGEX.test( permalinkTemplate ); + const originalSlug = useRef( slug ); + const slugToDisplay = slug || originalSlug.current; + const permalink = isEditable + ? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }` + : safeDecodeURIComponent( data.link || '' ); + + useEffect( () => { + if ( slug && originalSlug.current === undefined ) { + originalSlug.current = slug; + } + }, [ slug ] ); + + const onChangeControl = useCallback( + ( newValue?: string ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const { createNotice } = useDispatch( noticesStore ); + + const copyButtonRef = useCopyToClipboard( permalink, () => { + createNotice( 'info', __( 'Copied URL to clipboard.' ), { + isDismissible: true, + type: 'snackbar', + } ); + } ); + + return ( +
+ { isEditable && ( + + + + { __( 'Customize the last part of the URL.' ) } + + + { __( 'Learn more' ) } + + + + / + + } + suffix={ +
+ ); +}; + +export default SlugEdit; diff --git a/packages/fields/src/fields/slug/slug.view.tsx b/packages/fields/src/fields/slug/slug.view.tsx new file mode 100644 index 00000000000000..c54fad38ac079d --- /dev/null +++ b/packages/fields/src/fields/slug/slug.view.tsx @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { useEffect, useRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { SlugItem } from './types'; + +const SlugView = ( { item }: { item: SlugItem } ) => { + const slug = item.slug; + const originalSlug = useRef( slug ); + + useEffect( () => { + if ( slug && originalSlug.current === undefined ) { + originalSlug.current = slug; + } + }, [ slug ] ); + + const slugToDisplay = slug || originalSlug.current; + + return `/${ slugToDisplay ?? '' }`; +}; + +export default SlugView; diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/fields/src/fields/slug/style.scss similarity index 100% rename from packages/edit-site/src/components/post-fields/style.scss rename to packages/fields/src/fields/slug/style.scss diff --git a/packages/fields/src/fields/slug/types.ts b/packages/fields/src/fields/slug/types.ts new file mode 100644 index 00000000000000..c680c85c876bc7 --- /dev/null +++ b/packages/fields/src/fields/slug/types.ts @@ -0,0 +1,5 @@ +export type SlugItem = { + permalink_template?: string; + link?: string; + slug?: string; +}; diff --git a/packages/fields/src/index.ts b/packages/fields/src/index.ts index e69de29bb2d1d6..cbc6c8c464c5fd 100644 --- a/packages/fields/src/index.ts +++ b/packages/fields/src/index.ts @@ -0,0 +1 @@ +export * from './fields'; diff --git a/packages/fields/src/styles.scss b/packages/fields/src/styles.scss new file mode 100644 index 00000000000000..cdb130337f1cd9 --- /dev/null +++ b/packages/fields/src/styles.scss @@ -0,0 +1 @@ +@import "./fields/slug/style.scss"; diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index 79aa09d0ad56e3..10faef0372ae24 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -6,6 +6,19 @@ "declarationDir": "build-types", "checkJs": false }, - "references": [], + "references": [ + { "path": "../components" }, + { "path": "../compose" }, + { "path": "../data" }, + { "path": "../element" }, + { "path": "../i18n" }, + { "path": "../icons" }, + { "path": "../primitives" }, + { "path": "../private-apis" }, + { "path": "../warning" }, + { "path": "../url" }, + { "path": "../notices" }, + { "path": "../dataviews" } + ], "include": [ "src" ] } From 934bc1ec3ab2e861c697f560ed3ec02f0f11a050 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 17 Sep 2024 11:14:25 +0200 Subject: [PATCH 10/12] improve definition --- .../src/components/post-fields/index.js | 10 ++------- packages/fields/README.md | 6 +---- packages/fields/src/fields/index.ts | 3 +-- packages/fields/src/fields/slug/index.ts | 22 +++++++++++++++++++ packages/fields/src/fields/slug/slug.edit.tsx | 4 ++-- packages/fields/src/fields/slug/slug.view.tsx | 4 ++-- packages/fields/src/fields/slug/types.ts | 5 ----- packages/fields/src/types.ts | 2 ++ 8 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 packages/fields/src/fields/slug/index.ts delete mode 100644 packages/fields/src/fields/slug/types.ts diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 15c135cd331250..c9e83158ed0739 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -26,7 +26,7 @@ import { import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; -import { SlugView, SlugEdit } from '@wordpress/fields'; +import { slugField } from '@wordpress/fields'; /** * Internal dependencies @@ -370,13 +370,7 @@ function usePostFields( viewType ) { return ; }, }, - { - label: __( 'Link' ), - id: 'slug', - getValue: ( { item } ) => item.slug, - render: SlugView, - Edit: SlugEdit, - }, + slugField, { id: 'comment_status', label: __( 'Discussion' ), diff --git a/packages/fields/README.md b/packages/fields/README.md index 964de23922b361..b09716a7598c9e 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -50,11 +50,7 @@ Undocumented declaration. Undocumented declaration. -### SlugEdit - -Undocumented declaration. - -### SlugView +### slugField Undocumented declaration. diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 061fbc856e3ec2..f07896c9a49cc4 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -1,4 +1,3 @@ -export { default as SlugEdit } from './slug/slug.edit'; -export { default as SlugView } from './slug/slug.view'; +export { default as slugField } from './slug'; export { default as titleField } from './title'; export { default as orderField } from './order'; diff --git a/packages/fields/src/fields/slug/index.ts b/packages/fields/src/fields/slug/index.ts new file mode 100644 index 00000000000000..2d340f8e5366ad --- /dev/null +++ b/packages/fields/src/fields/slug/index.ts @@ -0,0 +1,22 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; +import SlugEdit from './slug.edit'; +import SlugView from './slug.view'; + +const slugField: Field< BasePost > = { + id: 'slug', + label: __( 'Link' ), + getValue: ( { item } ) => item.slug, + Edit: SlugEdit, + render: SlugView, +}; + +export default slugField; diff --git a/packages/fields/src/fields/slug/slug.edit.tsx b/packages/fields/src/fields/slug/slug.edit.tsx index 31d3df975cfbee..b2cc5138b97c4c 100644 --- a/packages/fields/src/fields/slug/slug.edit.tsx +++ b/packages/fields/src/fields/slug/slug.edit.tsx @@ -20,13 +20,13 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import type { SlugItem } from './types'; +import type { BasePost } from '../../types'; const SlugEdit = ( { field, onChange, data, -}: DataFormControlProps< SlugItem > ) => { +}: DataFormControlProps< BasePost > ) => { const { id } = field; const slug = field.getValue( { item: data } ) ?? ''; diff --git a/packages/fields/src/fields/slug/slug.view.tsx b/packages/fields/src/fields/slug/slug.view.tsx index c54fad38ac079d..7448673c6a8464 100644 --- a/packages/fields/src/fields/slug/slug.view.tsx +++ b/packages/fields/src/fields/slug/slug.view.tsx @@ -6,9 +6,9 @@ import { useEffect, useRef } from '@wordpress/element'; /** * Internal dependencies */ -import type { SlugItem } from './types'; +import type { BasePost } from '../../types'; -const SlugView = ( { item }: { item: SlugItem } ) => { +const SlugView = ( { item }: { item: BasePost } ) => { const slug = item.slug; const originalSlug = useRef( slug ); diff --git a/packages/fields/src/fields/slug/types.ts b/packages/fields/src/fields/slug/types.ts deleted file mode 100644 index c680c85c876bc7..00000000000000 --- a/packages/fields/src/fields/slug/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type SlugItem = { - permalink_template?: string; - link?: string; - slug?: string; -}; diff --git a/packages/fields/src/types.ts b/packages/fields/src/types.ts index 664c2dd417201c..70aa7756a74e4e 100644 --- a/packages/fields/src/types.ts +++ b/packages/fields/src/types.ts @@ -35,6 +35,8 @@ export interface BasePost extends CommonPost { menu_order?: number; ping_status?: 'open' | 'closed'; link?: string; + slug?: string; + permalink_template?: string; } export interface Template extends CommonPost { From dc2e1b83d58e1b1197eac1d95c84ad5e11c87eb3 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 18 Sep 2024 11:29:13 +0200 Subject: [PATCH 11/12] disable slug field control in bulk mode --- .../src/components/post-edit/index.js | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index f19fc9456c0b53..cb405eea11a856 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -69,6 +69,15 @@ function PostEditForm( { postType, postId } ) { 'comment_status', ], }; + + const fieldsWithBulkEditSupport = [ + 'title', + 'status', + 'date', + 'author', + 'comment_status', + ]; + const onChange = ( edits ) => { for ( const id of ids ) { if ( @@ -102,7 +111,16 @@ function PostEditForm( { postType, postId } ) { + fieldsWithBulkEditSupport.includes( field ) + ), + } + } onChange={ onChange } /> From 500b848fee1e1b62aa86afbc6d5adcd1ce20f5d1 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 18 Sep 2024 11:34:05 +0200 Subject: [PATCH 12/12] improve css classnames --- packages/fields/src/fields/slug/index.ts | 4 ++-- .../fields/slug/{slug.edit.tsx => slug-edit.tsx} | 12 ++++++------ .../fields/slug/{slug.view.tsx => slug-view.tsx} | 0 packages/fields/src/fields/slug/style.scss | 13 ++++++------- 4 files changed, 14 insertions(+), 15 deletions(-) rename packages/fields/src/fields/slug/{slug.edit.tsx => slug-edit.tsx} (89%) rename packages/fields/src/fields/slug/{slug.view.tsx => slug-view.tsx} (100%) diff --git a/packages/fields/src/fields/slug/index.ts b/packages/fields/src/fields/slug/index.ts index 2d340f8e5366ad..803e04bbfee52b 100644 --- a/packages/fields/src/fields/slug/index.ts +++ b/packages/fields/src/fields/slug/index.ts @@ -8,8 +8,8 @@ import type { Field } from '@wordpress/dataviews'; */ import type { BasePost } from '../../types'; import { __ } from '@wordpress/i18n'; -import SlugEdit from './slug.edit'; -import SlugView from './slug.view'; +import SlugEdit from './slug-edit'; +import SlugView from './slug-view'; const slugField: Field< BasePost > = { id: 'slug', diff --git a/packages/fields/src/fields/slug/slug.edit.tsx b/packages/fields/src/fields/slug/slug-edit.tsx similarity index 89% rename from packages/fields/src/fields/slug/slug.edit.tsx rename to packages/fields/src/fields/slug/slug-edit.tsx index b2cc5138b97c4c..3def1d868fca97 100644 --- a/packages/fields/src/fields/slug/slug.edit.tsx +++ b/packages/fields/src/fields/slug/slug-edit.tsx @@ -68,7 +68,7 @@ const SlugEdit = ( { } ); return ( -
+
{ isEditable && ( @@ -100,7 +100,7 @@ const SlugEdit = ( { autoComplete="off" spellCheck="false" type="text" - className="edit-site-dataviews-controls__slug-input" + className="fields-controls__slug-input" onChange={ ( newValue?: string ) => { onChangeControl( newValue ); } } @@ -111,14 +111,14 @@ const SlugEdit = ( { } } help={ { permalinkPrefix } - + { slugToDisplay } - + { permalinkSuffix } @@ -128,7 +128,7 @@ const SlugEdit = ( { ) } { ! isEditable && ( { permalink } diff --git a/packages/fields/src/fields/slug/slug.view.tsx b/packages/fields/src/fields/slug/slug-view.tsx similarity index 100% rename from packages/fields/src/fields/slug/slug.view.tsx rename to packages/fields/src/fields/slug/slug-view.tsx diff --git a/packages/fields/src/fields/slug/style.scss b/packages/fields/src/fields/slug/style.scss index c1eb06791ca320..d705c2c38681b8 100644 --- a/packages/fields/src/fields/slug/style.scss +++ b/packages/fields/src/fields/slug/style.scss @@ -1,18 +1,17 @@ -.edit-site-dataviews-controls__slug { - .edit-site-dataviews-controls__slug-external-icon { +.fields-controls__slug { + .fields-controls__slug-external-icon { margin-left: 5ch; } - .edit-site-dataviews-controls__slug-input - input.components-input-control__input { + .fields-controls__slug-input input.components-input-control__input { padding-inline-start: 0 !important; } - .edit-site-dataviews-controls__slug-help { + .fields-controls__slug-help { color: $gray-700; - .edit-site-dataviews-controls__slug-help-slug, - .edit-site-dataviews-controls__slug-help-suffix { + .fields-controls__slug-help-slug, + .fields-controls__slug-help-suffix { font-weight: 600; } }