Skip to content

Commit

Permalink
Remove hstack form search (+2 squashed commits)
Browse files Browse the repository at this point in the history
Squashed commits:
[62c7124201] lint fixes
[afa224734a] apply feedback
  • Loading branch information
jorgefilipecosta committed Jul 19, 2024
1 parent 154f1aa commit ff8f340
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 91 deletions.
58 changes: 37 additions & 21 deletions packages/dataviews/src/components/dataviews-filters/add-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,18 @@ interface AddFilterProps {
setOpenedFilter: ( filter: string | null ) => void;
}

function AddFilter(
{ filters, view, onChangeView, setOpenedFilter }: AddFilterProps,
ref: Ref< HTMLButtonElement >
) {
if ( ! filters.length || filters.every( ( { isPrimary } ) => isPrimary ) ) {
return null;
}
export function AddFilterDropdownMenu( {
filters,
view,
onChangeView,
setOpenedFilter,
trigger,
}: AddFilterProps & {
trigger: React.ReactNode;
} ) {
const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible );
return (
<DropdownMenu
trigger={
<Button
accessibleWhenDisabled
size="compact"
className="dataviews-filters__button"
variant="tertiary"
disabled={ ! inactiveFilters.length }
ref={ ref }
>
{ __( 'Add filter' ) }
</Button>
}
>
<DropdownMenu trigger={ trigger }>
{ inactiveFilters.map( ( filter ) => {
return (
<DropdownMenuItem
Expand Down Expand Up @@ -85,4 +74,31 @@ function AddFilter(
);
}

function AddFilter(
{ filters, view, onChangeView, setOpenedFilter }: AddFilterProps,
ref: Ref< HTMLButtonElement >
) {
if ( ! filters.length || filters.every( ( { isPrimary } ) => isPrimary ) ) {
return null;
}
const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible );
return (
<AddFilterDropdownMenu
trigger={
<Button
accessibleWhenDisabled
size="compact"
className="dataviews-filters-button"
variant="tertiary"
disabled={ ! inactiveFilters.length }
ref={ ref }
>
{ __( 'Add filter' ) }
</Button>
}
{ ...{ filters, view, onChangeView, setOpenedFilter } }
/>
);
}

export default forwardRef( AddFilter );
205 changes: 145 additions & 60 deletions packages/dataviews/src/components/dataviews-filters/index.tsx
Original file line number Diff line number Diff line change
@@ -1,65 +1,147 @@
/**
* WordPress dependencies
*/
import { memo, useContext, useRef } from '@wordpress/element';
import { __experimentalHStack as HStack } from '@wordpress/components';
import {
memo,
useContext,
useRef,
useMemo,
useCallback,
} from '@wordpress/element';
import { __experimentalHStack as HStack, Button } from '@wordpress/components';
import { funnel } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import FilterSummary from './filter-summary';
import AddFilter from './add-filter';
import { default as AddFilter, AddFilterDropdownMenu } from './add-filter';
import ResetFilters from './reset-filters';
import DataViewsContext from '../dataviews-context';
import { sanitizeOperators } from '../../utils';
import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from '../../constants';
import type { NormalizedFilter } from '../../types';
import type { NormalizedFilter, NormalizedField, View } from '../../types';

function Filters() {
const { fields, view, onChangeView, openedFilter, setOpenedFilter } =
useContext( DataViewsContext );
const addFilterRef = useRef< HTMLButtonElement >( null );
const filters: NormalizedFilter[] = [];
fields.forEach( ( field ) => {
if ( ! field.elements?.length ) {
return;
}
export function useFilters( fields: NormalizedField< any >[], view: View ) {
return useMemo( () => {
const filters: NormalizedFilter[] = [];
fields.forEach( ( field ) => {
if ( ! field.elements?.length ) {
return;
}

const operators = sanitizeOperators( field );
if ( operators.length === 0 ) {
return;
}
const operators = sanitizeOperators( field );
if ( operators.length === 0 ) {
return;
}

const isPrimary = !! field.filterBy?.isPrimary;
filters.push( {
field: field.id,
name: field.header,
elements: field.elements,
singleSelection: operators.some( ( op ) =>
[ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op )
),
operators,
isVisible:
isPrimary ||
!! view.filters?.some(
( f ) =>
f.field === field.id &&
ALL_OPERATORS.includes( f.operator )
const isPrimary = !! field.filterBy?.isPrimary;
filters.push( {
field: field.id,
name: field.header,
elements: field.elements,
singleSelection: operators.some( ( op ) =>
[ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op )
),
isPrimary,
operators,
isVisible:
isPrimary ||
!! view.filters?.some(
( f ) =>
f.field === field.id &&
ALL_OPERATORS.includes( f.operator )
),
isPrimary,
} );
} );
} );
// Sort filters by primary property. We need the primary filters to be first.
// Then we sort by name.
filters.sort( ( a, b ) => {
if ( a.isPrimary && ! b.isPrimary ) {
return -1;
}
if ( ! a.isPrimary && b.isPrimary ) {
return 1;
}
return a.name.localeCompare( b.name );
} );
// Sort filters by primary property. We need the primary filters to be first.
// Then we sort by name.
filters.sort( ( a, b ) => {
if ( a.isPrimary && ! b.isPrimary ) {
return -1;
}
if ( ! a.isPrimary && b.isPrimary ) {
return 1;
}
return a.name.localeCompare( b.name );
} );
return filters;
}, [ fields, view ] );
}

export function FilterVisibilityToggle( {
filters,
view,
onChangeView,
setOpenedFilter,
isShowingFilter,
setIsShowingFilter,
}: {
filters: NormalizedFilter[];
view: View;
onChangeView: ( view: View ) => void;
setOpenedFilter: ( filter: string | null ) => void;
isShowingFilter: boolean;
setIsShowingFilter: React.Dispatch< React.SetStateAction< boolean > >;
} ) {
const onChangeViewWithFilterVisibility = useCallback(
( _view: View ) => {
onChangeView( _view );
setIsShowingFilter( true );
},
[ onChangeView, setIsShowingFilter ]
);

const hasFilters = !! view.filters?.length;
if ( ! hasFilters ) {
return (
<AddFilterDropdownMenu
filters={ filters }
view={ view }
onChangeView={ onChangeViewWithFilterVisibility }
setOpenedFilter={ setOpenedFilter }
trigger={
<Button
size="compact"
icon={ funnel }
label={ __( 'Add filter' ) }
isPressed={ false }
aria-expanded={ false }
/>
}
/>
);
}
return (
<>
<Button
size="compact"
icon={ funnel }
label={ __( 'Toggle filter display' ) }
onClick={ () => {
if ( ! isShowingFilter ) {
setOpenedFilter( null );
}
setIsShowingFilter( ! isShowingFilter );
} }
isPressed={ isShowingFilter }
aria-expanded={ isShowingFilter }
/>
{ hasFilters && (
<span className="dataviews-filters-toggle__count">
{ view.filters?.length }
</span>
) }
</>
);
}

function Filters() {
const { fields, view, onChangeView, openedFilter, setOpenedFilter } =
useContext( DataViewsContext );
const addFilterRef = useRef< HTMLButtonElement >( null );
const filters = useFilters( fields, view );
const addFilter = (
<AddFilter
key="add-filter"
Expand All @@ -70,12 +152,12 @@ function Filters() {
setOpenedFilter={ setOpenedFilter }
/>
);
const visibleFilters = filters.filter( ( filter ) => filter.isVisible );
if ( visibleFilters.length === 0 ) {
return null;
}
const filterComponents = [
...filters.map( ( filter ) => {
if ( ! filter.isVisible ) {
return null;
}

return (
<FilterSummary
key={ filter.field }
Expand All @@ -90,19 +172,22 @@ function Filters() {
addFilter,
];

if ( filterComponents.length > 1 ) {
filterComponents.push(
<ResetFilters
key="reset-filters"
filters={ filters }
view={ view }
onChangeView={ onChangeView }
/>
);
}
filterComponents.push(
<ResetFilters
key="reset-filters"
filters={ filters }
view={ view }
onChangeView={ onChangeView }
/>
);

return (
<HStack justify="flex-start" style={ { width: 'fit-content' } } wrap>
<HStack
justify="flex-start"
style={ { width: 'fit-content' } }
className="dataviews-filters__container"
wrap
>
{ filterComponents }
</HStack>
);
Expand Down
23 changes: 23 additions & 0 deletions packages/dataviews/src/components/dataviews-filters/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,26 @@
width: $icon-size;
}
}

.dataviews-filters-toggle__container {
position: relative;
}

.dataviews-filters-toggle__count {
position: absolute;
top: math.div(-$grid-unit-15, 2);
right: -$grid-unit-15;
background: var(--wp-admin-theme-color, #3858e9);
height: $grid-unit-15 + math.div($grid-unit-05, 2);
width: $grid-unit-15 + math.div($grid-unit-05, 2);
line-height: $grid-unit-15 + math.div($grid-unit-05, 2);
text-align: center;
border-radius: 50%;
font-size: 10px;
outline: $border-width solid $white;
color: $white;
}

.dataviews-search {
width: 100%;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const DataViewsSearch = memo( function Search( { label }: SearchProps ) {
const searchLabel = label || __( 'Search' );
return (
<SearchControl
className="dataviews-search"
__nextHasNoMarginBottom
onChange={ setSearch }
value={ search }
Expand Down
Loading

0 comments on commit ff8f340

Please sign in to comment.