11'use client'
2- import type { I18nClient } from '@payloadcms/translations'
32import type { ClientBlock , Labels } from 'payload'
43
54import { useModal } from '@faceless-ui/modal'
65import { getTranslation } from '@payloadcms/translations'
7- import React , { useEffect , useMemo , useState } from 'react'
6+ import React , { useEffect } from 'react'
87
98import { Drawer } from '../../../elements/Drawer/index.js'
10- import { ThumbnailCard } from '../../../elements/ThumbnailCard/index.js'
11- import { DefaultBlockImage } from '../../../graphics/DefaultBlockImage/index.js'
12- import { useConfig } from '../../../providers/Config/index.js'
139import { useTranslation } from '../../../providers/Translation/index.js'
14- import './index.scss'
15- import { BlockSearch } from './BlockSearch/index.js'
10+ import { BlockSelector } from '../BlockSelector/index.js'
1611
1712export type Props = {
1813 readonly addRow : ( index : number , blockType ?: string ) => Promise < void > | void
@@ -22,125 +17,32 @@ export type Props = {
2217 readonly labels : Labels
2318}
2419
25- const baseClass = 'blocks-drawer'
26-
27- const getBlockLabel = ( block : ClientBlock , i18n : I18nClient ) => {
28- if ( typeof block . labels . singular === 'string' ) {
29- return block . labels . singular . toLowerCase ( )
30- }
31- if ( typeof block . labels . singular === 'object' ) {
32- return getTranslation ( block . labels . singular , i18n ) . toLowerCase ( )
33- }
34- return ''
35- }
36-
3720export const BlocksDrawer : React . FC < Props > = ( props ) => {
3821 const { addRow, addRowIndex, blocks, drawerSlug, labels } = props
3922
40- const [ searchTerm , setSearchTerm ] = useState ( '' )
41- const [ filteredBlocks , setFilteredBlocks ] = useState ( blocks )
4223 const { closeModal, isModalOpen } = useModal ( )
4324 const { i18n, t } = useTranslation ( )
44- const { config } = useConfig ( )
45-
46- const blockGroups = useMemo ( ( ) => {
47- const groups : Record < string , ( ClientBlock | string ) [ ] > = {
48- _none : [ ] ,
49- }
50- filteredBlocks . forEach ( ( block ) => {
51- if ( typeof block === 'object' && block . admin ?. group ) {
52- const group = block . admin . group
53- const label = typeof group === 'string' ? group : getTranslation ( group , i18n )
54-
55- if ( Object . hasOwn ( groups , label ) ) {
56- groups [ label ] . push ( block )
57- } else {
58- groups [ label ] = [ block ]
59- }
60- } else {
61- groups . _none . push ( block )
62- }
63- } )
64- return groups
65- } , [ filteredBlocks , i18n ] )
25+ const [ searchTermOverride , setSearchTermOverride ] = React . useState ( '' )
6626
6727 useEffect ( ( ) => {
6828 if ( ! isModalOpen ( drawerSlug ) ) {
69- setSearchTerm ( '' )
29+ setSearchTermOverride ( '' )
7030 }
7131 } , [ isModalOpen , drawerSlug ] )
7232
73- useEffect ( ( ) => {
74- const searchTermToUse = searchTerm . toLowerCase ( )
75-
76- const matchingBlocks = blocks ?. reduce ( ( matchedBlocks , _block ) => {
77- const block = typeof _block === 'string' ? config . blocksMap [ _block ] : _block
78- const blockLabel = getBlockLabel ( block , i18n )
79- if ( blockLabel . includes ( searchTermToUse ) ) {
80- matchedBlocks . push ( block )
81- }
82- return matchedBlocks
83- } , [ ] )
84-
85- setFilteredBlocks ( matchingBlocks )
86- } , [ searchTerm , blocks , i18n , config . blocksMap ] )
87-
8833 return (
8934 < Drawer
9035 slug = { drawerSlug }
9136 title = { t ( 'fields:addLabel' , { label : getTranslation ( labels . singular , i18n ) } ) }
9237 >
93- < BlockSearch setSearchTerm = { setSearchTerm } />
94- < div className = { `${ baseClass } __blocks-wrapper` } >
95- < ul className = { `${ baseClass } __block-groups` } >
96- { Object . entries ( blockGroups ) . map ( ( [ groupLabel , groupBlocks ] ) =>
97- ! groupBlocks . length ? null : (
98- < li
99- className = { [
100- `${ baseClass } __block-group` ,
101- groupLabel === '_none' && `${ baseClass } __block-group-none` ,
102- ]
103- . filter ( Boolean )
104- . join ( ' ' ) }
105- key = { groupLabel }
106- >
107- { groupLabel !== '_none' && (
108- < h3 className = { `${ baseClass } __block-group-label` } > { groupLabel } </ h3 >
109- ) }
110- < ul className = { `${ baseClass } __blocks` } >
111- { groupBlocks . map ( ( _block , index ) => {
112- const block = typeof _block === 'string' ? config . blocksMap [ _block ] : _block
113-
114- const { slug, imageAltText, imageURL, labels : blockLabels } = block
115-
116- return (
117- < li className = { `${ baseClass } __block` } key = { index } >
118- < ThumbnailCard
119- alignLabel = "center"
120- label = { getTranslation ( blockLabels ?. singular , i18n ) }
121- onClick = { ( ) => {
122- void addRow ( addRowIndex , slug )
123- closeModal ( drawerSlug )
124- } }
125- thumbnail = {
126- < div className = { `${ baseClass } __default-image` } >
127- { imageURL ? (
128- < img alt = { imageAltText } src = { imageURL } />
129- ) : (
130- < DefaultBlockImage />
131- ) }
132- </ div >
133- }
134- />
135- </ li >
136- )
137- } ) }
138- </ ul >
139- </ li >
140- ) ,
141- ) }
142- </ ul >
143- </ div >
38+ < BlockSelector
39+ blocks = { blocks }
40+ onSelect = { ( slug ) => {
41+ void addRow ( addRowIndex , slug )
42+ closeModal ( drawerSlug )
43+ } }
44+ searchTerm = { searchTermOverride }
45+ />
14446 </ Drawer >
14547 )
14648}
0 commit comments