{"id":233738,"date":"2023-02-20T10:38:00","date_gmt":"2023-02-20T07:38:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233738"},"modified":"2023-02-26T12:09:20","modified_gmt":"2023-02-26T09:09:20","slug":"adicionar-configuracoes-personalizadas-aos-blocos-existentes-do-wordpress-gutenberg","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/adicionar-configuracoes-personalizadas-aos-blocos-existentes-do-wordpress-gutenberg\/","title":{"rendered":"Adicionar configura\u00e7\u00f5es personalizadas aos blocos existentes do WordPress Gutenberg"},"content":{"rendered":"\n<p>J\u00e1 se viu na situa\u00e7\u00e3o em que deseja adicionar suas configura\u00e7\u00f5es personalizadas aos blocos Gutenberg do WordPress? Neste post vamos detalhar como fazer isso. Voc\u00ea encontrar\u00e1 dois c\u00f3digos de exemplo de casos de uso da vida real para adicionar configura\u00e7\u00f5es personalizadas aos blocos do WordPress.<\/p>\n<p>Tenha em mente que, como os blocos do Gutenberg s\u00e3o Javascript, modific\u00e1-los requer que voc\u00ea escreva o c\u00f3digo em Javascript. Assim como o c\u00f3digo PHP do WordPress tem ganchos e filtros que permitem que desenvolvedores de temas ou plugins modifiquem seu c\u00f3digo, tamb\u00e9m existem filtros no c\u00f3digo Javascript do WordPress. Da mesma forma que a fun\u00e7\u00e3o do PHP <code>[add_filter](https:\/\/developer.wordpress.org\/reference\/functions\/add_filter\/)()<\/code>, temos a fun\u00e7\u00e3o Javascript <code>[addFilter](https:\/\/developer.wordpress.org\/block-editor\/packages\/packages-hooks\/#api-usage)()<\/code>.<\/p>\n<p>Estarei escrevendo o c\u00f3digo na sintaxe Javascript ES6, que requer um compilador para transform\u00e1-lo. Voc\u00ea pode escrever na sintaxe ES5, mas eu recomendo ir para ES6\/ESNext. Eu tenho um <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/guia-completo-em-configurando-um-ambiente-de-desenvolvimento-para-gutenberg\/\" title=\"post que explica como configurar um transformador para ES6\/ESNext\">post que explica como configurar um transformador para ES6\/ESNext<\/a>. Eu tamb\u00e9m suponho que voc\u00ea tenha alguma familiaridade com React\/JSX, possivelmente alguma experi\u00eancia em <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/como-criar-um-bloco-personalizado-do-wordpress-gutenberg-serie-de-tutoriais\/\" title=\"como criar seus pr\u00f3prios blocos Gutenberg personalizados\">como criar seus pr\u00f3prios blocos Gutenberg personalizados<\/a>.<\/p>\n<h2>O que voc\u00ea pode filtrar em blocos Gutenberg<\/h2>\n<p>N\u00e3o h\u00e1 muita documenta\u00e7\u00e3o em ganchos e filtros Gutenberg dispon\u00edveis. Mas com o prop\u00f3sito de adicionar configura\u00e7\u00f5es personalizadas e de alguma forma aplic\u00e1-las em blocos existentes; isso \u00e9 o que eu encontrei at\u00e9 agora. Concentrei-me em adicionar configura\u00e7\u00f5es simples \u2013 n\u00e3o em opera\u00e7\u00f5es que exigem mudan\u00e7as dr\u00e1sticas de componentes ou comportamento complexo.<\/p>\n<p>H\u00e1 tr\u00eas etapas para adicionar configura\u00e7\u00f5es personalizadas a blocos existentes:<\/p>\n<ul>\n<li><code>[registerBlockType](https:\/\/developer.wordpress.org\/block-editor\/developers\/block-api\/block-registration\/#registerblocktype)<\/code>Adicionamos um filtro no array de configura\u00e7\u00f5es do bloco existente. Isso nos permite adicionar novos atributos ao <code>attributes<\/code>array, permitindo assim salvar informa\u00e7\u00f5es adicionais no bloco. Precisamos salvar nossa configura\u00e7\u00e3o personalizada em algum lugar.<\/li>\n<li>Conecte-se ao componente do bloco <code>edit<\/code>(o componente respons\u00e1vel por renderizar o bloco no editor). Neste gancho, podemos nos conectar ao Inspetor (a barra lateral) e adicionar nossos pr\u00f3prios componentes. Podemos adicionar uma nova se\u00e7\u00e3o\/painel, ou podemos nos conectar \u00e0 se\u00e7\u00e3o &quot;Avan\u00e7ado&quot; que est\u00e1 sempre presente em todos os blocos. Ent\u00e3o cabe a n\u00f3s renderizar as entradas de configura\u00e7\u00e3o, como entradas de texto, caixas de sele\u00e7\u00e3o ou outros enfeites.<\/li>\n<li><code>save<\/code>Filtre os adere\u00e7os do bloco. Podemos ajustar as props para save, que \u00e9 respons\u00e1vel tanto por salvar o bloco quanto renderiz\u00e1-lo no frontend (fora do editor). No nosso caso, queremos adicionar uma classe ou estilo embutido.<\/li>\n<\/ul>\n<p>Podemos segmentar blocos espec\u00edficos ou segmentar todos. Sempre temos acesso ao tipo de bloco em que estamos.<\/p>\n<p>Em outras palavras: adicionamos algumas configura\u00e7\u00f5es personalizadas no Inspector e as salvamos em atributos personalizados que adicionamos ao bloco. Podemos ent\u00e3o influenciar o nome da classe do bloco ou o estilo inline (em alguns casos), dependendo dos atributos salvos. Com os nomes de classe personalizados, podemos facilmente adicionar CSS personalizado que visualmente d\u00e1 um efeito \u00e0s nossas configura\u00e7\u00f5es.<\/p>\n<h2>O que n\u00e3o podemos fazer (por enquanto?)<\/h2>\n<p>Infelizmente, existem algumas coisas que n\u00e3o podemos acessar com filtros em blocos existentes. No que diz respeito \u00e0 adi\u00e7\u00e3o de configura\u00e7\u00f5es personalizadas simples aos blocos, essas s\u00e3o coisas comuns que n\u00e3o podemos afetar.<\/p>\n<h3>Sem acesso ao estilo embutido do bloco dentro do editor<\/h3>\n<p>Em casos de configura\u00e7\u00f5es que afetam o design de um bloco, precisamos adicionar estilo inline no n\u00f3 de encapsulamento do bloco. Apenas o nome da classe n\u00e3o serve. Por exemplo, se voc\u00ea adicionar uma configura\u00e7\u00e3o de cor personalizada e o usu\u00e1rio selecionar uma cor personalizada (do colorpicker), voc\u00ea n\u00e3o poder\u00e1 resolver isso adicionando uma classe \u2013 voc\u00ea precisa de um estilo embutido.<\/p>\n<p>Infelizmente, parece que os blocos padr\u00e3o do WordPress lidam com o estilo inline no editor de forma totalmente independente, sem op\u00e7\u00e3o de filtragem ou &#8220;liga\u00e7\u00e3o&quot;. Mostrarei uma maneira de contornar isso no \u00faltimo exemplo abaixo, mas n\u00e3o \u00e9 ideal em todos os casos.<\/p>\n<p>Por que se importar que o bloco pare\u00e7a diferente no editor versus no frontend, voc\u00ea pode perguntar? O objetivo de Gutenberg \u00e9 implementar uma maneira visual de editar conte\u00fado onde o que vemos \u00e9 realmente o que obtemos. Queremos alcan\u00e7ar a mesma apar\u00eancia visual tanto no editor quanto no frontend.<\/p>\n<h3>Alguns blocos n\u00e3o incluem o nome da classe no editor<\/h3>\n<p>Como mencionado acima, podemos filtrar o nome da classe de encapsulamento do bloco, pois este \u00e9 um prop que \u00e9 passado para todos os blocos do Gutenberg. Mas, infelizmente, existem alguns blocos que n\u00e3o aplicam a classe do bloco em <code>edit<\/code>. Um exemplo \u00e9 o bloco Cover. Eu brinquei muito usando blocos Cover como &#8220;se\u00e7\u00f5es&#8221; para frontpages e continuo tendo problemas porque o bloco Cover constr\u00f3i sua pr\u00f3pria classe dentro do <code>edit<\/code>. Ele pula completamente a classe &#8220;global&#8221; do bloco (que \u00e9 a que temos acesso por meio de filtros).<\/p>\n<p>Mas pelo menos podemos ter certeza de que os nomes das classes filtradas s\u00e3o sempre aplicados em <code>save<\/code>(frontend). Isso acontece automaticamente fora do c\u00f3digo espec\u00edfico de cada bloco.<\/p>\n<p>Se eu estiver errado sobre qualquer um dos itens acima, por favor, deixe-me saber nos coment\u00e1rios abaixo! Estou continuamente aprendendo Gutenberg e, ao mesmo tempo, Gutenberg evolui tamb\u00e9m. Espero que em algum momento o acima seja poss\u00edvel em algum momento ou que seja poss\u00edvel, mas estou perdendo algumas informa\u00e7\u00f5es cruciais!<\/p>\n<p>Com isso fora do caminho, vamos come\u00e7ar a analisar algum c\u00f3digo.<\/p>\n<h2>Exemplo 1: adicionar um campo de altern\u00e2ncia para ocultar um bloco de capa no celular<\/h2>\n<p>Vamos supor que estamos desenvolvendo um tema onde os blocos de capa ser\u00e3o usados \u200b\u200bpara &#8220;se\u00e7\u00f5es&#8221; na primeira p\u00e1gina. E queremos fornecer ao usu\u00e1rio a possibilidade de ocultar uma determinada se\u00e7\u00e3o do celular. Para resolver isso, podemos adicionar um campo de altern\u00e2ncia na se\u00e7\u00e3o &#8220;Avan\u00e7ado&#8221; no Inspetor do bloco de capa. Se o campo estiver ativado, o bloco Cover obter\u00e1 uma classe personalizada adicional que podemos direcionar com CSS e consultas de m\u00eddia.<\/p>\n<p>A prop\u00f3sito: Este \u00e9 um caso em que o problema do bloco de capa n\u00e3o aplicar nossos nomes de classe personalizados no editor \u00e9 realmente um benef\u00edcio! Imagine se tivesse; ent\u00e3o seria imposs\u00edvel para o usu\u00e1rio editar o bloco no editor se ele tiver uma tela pequena!<\/p>\n<p>Como mencionado anteriormente, h\u00e1 tr\u00eas etapas para as quais precisamos codificar. Tamb\u00e9m precisamos adicionar algum PHP para enfileirar nosso arquivo Javascript no editor. Vamos fazer isso primeiro.<\/p>\n<h3>Adicionando nosso script ao editor<\/h3>\n<p>Conectamos uma fun\u00e7\u00e3o \u00e0 a\u00e7\u00e3o <code>[enqueue_block_editor_assets](https:\/\/developer.wordpress.org\/reference\/hooks\/enqueue_block_editor_assets\/)<\/code>. Dentro de nossa fun\u00e7\u00e3o n\u00f3s enfileiramos um script, assim como normalmente far\u00edamos no <code>wp_enqueue_scripts<\/code>hook.<\/p>\n<pre><code>add_action('enqueue_block_editor_assets', function() {\n    wp_enqueue_script('awp-gutenberg-filters', get_template_directory_uri(). '\/assets\/js\/gutenberg-filters.js', ['wp-edit-post']);\n});<\/code><\/pre>\n<p>Lembre-se de ajustar o caminho para onde seu script est\u00e1! Nota: Se voc\u00ea estiver escrevendo em ES6 com webpack compilando seu Javascript, lembre-se de definir o caminho para a constru\u00e7\u00e3o do seu script, n\u00e3o a fonte.<\/p>\n<p>Eu gosto de adicionar &#8216; <code>wp-edit-post<\/code>&#8216; como uma depend\u00eancia ao script para garantir que ele carregue tarde o suficiente.<\/p>\n<p>Isso \u00e9 todo o PHP que precisamos fazer. O resto est\u00e1 escrito em nosso arquivo Javascript.<\/p>\n<h3>Adicionar um atributo personalizado<\/h3>\n<p>O primeiro filtro que usaremos \u00e9 qual o objeto de configura\u00e7\u00f5es dos <code>blocks.registerBlockType<\/code>filtros .<code>registerBlockType<\/code><\/p>\n<p>Mas primeiro, um pouco sobre como adicionar filtros em Javascript. Como n\u00e3o encontrei nenhuma documenta\u00e7\u00e3o boa para isso, vou explicar um pouco aqui. A fun\u00e7\u00e3o <code>addFilter<\/code>est\u00e1 no <code>wp.hooks<\/code>namespace e aceita quatro argumentos.<\/p>\n<p><code>addFilter('hookName', 'namespace', 'functionName', 'priority');<\/code><\/p>\n<p>O primeiro par\u00e2metro, &#8216;hookName&#8217;, \u00e9 o nome do filtro ao qual queremos nos conectar. Este \u00e9 o equivalente ao primeiro par\u00e2metro ao usar PHP&#8217;s <code>add_filter()<\/code>. O segundo par\u00e2metro, &#8216;namespace&#8217;, \u00e9 um nome de namespace personalizado para seu c\u00f3digo. Isso \u00e9 apenas para evitar a colis\u00e3o de nomes. Voc\u00ea pode definir o que quiser aqui, apenas n\u00e3o use o namespace do WordPress (&#8216;wp&#8217;). Use uma forma abreviada de seu nome ou nome do projeto. O terceiro par\u00e2metro, &#8216;functionName&#8217;, \u00e9 a fun\u00e7\u00e3o hooked \u2013 que \u00e9 o mesmo que o <code>add_filter()<\/code>segundo argumento do PHP. E, finalmente, o quarto par\u00e2metro, &#8216;prioridade&#8217;, \u00e9 opcional. Novamente, isso \u00e9 o mesmo que o <code>add_filter()<\/code>terceiro argumento do PHP.<\/p>\n<p>O processo para filtros em Javascript \u00e9 o mesmo que em PHP. Definimos uma fun\u00e7\u00e3o que precisa retornar a vari\u00e1vel filtrada. \u00c0s vezes, a vari\u00e1vel \u00e9 uma string, um objeto ou um componente. Dentro da fun\u00e7\u00e3o, modificamos a vari\u00e1vel conforme acharmos adequado.<\/p>\n<p>No nosso caso queremos adicionar um novo atributo ao <code>attribute<\/code>objeto do bloco. Chamaremos o novo atributo <code>hideOnMobile<\/code>e definiremos seu tipo como <code>boolean<\/code>. Isso \u00e9 feito assim:<\/p>\n<pre><code>function addCoverAttribute(settings, name) {\n    if (typeof settings.attributes !== 'undefined') {\n        if (name == 'core\/cover') {\n            settings.attributes = Object.assign(settings.attributes, {\n                hideOnMobile: {\n                    type: 'boolean',\n                }\n            });\n        }\n    }\n    return settings;\n}\n\u00a0\nwp.hooks.addFilter(\n    'blocks.registerBlockType',\n    'awp\/cover-custom-attribute',\n    addCoverAttribute\n);<\/code><\/pre>\n<p>Na linha <code>#3<\/code>, certificamo-nos de segmentar apenas blocos do tipo &#8216; <code>core\/cover<\/code>&#8216;. O segundo argumento para <code>blocks.registerBlockType<\/code>filtrar \u00e9 convenientemente o nome do bloco. Em seguida, adicionamos um novo item de objeto ao <code>settings.attributes<\/code>objeto. Por fim, certificamo-nos de retornar a vari\u00e1vel filtrada, <code>settings<\/code>.<\/p>\n<p>Neste ponto, visualmente, nada \u00e9 alterado em Gutenberg. Mas todos os blocos Cover agora t\u00eam um atributo adicional que podemos usar para armazenar nossa configura\u00e7\u00e3o.<\/p>\n<h3>Adicionar configura\u00e7\u00e3o ao Inspetor (painel Avan\u00e7ado)<\/h3>\n<p>O segundo filtro \u00e9 chamado <code>editor.BlockEdit<\/code>e filtra o componente do bloco <code>edit<\/code>. Este filtro recebe o componente do bloco original <code>BlockEdit<\/code>e retorna um novo componente encapsulado. Precisamos usar <code>wp.compose.createHigherOrderComponent<\/code>para retornar o componente encapsulado.<\/p>\n<p>Dentro do nosso componente, certificamo-nos de renderizar o componente encapsulado <code>BlockEdit<\/code>, independentemente. Mas se o bloco for do tipo Cover, tamb\u00e9m conectamos ao componente <code>InspectorAdvancedControls<\/code>(que \u00e9 o painel &#8220;Avan\u00e7ado&#8221; no Inspector) e adicionamos um arquivo <code>ToggleControl<\/code>. Escrevemos o <code>ToggleControl<\/code>para mostrar o valor e atualizar o atributo personalizado que adicionamos anteriormente, <code>hideOnMobile<\/code>.<\/p>\n<pre><code>const coverAdvancedControls = wp.compose.createHigherOrderComponent((BlockEdit) =&gt; {\n    return (props) =&gt; {\n        const { Fragment } = wp.element;\n        const { ToggleControl } = wp.components;\n        const { InspectorAdvancedControls } = wp.blockEditor;\n        const { attributes, setAttributes, isSelected } = props;\n        return (&lt;Fragment&gt;\n                &lt;BlockEdit {...props} \/&gt;\n                {isSelected &amp;&amp; (props.name == 'core\/cover') &amp;&amp; \n                    &lt;InspectorAdvancedControls&gt;\n                        &lt;ToggleControl\n                            label={wp.i18n.__('Hide on mobile', 'awp')}\n                            checked={!!attributes.hideOnMobile}\n                            onChange={(newval) =&gt; setAttributes({ hideOnMobile: !attributes.hideOnMobile })}\n                        \/&gt;\n                    &lt;\/InspectorAdvancedControls&gt;\n                }\n            &lt;\/Fragment&gt;\n        );\n    };\n}, 'coverAdvancedControls');\n\u00a0\nwp.hooks.addFilter(\n    'editor.BlockEdit',\n    'awp\/cover-advanced-control',\n    coverAdvancedControls\n);<\/code><\/pre>\n<p>N\u00e3o se esque\u00e7a de devolver sempre o original <code>BlockEdit<\/code>, o que fazemos na linha <code>#9<\/code>. Na linha #10 verificamos se o tipo do bloco \u00e9 Cover e renderizamos o <code>InspectorAdvancedControls<\/code>componente. Dentro daqui adicionamos um <code>ToggleControl<\/code>, que \u00e9 um controle de entrada que \u00e9 exibido como uma altern\u00e2ncia entre true ou false. Definimos um r\u00f3tulo e conectamos seu valor ao <code>hideOnMobile<\/code>atributo. Se voc\u00ea adicionou configura\u00e7\u00f5es ao Inspetor antes, isso deve ser bastante simples para voc\u00ea.<\/p>\n<p>Com o c\u00f3digo acima, agora devemos obter isso dentro do painel &#8220;Avan\u00e7ado&#8221; nos blocos Inspector on Cover:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d70271f5a.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d70271f5a.png\" alt=\"Adicionar configura\u00e7\u00f5es personalizadas aos blocos existentes do WordPress Gutenberg\"><\/a><\/p>\n<p>A entrada agora atualizar\u00e1 nosso atributo personalizado <code>hideOnMobile<\/code>. O \u00faltimo passo \u00e9 fazer algo dependendo do valor deste atributo. A partir de agora, o atributo \u00e9 salvo, mas na verdade n\u00e3o afeta nada.<\/p>\n<h3>Adicionar uma classe personalizada<\/h3>\n<p>A etapa final \u00e9 adicionar uma classe personalizada \u00e0 classe do bloco. Fazemos isso com o filtro <code>blocks.getSaveContent.extraProps<\/code>. <code>save<\/code>Este filtro afeta os adere\u00e7os do componente do bloco. Um deles \u00e9 o prop <code>className<\/code>, que sempre ser\u00e1 aplicado no frontend. Simplesmente anexamos nossa classe personalizada depois dela se o atributo for <code>true<\/code>, e depois a retornamos. Decidi adicionar uma classe &#8216; <code>hide-on-mobile<\/code>&#8216;, mas voc\u00ea pode cham\u00e1-la como quiser.<\/p>\n<pre><code>function coverApplyExtraClass(extraProps, blockType, attributes) {\n    const { hideOnMobile } = attributes;\n\u00a0\n    if (typeof hideOnMobile !== 'undefined' &amp;&amp; hideOnMobile) {\n        extraProps.className = extraProps.className + ' hide-on-mobile';\n    }\n    return extraProps;\n}\n\u00a0\nwp.hooks.addFilter(\n    'blocks.getSaveContent.extraProps',\n    'awp\/cover-apply-class',\n    coverApplyExtraClass\n);<\/code><\/pre>\n<p>Este c\u00f3digo \u00e9 bastante autoexplicativo. Na linha <code>#4<\/code>verificamos se o atributo <code>hideOnMobile<\/code>existe e \u00e9 <code>true<\/code>. Nesse caso, anexamos uma classe personalizada \u00e0 <code>className<\/code>string.<\/p>\n<p>Com todos os tr\u00eas filtros acima, agora devemos obter uma classe personalizada &#8216;hide-on-mobile&#8217; aplicada ao nosso bloco Cover sempre que a configura\u00e7\u00e3o for ativada.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d70343817.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d70343817.png\" alt=\"Adicionar configura\u00e7\u00f5es personalizadas aos blocos existentes do WordPress Gutenberg\"><\/a><\/p>\n<p>Tudo o que resta \u00e9 adicionar um pouco de CSS \u00e0 folha de estilo do frontend do seu tema. Algo assim;<\/p>\n<pre><code>.wp-block-cover.hide-on-mobile { display: none; }\n@media (min-width: 480px) {\n    .wp-block-cover.hide-on-mobile { display: block; }\n}<\/code><\/pre>\n<h2>Exemplo 2: Adicionar painel Inspetor com configura\u00e7\u00e3o de cor de fundo personalizada para bloco Espa\u00e7ador<\/h2>\n<p>Para o segundo caso de uso, queremos adicionar configura\u00e7\u00f5es de cores personalizadas ao bloco Espa\u00e7ador. Por padr\u00e3o, o bloco Espa\u00e7ador n\u00e3o possui outras configura\u00e7\u00f5es al\u00e9m de sua altura. Vamos supor que queremos adicionar uma cor de fundo que colora a altura total do bloco Espa\u00e7ador. Isso permite que o usu\u00e1rio adicione &#8220;faixas&#8221; vazias e coloridas dentro de seu conte\u00fado. Nesse caso, queremos adicionar as configura\u00e7\u00f5es de cores em seu pr\u00f3prio painel separado no Inspetor, conforme o comportamento normal esperado para as configura\u00e7\u00f5es de cores.<\/p>\n<p>Nota: O manuseio de cores \u00e9 um pouco mais complicado, pois precisamos usar um (outro) componente de ordem superior <code>withColors<\/code>. Porque j\u00e1 precisamos implementar um componente de ordem superior no <code>editor.BlockEdit<\/code>que precisamos para <code>compose<\/code>v\u00e1rios componentes. Al\u00e9m disso, precisamos adicionar dois atributos para cada configura\u00e7\u00e3o de cor. Um conter\u00e1 o slug da paleta de cores e o outro conter\u00e1 o c\u00f3digo de cor hexadecimal \u2013 somente se o usu\u00e1rio tiver optado por uma cor personalizada (usado o colorpicker). Esse \u00e9 um comportamento comum ao trabalhar com <code>withColors<\/code>. Eu tenho um &lt;a href=&quot;https:\/\/wordpress.mediadoma.com\/pt-pt\/como-adicionar-configuracoes-de-cores-ao-seu-bloco-gutenberg-personalizado\/&quot; title=&quot;post que explica como adicionar configura\u00e7\u00f5es de cores e <code>withColors<\/code>em detalhes&#8221; &gt;post que explica como adicionar configura\u00e7\u00f5es de cores e <code>withColors<\/code>em detalhes<\/a> se voc\u00ea ficar confuso.<\/p>\n<p>Em segundo lugar, neste caso, nos depararemos com a quest\u00e3o explicada acima; onde n\u00e3o podemos adicionar o estilo inline apropriado ao editor. A solu\u00e7\u00e3o que optei neste caso \u00e9 envolver o bloco Spacer dentro de a <code>div<\/code>no editor e aplicar as classes apropriadas e o estilo inline ao wrapper <code>div<\/code>. Isso torna a cor selecionada vis\u00edvel no editor quando o bloco \u00e9 desmarcado. Ao selecionar o bloco, no entanto, o WordPress adiciona seu pr\u00f3prio plano de fundo cinza claro personalizado ao bloco, cobrindo nossa cor de plano de fundo personalizada. Um CSS para o editor corrigir\u00e1 isso. Vou explicar mais no final.<\/p>\n<p>Os passos s\u00e3o os mesmos do exemplo acima. Enfileiramos nosso script para o editor em PHP primeiro. Ent\u00e3o em Javascript filtramos o <code>attributes<\/code>objeto, o <code>edit<\/code>componente do Espa\u00e7ador e finalmente o <code>save<\/code>componente do Espa\u00e7ador.<\/p>\n<h3>Adicionando nosso script ao editor<\/h3>\n<p>Conectamos uma fun\u00e7\u00e3o \u00e0 a\u00e7\u00e3o <code>[enqueue_block_editor_assets](https:\/\/developer.wordpress.org\/reference\/hooks\/enqueue_block_editor_assets\/)<\/code>. Dentro de nossa fun\u00e7\u00e3o n\u00f3s enfileiramos um script, assim como normalmente far\u00edamos no <code>wp_enqueue_scripts<\/code>hook.<\/p>\n<pre><code>add_action('enqueue_block_editor_assets', function() {\n    wp_enqueue_script('awp-gutenberg-filters', get_template_directory_uri(). '\/assets\/js\/gutenberg-filters.js', ['wp-edit-post']);\n});<\/code><\/pre>\n<p>Lembre-se de ajustar o caminho ao seu script. Eu gosto de adicionar &#8216; <code>wp-edit-post<\/code>&#8216; como uma depend\u00eancia ao script para garantir que ele carregue tarde o suficiente.<\/p>\n<p>Isso \u00e9 todo o PHP que precisamos fazer. O resto est\u00e1 escrito em nosso arquivo Javascript.<\/p>\n<h3>Adicionar atributos personalizados<\/h3>\n<p>Como no exemplo acima, adicionamos um filtro <code>blocks.registerBlockType<\/code>para adicionar itens de objeto adicionais ao objeto do bloco <code>attributes<\/code>.<\/p>\n<p>Ao trabalhar com <code>withColors<\/code>, precisamos adicionar dois atributos para cada cor. O nome do nosso atributo de cor de fundo \u00e9 <code>backgroundColor<\/code>, o que significa que o segundo atributo deve ser nomeado <code>customBackgroundColor<\/code>. Tudo isso \u00e9 explicado no <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/como-adicionar-configuracoes-de-cores-ao-seu-bloco-gutenberg-personalizado\/\" title=\"meu post sobre como lidar com configura\u00e7\u00f5es de cores em Gutenberg\">meu post sobre como lidar com configura\u00e7\u00f5es de cores em Gutenberg<\/a>. Ambos devem ser do tipo string, e aplicados apenas a blocos do tipo Spacer.<\/p>\n<pre><code>function addSpacerAttributes(settings, name) {\n    if (typeof settings.attributes !== 'undefined') {\n        if (name == 'core\/spacer') {\n            settings.attributes = Object.assign(settings.attributes, {\n                backgroundColor: {\n                    type: 'string',\n                },\n                customBackgroundColor: {\n                    type: 'string'\n                }\n            });\n        }\n    }\n    return settings;\n}\n\u00a0\nwp.hooks.addFilter(\n    'blocks.registerBlockType',\n    'awp\/spacer-background-attribute',\n    addSpacerAttributes\n);<\/code><\/pre>\n<h3>Adicionar painel ColorSettings ao Inspetor<\/h3>\n<p>A segunda etapa \u00e9 adicionar um painel de configura\u00e7\u00f5es de cores ao Inspetor para o bloco Espa\u00e7ador filtrando <code>editor.BlockEdit<\/code>.<\/p>\n<pre><code>const spacerInspectorControls = wp.compose.compose(\n    wp.blockEditor.withColors({backgroundColor: 'background-color'}),\n\u00a0\n    wp.compose.createHigherOrderComponent((BlockEdit) =&gt; {\n        return (props) =&gt; {\n\u00a0\n            if (props.name !== 'core\/spacer') {\n                return(&lt;BlockEdit {...props} \/&gt;);\n            }\n\u00a0\n            const { Fragment } = wp.element;\n            const { InspectorControls, PanelColorSettings } = wp.blockEditor;\n            const { attributes, setAttributes, isSelected } = props;\n            const { backgroundColor, setBackgroundColor } = props;\n\u00a0\n            let newClassName = (attributes.className != undefined)? attributes.className: '';\n            let newStyles = {...props.style};\n            if (backgroundColor != undefined) {\n                if (backgroundColor.class == undefined) {\n                    newStyles.backgroundColor = backgroundColor.color;\n                } else {\n                    newClassName += ' ' + backgroundColor.class;\n                }\n            }\n            const newProps = {\n                ...props,\n                attributes: {\n                    ...attributes,\n                    className: newClassName\n                },\n                style: newStyles\n            }\n\u00a0\n            return (&lt;Fragment&gt;\n                    &lt;div style={newStyles} className={newClassName}&gt;\n                        &lt;BlockEdit {...newProps} \/&gt;\n                        {isSelected &amp;&amp; (props.name == 'core\/spacer') &amp;&amp; \n                            &lt;InspectorControls&gt;\n                                &lt;PanelColorSettings \n                                    title={wp.i18n.__('Color Settings', 'awp')}\n                                    colorSettings={[\n                                        {\n                                            value: backgroundColor.color,\n                                            onChange: setBackgroundColor,\n                                            label: wp.i18n.__('Background color', 'awp')\n                                        }\n                                    ]}\n                                \/&gt;\n                            &lt;\/InspectorControls&gt;\n                        }\n                    &lt;\/div&gt;\n                &lt;\/Fragment&gt;\n            );\n        };\n}, 'spacerInspectorControls'));\n\u00a0\nwp.hooks.addFilter(\n    'editor.BlockEdit',\n    'awp\/spacer-inspector-control',\n    spacerInspectorControls\n);<\/code><\/pre>\n<p>Precisamos usar <code>compose<\/code>para combinar o componente de ordem superior retornado desse filtro e <code>withColors<\/code>. Em outras palavras, n\u00f3s simplesmente envolvemos o componente retornado em <code>withColors<\/code>. Como par\u00e2metro para <code>withColors<\/code>n\u00f3s fornecemos nosso atributo <code>backgroundColor<\/code>.<\/p>\n<p>Dentro do componente encapsulado, sempre retornamos <code>BlockEdit<\/code>(linha <code>#9<\/code>e <code>#39<\/code>para blocos espa\u00e7adores). Para blocos do tipo Espa\u00e7ador, tamb\u00e9m conectamos <code>InspectorControls<\/code>para adicionar um <code>PanelColorSettings<\/code>para nossa escolha de cor. Este \u00e9 o procedimento padr\u00e3o de adi\u00e7\u00e3o de configura\u00e7\u00f5es de cores.<\/p>\n<p>Na linha <code>#17 - 34<\/code>geramos manualmente a classe necess\u00e1ria e\/ou o estilo inline. Em seguida, na linha <code>#38<\/code>, adicionamos uma div envolvente <code>BlockEdit<\/code>com essas classes e estilos embutidos.<\/p>\n<p>O resultado \u00e9 um novo painel de configura\u00e7\u00f5es de cores no Inspector for Spacer blocks, totalmente funcional.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d7041a66b.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d7041a66b.png\" alt=\"Adicionar configura\u00e7\u00f5es personalizadas aos blocos existentes do WordPress Gutenberg\"><\/a><\/p>\n<p>Escolher uma cor de paleta ou uma cor personalizada ser\u00e1 realmente afetada na div de encapsulamento dentro do editor. Mas voc\u00ea s\u00f3 pode v\u00ea-lo quando desmarcar o bloco Espa\u00e7ador!<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d7052e0c9.gif\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-152421-61e4d7052e0c9.gif\" alt=\"Adicionar configura\u00e7\u00f5es personalizadas aos blocos existentes do WordPress Gutenberg\"><\/a><\/p>\n<p>Isso acontece porque o WordPress aplica seu pr\u00f3prio estilo ao selecionar um bloco espa\u00e7ador. Vamos corrigi-lo no final, primeiro s\u00f3 precisamos aplicar a mesma classe e\/ou estilo inline no frontend tamb\u00e9m.<\/p>\n<h3>Adicione classe personalizada e estilo embutido para salvar<\/h3>\n<p>Finalmente, precisamos filtrar <code>blocks.getSaveContent.extraProps<\/code>e aplicar a classe necess\u00e1ria e\/ou o estilo inline para o frontend. Novamente, isso \u00e9 muito semelhante ao que fizemos no exemplo 1 acima. Se uma cor de paleta foi escolhida, precisamos adicionar um nome de classe que siga os padr\u00f5es do WordPress para configura\u00e7\u00f5es de cores (&#8221; <code>has-&lt;PALETTESLUG&gt;-background-color<\/code>&#8220;). Se uma cor personalizada foi escolhida, precisamos adicionar um estilo inline com a cor hexadecimal.<\/p>\n<p>Nota: Se voc\u00ea precisar lidar muito com nomes de classes, recomendo importar a <code>classnames<\/code>biblioteca. Isso \u00e9 muito utilizado no Gutenberg porque simplifica muito a defini\u00e7\u00e3o dos nomes de classe apropriados. O c\u00f3digo abaixo assume que voc\u00ea n\u00e3o o fez e comp\u00f5e o nome da classe manualmente.<\/p>\n<pre><code>function applySpacerBackground(props, blockType, attributes) {\n    if (blockType.name == 'core\/spacer') {\n        const { backgroundColor, customBackgroundColor } = attributes;\n\u00a0\n        \/\/ For improved class name handling, use classnames library. Or do it manually like..\n        let className = (props.className != undefined)? props.className: '';\n        if (backgroundColor != undefined) {\n            className += ' has-' + backgroundColor + '-background-color';\n        }\n        props.className = className;\n        if (customBackgroundColor != undefined) {\n            Object.assign(props, { style: { ...props.style, backgroundColor: customBackgroundColor }});\n        }\n    }\n    return props;\n}\n\u00a0\nwp.hooks.addFilter(\n    'blocks.getSaveContent.extraProps',\n    'awp\/spacer-apply-class',\n    applySpacerBackground\n);<\/code><\/pre>\n<p>Com o c\u00f3digo acima, o frontend agora renderizar\u00e1 perfeitamente os blocos Spacer com nossa op\u00e7\u00e3o de cor personalizada!<\/p>\n<p>A corre\u00e7\u00e3o final (opcional) \u00e9 adicionar algum CSS ao editor. Voc\u00ea precisar\u00e1 adicionar CSS embutido ou uma folha de estilo do editor. Por exemplo, voc\u00ea pode enfileirar uma folha de estilo no mesmo gancho PHP que usamos para enfileirar nosso arquivo Javascript. N\u00e3o entrarei em detalhes sobre como fazer isso; mas o CSS que voc\u00ea precisa \u00e9 algo como o abaixo. Tudo o que ele faz \u00e9 definir o espa\u00e7ador <code>background-color<\/code>para a cor herdada (ele herdar\u00e1 de nossa div de encapsulamento) quando o bloco for selecionado:<\/p>\n<pre><code>.block-library-spacer__resize-container.is-selected { \n    background-color: inherit; \n}<\/code><\/pre>\n<p>PS: Tenha em mente que isso est\u00e1 sujeito a altera\u00e7\u00f5es no futuro. Gutenberg ainda est\u00e1 em forte evolu\u00e7\u00e3o.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>Neste post, aprendemos dois m\u00e9todos de implementa\u00e7\u00e3o de configura\u00e7\u00f5es personalizadas para blocos existentes do WordPress Gutenberg. \u00c9 totalmente poss\u00edvel para configura\u00e7\u00f5es simples que talvez requeiram apenas uma classe ou estilo embutido. Vimos as advert\u00eancias, que espero que sejam corrigidas em vers\u00f5es posteriores do Gutenberg!<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Neste post, entraremos em detalhes sobre como adicionar suas configura\u00e7\u00f5es personalizadas aos blocos Gutenberg existentes do WordPress com dois exemplos de c\u00f3digo de casos de uso da vida real.<\/p>\n","protected":false},"author":1,"featured_media":152422,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,898,722,722,837,941,941,1110,837,846,846,867,867],"tags":[1170],"class_list":["post-233738","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-guia-para-iniciantes","category-gutenberg-8","category-n-a","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/233738","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=233738"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/233738\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/152422"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=233738"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=233738"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=233738"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}