From 7b7196f06b6bbfc2d138fb313b9c1d84e2a5f066 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 3 Sep 2024 15:53:24 +0200 Subject: [PATCH 01/57] Dataviews Filter search widget: do not use Composite store (#64985) * Dataviews Filter search widget: do not use Composite store * Use internal CompositeHover and CompositeTypeahead version * Better comment * Refactor generateCompositeItemId arguments * Export Composite.Typeahead and Composite.Hover as private APIs * CHANGELOG --- Co-authored-by: ciampo Co-authored-by: tyxla --- packages/components/CHANGELOG.md | 1 + packages/components/src/private-apis.ts | 2 + .../dataviews-filters/search-widget.tsx | 60 ++++++++++++++----- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3b8d45be5861b..5a58ddfda38b9 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -66,6 +66,7 @@ ### Internal +- `DropdownMenu` v2: expose CompositeTypeaheadV2 and CompositeHoverV2 via private APIs ([#64985](https://github.com/WordPress/gutenberg/pull/64985)). - `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873), [#64942](https://github.com/WordPress/gutenberg/pull/64942)). - `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)). - `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)). diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index fa9fece048617..7bcab0e052e02 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -18,6 +18,8 @@ lock( privateApis, { CompositeGroupV2: Composite.Group, CompositeItemV2: Composite.Item, CompositeRowV2: Composite.Row, + CompositeTypeaheadV2: Composite.Typeahead, + CompositeHoverV2: Composite.Hover, useCompositeStoreV2: useCompositeStore, __experimentalPopoverLegacyPositionToPlacement, createPrivateSlotFill, diff --git a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx index 1b369222b8f28..24ef3b5594b41 100644 --- a/packages/dataviews/src/components/dataviews-filters/search-widget.tsx +++ b/packages/dataviews/src/components/dataviews-filters/search-widget.tsx @@ -8,6 +8,7 @@ import removeAccents from 'remove-accents'; /** * WordPress dependencies */ +import { useInstanceId } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { useState, useMemo, useDeferredValue } from '@wordpress/element'; import { @@ -27,7 +28,8 @@ import type { Filter, NormalizedFilter, View } from '../../types'; const { CompositeV2: Composite, CompositeItemV2: CompositeItem, - useCompositeStoreV2: useCompositeStore, + CompositeHoverV2: CompositeHover, + CompositeTypeaheadV2: CompositeTypeahead, } = unlock( componentsPrivateApis ); interface SearchWidgetProps { @@ -84,22 +86,37 @@ const getNewValue = ( return [ value ]; }; +function generateFilterElementCompositeItemId( + prefix: string, + filterElementValue: string +) { + return `${ prefix }-${ filterElementValue }`; +} + function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) { - const compositeStore = useCompositeStore( { - virtualFocus: true, - focusLoop: true, - // When we have no or just one operator, we can set the first item as active. - // We do that by passing `undefined` to `defaultActiveId`. Otherwise, we set it to `null`, - // so the first item is not selected, since the focus is on the operators control. - defaultActiveId: filter.operators?.length === 1 ? undefined : null, - } ); + const baseId = useInstanceId( ListBox, 'dataviews-filter-list-box' ); + + const [ activeCompositeId, setActiveCompositeId ] = useState< + string | null | undefined + >( + // When there are one or less operators, the first item is set as active + // (by setting the initial `activeId` to `undefined`). + // With 2 or more operators, the focus is moved on the operators control + // (by setting the initial `activeId` to `null`), meaning that there won't + // be an active item initially. Focus is then managed via the + // `onFocusVisible` callback. + filter.operators?.length === 1 ? undefined : null + ); const currentFilter = view.filters?.find( ( f ) => f.field === filter.field ); const currentValue = getCurrentValue( filter, currentFilter ); return ( { - if ( ! compositeStore.getState().activeId ) { - compositeStore.move( compositeStore.first() ); + // `onFocusVisible` needs the `Composite` component to be focusable, + // which is implicitly achieved via the `virtualFocus: true` option + // in the `useCompositeStore` hook. + if ( ! activeCompositeId && filter.elements.length ) { + setActiveCompositeId( + generateFilterElementCompositeItemId( + baseId, + filter.elements[ 0 ].value + ) + ); } } } - render={ } + render={ } > { filter.elements.map( ( element ) => ( - { element.label } - + ) ) } ); From 66eeb388745456156d21cfc4733933a731a6c883 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Tue, 3 Sep 2024 15:57:23 +0200 Subject: [PATCH 02/57] Block Bindings: Add warning in attributes connected to invalid sources (#65002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add warning with invalid sources * Change variable name Co-authored-by: Greg Ziółkowski * Use `isSourceInvalid` variable --------- Co-authored-by: SantosGuillamot Co-authored-by: gziolo Co-authored-by: ndiego Co-authored-by: jasmussen --- packages/block-editor/src/hooks/block-bindings.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 3b90ecc1a0c17..ea069c15a028f 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -96,16 +96,20 @@ function BlockBindingsAttribute( { attribute, binding } ) { const { source: sourceName, args } = binding || {}; const sourceProps = unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); + const isSourceInvalid = ! sourceProps; return ( { attribute } { !! binding && ( - { args?.key || sourceProps?.label || sourceName } + { isSourceInvalid + ? __( 'Invalid source' ) + : args?.key || sourceProps?.label || sourceName } ) } From 84b48f7256dceae44432c8ee3b54433ed0674035 Mon Sep 17 00:00:00 2001 From: "Joen A." <1204802+jasmussen@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:00:50 +0200 Subject: [PATCH 03/57] Icons: Add thumbs up and down icons. (#65004) Co-authored-by: jasmussen Co-authored-by: jameskoster --- packages/icons/src/index.js | 2 ++ packages/icons/src/library/thumbs-down.js | 12 ++++++++++++ packages/icons/src/library/thumbs-up.js | 12 ++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 packages/icons/src/library/thumbs-down.js create mode 100644 packages/icons/src/library/thumbs-up.js diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 9250f413a8572..11b3da927f364 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -255,6 +255,8 @@ export { default as tableRowBefore } from './library/table-row-before'; export { default as tableRowDelete } from './library/table-row-delete'; export { default as table } from './library/table'; export { default as tag } from './library/tag'; +export { default as thumbsDown } from './library/thumbs-down'; +export { default as thumbsUp } from './library/thumbs-up'; export { default as symbolFilled } from './library/symbol-filled'; export { default as termDescription } from './library/term-description'; export { default as footer } from './library/footer'; diff --git a/packages/icons/src/library/thumbs-down.js b/packages/icons/src/library/thumbs-down.js new file mode 100644 index 0000000000000..94e11ee8f0638 --- /dev/null +++ b/packages/icons/src/library/thumbs-down.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const thumbsDown = ( + + + +); + +export default thumbsDown; diff --git a/packages/icons/src/library/thumbs-up.js b/packages/icons/src/library/thumbs-up.js new file mode 100644 index 0000000000000..f65b6445359e2 --- /dev/null +++ b/packages/icons/src/library/thumbs-up.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const thumbsUp = ( + + + +); + +export default thumbsUp; From 559edaedc00efd3cd9f47418904fb2214d970124 Mon Sep 17 00:00:00 2001 From: Ramon Date: Wed, 4 Sep 2024 00:09:03 +1000 Subject: [PATCH 04/57] Color panel hook: rename to remove ambiguity (#64993) Co-authored-by: ramonjd Co-authored-by: ciampo --- .../src/components/global-styles/color-panel.js | 6 +++--- .../src/components/global-styles/color-panel.native.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/color-panel.js b/packages/block-editor/src/components/global-styles/color-panel.js index 15f06310176c7..87c19adedbb27 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.js +++ b/packages/block-editor/src/components/global-styles/color-panel.js @@ -33,7 +33,7 @@ import { unlock } from '../../lock-unlock'; export function useHasColorPanel( settings ) { const hasTextPanel = useHasTextPanel( settings ); - const hasBackgroundPanel = useHasBackgroundPanel( settings ); + const hasBackgroundPanel = useHasBackgroundColorPanel( settings ); const hasLinkPanel = useHasLinkPanel( settings ); const hasHeadingPanel = useHasHeadingPanel( settings ); const hasButtonPanel = useHasButtonPanel( settings ); @@ -97,7 +97,7 @@ export function useHasButtonPanel( settings ) { ); } -export function useHasBackgroundPanel( settings ) { +export function useHasBackgroundColorPanel( settings ) { const colors = useColorsPerOrigin( settings ); const gradients = useGradientsPerOrigin( settings ); return ( @@ -347,7 +347,7 @@ export default function ColorPanel( { }; // BackgroundColor - const showBackgroundPanel = useHasBackgroundPanel( settings ); + const showBackgroundPanel = useHasBackgroundColorPanel( settings ); const backgroundColor = decodeValue( inheritedValue?.color?.background ); const userBackgroundColor = decodeValue( value?.color?.background ); const gradient = decodeValue( inheritedValue?.color?.gradient ); diff --git a/packages/block-editor/src/components/global-styles/color-panel.native.js b/packages/block-editor/src/components/global-styles/color-panel.native.js index fcbff4e5a07d7..87002b5fa3e22 100644 --- a/packages/block-editor/src/components/global-styles/color-panel.native.js +++ b/packages/block-editor/src/components/global-styles/color-panel.native.js @@ -18,7 +18,7 @@ import InspectorControls from '../inspector-controls'; import { useHasColorPanel, useHasTextPanel, - useHasBackgroundPanel, + useHasBackgroundColorPanel, } from './color-panel.js'; import { useGlobalStyles } from './use-global-styles-context'; @@ -95,7 +95,7 @@ const ColorPanel = ( { ); // BackgroundColor - const showBackgroundPanel = useHasBackgroundPanel( settings ); + const showBackgroundPanel = useHasBackgroundColorPanel( settings ); const backgroundColor = decodeValue( inheritedValue?.color?.background ); const gradient = decodeValue( inheritedValue?.color?.gradient ); const setBackgroundColor = useCallback( From 7c0638b5a5ad278da458ff5d3fa4cd8a753e301d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:18:38 +0200 Subject: [PATCH 05/57] DataViews: fix field reordering and visibility logic (#64999) Co-authored-by: oandregal Co-authored-by: youknowriad Co-authored-by: jorgefilipecosta --- .../dataviews-view-config/index.tsx | 251 ++++++++---------- .../dataviews/src/dataviews-layouts/index.ts | 65 ++++- .../table/column-header-menu.tsx | 105 ++++---- .../src/dataviews-layouts/table/index.tsx | 5 +- packages/dataviews/src/normalize-fields.ts | 2 + packages/dataviews/src/types.ts | 2 + 6 files changed, 238 insertions(+), 192 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index 331d0d62dca00..c01c72d2ebc69 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -38,8 +38,13 @@ import { sortIcons, sortLabels, } from '../../constants'; -import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; -import type { NormalizedField, SupportedLayouts, View } from '../../types'; +import { + VIEW_LAYOUTS, + getNotHidableFieldIds, + getVisibleFieldIds, + getHiddenFieldIds, +} from '../../dataviews-layouts'; +import type { SupportedLayouts, View, Field } from '../../types'; import DataViewsContext from '../dataviews-context'; import { unlock } from '../../lock-unlock'; import DensityPicker from '../../dataviews-layouts/grid/density-picker'; @@ -232,50 +237,34 @@ function ItemsPerPageControl() { ); } +interface FieldItemProps { + id: any; + label: string; + index: number; + isVisible: boolean; + isHidable: boolean; +} + function FieldItem( { + field: { id, label, index, isVisible, isHidable }, fields, - fieldId, - mandatoryFields, - viewFields, view, onChangeView, }: { - fields: NormalizedField< any >[]; - fieldId: string; - mandatoryFields: string | any[]; - viewFields: string[]; + field: FieldItemProps; + fields: Field< any >[]; view: View; onChangeView: ( view: View ) => void; } ) { - let fieldLabel; - let fieldIsHidable; - const fieldObject = fields.find( - ( f ) => f.id === fieldId - ) as NormalizedField< any >; - if ( fieldObject ) { - fieldLabel = fieldObject.label; - fieldIsHidable = - fieldObject.enableHiding !== false && - ! mandatoryFields.includes( fieldId ); - } else if ( view.type === LAYOUT_TABLE ) { - const combinedFieldObject = view.layout?.combinedFields?.find( - ( f ) => f.id === fieldId - ); - if ( combinedFieldObject ) { - fieldLabel = combinedFieldObject.label; - fieldIsHidable = ! mandatoryFields.includes( fieldId ); - } - } + const visibleFieldIds = getVisibleFieldIds( view, fields ); - const index = view.fields?.indexOf( fieldId ) as number; - const isVisible = viewFields.includes( fieldId ); return ( - + - { fieldLabel } + { label }