{"id":233678,"date":"2023-02-20T10:43:00","date_gmt":"2023-02-20T07:43:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233678"},"modified":"2023-02-26T12:28:11","modified_gmt":"2023-02-26T09:28:11","slug":"agregue-configuraciones-personalizadas-a-los-bloques-existentes-de-wordpress-gutenberg","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/agregue-configuraciones-personalizadas-a-los-bloques-existentes-de-wordpress-gutenberg\/","title":{"rendered":"Agregue configuraciones personalizadas a los bloques existentes de WordPress Gutenberg"},"content":{"rendered":"\n<p>\u00bfAlguna vez se encontr\u00f3 en la situaci\u00f3n en la que desea agregar su configuraci\u00f3n personalizada a los bloques de Gutenberg de WordPress? En esta publicaci\u00f3n entraremos en detalles sobre c\u00f3mo hacerlo. Encontrar\u00e1 dos c\u00f3digos de ejemplo de casos de uso de la vida real para agregar configuraciones personalizadas a los bloques de WordPress.<\/p>\n<p>Tenga en cuenta que debido a que los bloques de Gutenberg son Javascript, modificarlos requiere que escriba el c\u00f3digo en Javascript. Al igual que el c\u00f3digo PHP de WordPress tiene ganchos y filtros que permiten a los desarrolladores de temas o complementos modificar su c\u00f3digo, tambi\u00e9n hay filtros en el c\u00f3digo Javascript de WordPress. De manera similar a la funci\u00f3n de PHP <code>[add_filter](https:\/\/developer.wordpress.org\/reference\/functions\/add_filter\/)()<\/code>, tenemos la funci\u00f3n de Javascript <code>[addFilter](https:\/\/developer.wordpress.org\/block-editor\/packages\/packages-hooks\/#api-usage)()<\/code>.<\/p>\n<p>Escribir\u00e9 el c\u00f3digo en la sintaxis de Javascript ES6, que requiere un compilador para transformarlo. Puede escribir en la sintaxis de ES5, pero recomiendo ir a ES6\/ESNext. Tengo una <a href=\"https:\/\/wordpress.mediadoma.com\/es\/guia-completa-para-configurar-un-entorno-de-desarrollo-para-gutenberg\/\" title=\"publicaci\u00f3n que explica c\u00f3mo configurar un transformador para ES6\/ESNext\">publicaci\u00f3n que explica c\u00f3mo configurar un transformador para ES6\/ESNext<\/a>. Tambi\u00e9n asumo que tiene cierta familiaridad con React\/JSX, posiblemente alguna experiencia en <a href=\"https:\/\/wordpress.mediadoma.com\/es\/como-crear-un-bloque-gutenberg-de-wordpress-personalizado-serie-de-tutoriales\/\" title=\"c\u00f3mo crear sus propios bloques de Gutenberg personalizados\">c\u00f3mo crear sus propios bloques de Gutenberg personalizados<\/a>.<\/p>\n<h2>Qu\u00e9 puedes filtrar en los bloques de Gutenberg<\/h2>\n<p>No hay mucha documentaci\u00f3n en los ganchos y filtros de Gutenberg disponibles. Pero con el prop\u00f3sito de agregar configuraciones personalizadas y aplicarlas de alguna manera a los bloques existentes; esto es lo que he encontrado hasta ahora. Me he centrado en agregar configuraciones simples, no operaciones que requieren cambios dr\u00e1sticos en los componentes o un comportamiento complejo.<\/p>\n<p>Hay tres pasos para agregar configuraciones personalizadas a los bloques existentes:<\/p>\n<ul>\n<li>Agregamos un filtro en la <code>[registerBlockType](https:\/\/developer.wordpress.org\/block-editor\/developers\/block-api\/block-registration\/#registerblocktype)<\/code>matriz de configuraci\u00f3n del bloque existente. Esto nos permite agregar nuevos atributos a la <code>attributes<\/code>matriz, lo que nos permite guardar informaci\u00f3n adicional en el bloque. Necesitamos guardar nuestra configuraci\u00f3n personalizada en alg\u00fan lugar.<\/li>\n<li>Eng\u00e1nchese al componente del bloque <code>edit<\/code>(el componente responsable de representar el bloque en el editor). En este gancho podemos conectarnos al Inspector (la barra lateral) y agregar nuestros propios componentes. Podemos agregar una nueva secci\u00f3n\/panel, o podemos conectarnos a la secci\u00f3n &quot;Avanzada&quot; que siempre est\u00e1 presente en todos los bloques. Luego, depende de nosotros representar las entradas de configuraci\u00f3n, como entradas de texto, casillas de verificaci\u00f3n o lo que sea.<\/li>\n<li><code>save<\/code>Filtra los accesorios del bloque. Podemos ajustar los accesorios para guardar, que es responsable tanto de guardar el bloque como de mostrarlo en la interfaz (fuera del editor). En nuestro caso, queremos agregar una clase o un estilo en l\u00ednea.<\/li>\n<\/ul>\n<p>Podemos apuntar a bloques espec\u00edficos o apuntar a todos. Siempre tenemos acceso al tipo de bloque en el que estamos.<\/p>\n<p>Para decirlo en otras palabras: agregamos algunas configuraciones personalizadas en Inspector y las guardamos en atributos personalizados que hemos agregado al bloque. Luego podemos influir en el nombre de la clase del bloque o en el estilo en l\u00ednea (en algunos casos), seg\u00fan los atributos guardados. Con los nombres de clase personalizados, podemos agregar f\u00e1cilmente CSS personalizado que le da un efecto visual a nuestra configuraci\u00f3n.<\/p>\n<h2>Lo que no podemos hacer (\u00bfpor ahora?)<\/h2>\n<p>Desafortunadamente, hay algunas cosas a las que no podemos acceder con filtros en bloques existentes. En lo que respecta a agregar configuraciones personalizadas simples a los bloques, estas son cosas comunes que no podemos afectar.<\/p>\n<h3>Sin acceso al estilo en l\u00ednea del bloque dentro del editor<\/h3>\n<p>En casos de configuraciones que afectan el dise\u00f1o de un bloque, necesitamos agregar un estilo en l\u00ednea en el nodo de ajuste del bloque. Solo el nombre de la clase no servir\u00e1. Por ejemplo, si agrega una configuraci\u00f3n de color personalizada y el usuario selecciona un color personalizado (del selector de colores), no puede resolver esto agregando una clase; necesita un estilo en l\u00ednea.<\/p>\n<p>Desafortunadamente, parece que los bloques predeterminados de WordPress manejan el estilo en l\u00ednea en el editor de forma completamente independiente sin opci\u00f3n de filtrado o &quot;enganche&quot;. Mostrar\u00e9 una forma de evitar esto en el \u00faltimo ejemplo a continuaci\u00f3n, pero no es ideal en todos los casos.<\/p>\n<p>\u00bfPor qu\u00e9 le importa que el bloque se vea diferente en el editor que en la interfaz? El objetivo de Gutenberg es implementar una forma visual de editar contenido donde lo que vemos es en realidad lo que obtenemos. Queremos lograr el mismo aspecto visual tanto en el editor como en la interfaz.<\/p>\n<h3>Algunos bloques no incluyen el nombre de la clase en el editor<\/h3>\n<p>Como se mencion\u00f3 anteriormente, podemos filtrar el nombre de la clase de ajuste del bloque, ya que se trata de un accesorio que se pasa a todos los bloques de Gutenberg. Pero, desafortunadamente, hay algunos bloques que no aplican la clase del bloque en absoluto en <code>edit<\/code>. Un ejemplo es el bloque Cover. He jugado mucho con los bloques de portada como &quot;secciones&quot; para las portadas, y sigo teniendo problemas porque el bloque de portada crea su propia clase dentro de <code>edit<\/code>. Se salta por completo incluir la clase \u00abglobal&quot; del bloque (que es a la que tenemos acceso a trav\u00e9s de filtros).<\/p>\n<p>Pero al menos podemos estar seguros de que los nombres de clase filtrados siempre se aplican en <code>save<\/code>(frontend). Esto sucede autom\u00e1ticamente fuera del c\u00f3digo espec\u00edfico de cada bloque.<\/p>\n<p>Si me equivoco acerca de cualquiera de los anteriores, \u00a1POR FAVOR h\u00e1gamelo saber en los comentarios a continuaci\u00f3n! Estoy continuamente aprendiendo Gutenberg y, al mismo tiempo, Gutenberg tambi\u00e9n evoluciona. Espero que en alg\u00fan momento lo anterior sea posible en alg\u00fan momento o que sea posible, \u00a1pero solo me falta informaci\u00f3n crucial!<\/p>\n<p>Con eso fuera del camino, comencemos a buscar algo de c\u00f3digo.<\/p>\n<h2>Ejemplo 1: agregue un campo de alternancia para ocultar un bloque de portada en un dispositivo m\u00f3vil<\/h2>\n<p>Supongamos que estamos desarrollando un tema en el que los bloques de portada se utilizar\u00e1n para las &quot;secciones&quot; en la p\u00e1gina principal. Y queremos brindarle al usuario la posibilidad de ocultar una determinada secci\u00f3n del dispositivo m\u00f3vil. Para resolver esto, podemos agregar un campo de alternancia en la secci\u00f3n &quot;Avanzado&quot; en el Inspector del bloque Portada. Si el campo est\u00e1 activado, el bloque Portada obtendr\u00e1 una clase personalizada adicional a la que podemos apuntar con CSS y consultas de medios.<\/p>\n<p>Por cierto: \u00a1este es un caso en el que el problema de que el bloque de portada no aplica nuestros nombres de clase personalizados en el editor es realmente un beneficio! Imag\u00ednese si lo hiciera; \u00a1entonces ser\u00eda imposible para el usuario editar el bloque en el editor si tiene una pantalla peque\u00f1a!<\/p>\n<p>Como se mencion\u00f3 anteriormente, hay tres pasos que debemos codificar. Tambi\u00e9n necesitamos agregar algo de PHP para poner en cola nuestro archivo Javascript en el editor. Hagamos eso primero.<\/p>\n<h3>Agregando nuestro script al editor<\/h3>\n<p>Enganchamos una funci\u00f3n a la acci\u00f3n <code>[enqueue_block_editor_assets](https:\/\/developer.wordpress.org\/reference\/hooks\/enqueue_block_editor_assets\/)<\/code>. Dentro de nuestra funci\u00f3n, ponemos en cola un script, tal como lo har\u00edamos normalmente en <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>\u00a1Recuerde ajustar la ruta a donde est\u00e1 su secuencia de comandos! Nota: si est\u00e1 escribiendo en ES6 con un paquete web compilando su Javascript, recuerde establecer la ruta a la compilaci\u00f3n de su secuencia de comandos, no la fuente.<\/p>\n<p>Me gusta agregar &#8216; <code>wp-edit-post<\/code>&#8216; como una dependencia al script para asegurar que se cargue lo suficientemente tarde.<\/p>\n<p>Eso es todo el PHP que necesitamos hacer. El resto est\u00e1 escrito en nuestro archivo Javascript.<\/p>\n<h3>Agregar un atributo personalizado<\/h3>\n<p>El primer filtro que usaremos es el objeto de configuraci\u00f3n de los <code>blocks.registerBlockType<\/code>filtros .<code>registerBlockType<\/code><\/p>\n<p>Pero primero, un poco sobre agregar filtros en Javascript. Como no he encontrado ninguna buena documentaci\u00f3n para esto, lo explicar\u00e9 un poco aqu\u00ed. La funci\u00f3n <code>addFilter<\/code>est\u00e1 en el espacio de <code>wp.hooks<\/code>nombres y acepta cuatro argumentos.<\/p>\n<p><code>addFilter('hookName', 'namespace', 'functionName', 'priority');<\/code><\/p>\n<p>El primer par\u00e1metro, &#8216;hookName&#8217;, es el nombre del filtro al que queremos engancharnos. Este es el equivalente al primer par\u00e1metro cuando se usa PHP <code>add_filter()<\/code>. El segundo par\u00e1metro, &#8216;espacio de nombres&#8217;, es un nombre de espacio de nombres personalizado para su c\u00f3digo. Esto es solo para evitar la colisi\u00f3n de nombres. Puede configurar pr\u00e1cticamente cualquier cosa que desee aqu\u00ed, simplemente no use el espacio de nombres de WordPress (&#8216;wp&#8217;). Utilice una forma abreviada de su nombre o nombre del proyecto. El tercer par\u00e1metro, &#8216;functionName&#8217;, es la funci\u00f3n enganchada, que es lo mismo que el <code>add_filter()<\/code>segundo argumento de PHP. Y finalmente el cuarto par\u00e1metro, &#8216;prioridad&#8217;, es opcional. Nuevamente, esto es lo mismo que el <code>add_filter()<\/code>tercer argumento de PHP.<\/p>\n<p>El proceso de filtros en Javascript es el mismo que en PHP. Definimos una funci\u00f3n que necesita devolver la variable filtrada. A veces, la variable es una cadena, un objeto o un componente. Dentro de la funci\u00f3n modificamos la variable como mejor nos parezca.<\/p>\n<p>En nuestro caso, queremos agregar un nuevo atributo al <code>attribute<\/code>objeto del bloque. Llamaremos al nuevo atributo <code>hideOnMobile<\/code>y estableceremos su tipo en <code>boolean<\/code>. Esto se hace as\u00ed:<\/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>En la l\u00ednea <code>#3<\/code>, nos aseguramos de apuntar solo a bloques de tipo &#8216; <code>core\/cover<\/code>&#8216;. El segundo argumento para <code>blocks.registerBlockType<\/code>filtrar es convenientemente el nombre del bloque. Luego agregamos un nuevo elemento de objeto al <code>settings.attributes<\/code>objeto. Finalmente nos aseguramos de devolver la variable filtrada, <code>settings<\/code>.<\/p>\n<p>En este punto visualmente nada ha cambiado en Gutenberg. Pero todos los bloques Cover ahora tienen un atributo adicional que podemos usar para almacenar nuestra configuraci\u00f3n.<\/p>\n<h3>Agregar configuraci\u00f3n a Inspector (panel Avanzado)<\/h3>\n<p>El segundo filtro se llama y filtra el componente <code>editor.BlockEdit<\/code>del bloque. <code>edit<\/code>Este filtro recibe el componente del bloque original <code>BlockEdit<\/code>y devuelve un nuevo componente envuelto. Necesitamos usar <code>wp.compose.createHigherOrderComponent<\/code>para devolver el componente envuelto.<\/p>\n<p>Dentro de nuestro componente, nos aseguramos de representar el componente envuelto <code>BlockEdit<\/code>, independientemente. Pero si el bloque es de tipo Cover, tambi\u00e9n enganchamos el componente <code>InspectorAdvancedControls<\/code>(que es el panel &quot;Avanzado&quot; en Inspector) y agregamos un archivo <code>ToggleControl<\/code>. Escribimos <code>ToggleControl<\/code>para mostrar el valor y actualizar el atributo personalizado que agregamos 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>No olvides devolver siempre el original <code>BlockEdit<\/code>, cosa que hacemos en line <code>#9<\/code>. En la l\u00ednea #10 verificamos si el tipo de bloque es Cover y renderizamos el <code>InspectorAdvancedControls<\/code>componente. Dentro de aqu\u00ed agregamos un <code>ToggleControl<\/code>, que es un control de entrada que se muestra como un interruptor entre verdadero o falso. Establecemos una etiqueta y conectamos su valor al <code>hideOnMobile<\/code>atributo. Si ha agregado configuraciones a Inspector anteriormente, esto deber\u00eda ser bastante sencillo para usted.<\/p>\n<p>Con el c\u00f3digo anterior, ahora deber\u00edamos obtener esto dentro del panel &quot;Avanzado&quot; en los bloques 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=\"Agregue configuraciones personalizadas a los bloques existentes de WordPress Gutenberg\"><\/a><\/p>\n<p>La entrada ahora actualizar\u00e1 nuestro atributo personalizado <code>hideOnMobile<\/code>. El \u00faltimo paso es hacer algo dependiendo del valor de este atributo. A partir de ahora, el atributo se guarda, pero en realidad no afecta nada.<\/p>\n<h3>Agregar una clase personalizada<\/h3>\n<p>El paso final es agregar una clase personalizada a la clase del bloque. Esto lo hacemos con el filtro <code>blocks.getSaveContent.extraProps<\/code>. Este filtro afecta a los accesorios del <code>save<\/code>componente del bloque. Uno de ellos es el prop <code>className<\/code>, que siempre se aplicar\u00e1 al frontend. Simplemente agregamos nuestra clase personalizada despu\u00e9s si el atributo era <code>true<\/code>, y luego lo devolvemos. He decidido agregar una clase &#8216; <code>hide-on-mobile<\/code>&#8216;, pero puedes llamarla como quieras.<\/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 es bastante autoexplicativo. En l\u00ednea <code>#4<\/code>comprobamos si el atributo <code>hideOnMobile<\/code>existe y es <code>true<\/code>. Si es as\u00ed, agregamos una clase personalizada a la <code>className<\/code>cadena.<\/p>\n<p>Con los tres filtros anteriores, ahora deber\u00edamos aplicar una clase personalizada &#8216;ocultar en el m\u00f3vil&#8217; a nuestro bloque de portada siempre que la configuraci\u00f3n est\u00e9 activada.<\/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=\"Agregue configuraciones personalizadas a los bloques existentes de WordPress Gutenberg\"><\/a><\/p>\n<p>Todo lo que queda es agregar algo de CSS a la hoja de estilo de la interfaz de usuario de su tema. Algo como esto;<\/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>Ejemplo 2: agregue el panel Inspector con una configuraci\u00f3n de color de fondo personalizada para el bloque espaciador<\/h2>\n<p>Para el segundo caso de uso, queremos agregar configuraciones de color personalizadas al bloque espaciador. Por defecto, el bloque espaciador no tiene otras configuraciones adem\u00e1s de su altura. Supongamos que queremos agregar un color de fondo que coloree la altura completa del bloque espaciador. Eso permite al usuario agregar &quot;rayas&quot; vac\u00edas y de colores dentro de su contenido. En este caso, queremos agregar la configuraci\u00f3n de color en su propio panel separado en Inspector, seg\u00fan el comportamiento habitual esperado para la configuraci\u00f3n de color.<\/p>\n<p>Nota: el manejo de los colores es un poco m\u00e1s complicado ya que necesitamos usar un (otro) componente de orden superior <code>withColors<\/code>. Debido a que ya necesitamos implementar un componente de orden superior en el <code>editor.BlockEdit<\/code>que necesitamos <code>compose<\/code>m\u00faltiples componentes. Adem\u00e1s, necesitamos agregar dos atributos para cada configuraci\u00f3n de color. Uno contendr\u00e1 el slug de la paleta de colores y el otro contendr\u00e1 el c\u00f3digo de color hexadecimal, solo si el usuario ha optado por un color personalizado (us\u00f3 el selector de color). Todo esto es un comportamiento com\u00fan cuando se trabaja con <code>withColors<\/code>. Tengo una &lt;a href=&quot;https:\/\/wordpress.mediadoma.com\/es\/como-agregar-configuraciones-de-color-a-su-bloque-de-gutenberg-personalizado\/&quot; title=&quot;publicaci\u00f3n que explica c\u00f3mo agregar configuraciones de color y <code>withColors<\/code>en detalle\u00bb &gt;publicaci\u00f3n que explica c\u00f3mo agregar configuraciones de color y <code>withColors<\/code>en detalle<\/a> si te confundes.<\/p>\n<p>En segundo lugar, en este caso nos encontraremos con el problema explicado anteriormente; donde no podemos agregar el estilo en l\u00ednea apropiado al editor. La soluci\u00f3n por la que he optado en este caso es envolver el bloque espaciador dentro de un <code>div<\/code>en el editor y aplicar las clases adecuadas y el estilo en l\u00ednea al envoltorio <code>div<\/code>. Esto hace que el color seleccionado sea visible en el editor cuando el bloque no est\u00e1 seleccionado. Sin embargo, al seleccionar el bloque, WordPress agrega su propio fondo gris claro personalizado al bloque, cubriendo nuestro color de fondo personalizado. Un CSS al editor arreglar\u00e1 esto. Explicar\u00e9 m\u00e1s al final.<\/p>\n<p>Los pasos son los mismos que en el ejemplo anterior. Encolamos nuestro script al editor en PHP primero. Luego en Javascript filtramos el <code>attributes<\/code>objeto, el <code>edit<\/code>componente de Spacer y finalmente el <code>save<\/code>componente de Spacer.<\/p>\n<h3>Agregando nuestro script al editor<\/h3>\n<p>Enganchamos una funci\u00f3n a la acci\u00f3n <code>[enqueue_block_editor_assets](https:\/\/developer.wordpress.org\/reference\/hooks\/enqueue_block_editor_assets\/)<\/code>. Dentro de nuestra funci\u00f3n, ponemos en cola un script, tal como lo har\u00edamos normalmente en <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>Recuerde ajustar la ruta a su script. Me gusta agregar &#8216; <code>wp-edit-post<\/code>&#8216; como una dependencia al script para asegurar que se cargue lo suficientemente tarde.<\/p>\n<p>Eso es todo el PHP que necesitamos hacer. El resto est\u00e1 escrito en nuestro archivo Javascript.<\/p>\n<h3>Agregar atributos personalizados<\/h3>\n<p>Como en el ejemplo anterior, agregamos un filtro <code>blocks.registerBlockType<\/code>para agregar elementos de objetos adicionales al objeto del bloque <code>attributes<\/code>.<\/p>\n<p>Cuando trabajamos con <code>withColors<\/code>necesitamos agregar dos atributos para cada color. El nombre de nuestro atributo de color de fondo es <code>backgroundColor<\/code>, lo que significa que el segundo atributo debe tener el nombre <code>customBackgroundColor<\/code>. Todo esto se explica en <a href=\"https:\/\/wordpress.mediadoma.com\/es\/como-agregar-configuraciones-de-color-a-su-bloque-de-gutenberg-personalizado\/\" title=\"mi publicaci\u00f3n sobre el manejo de la configuraci\u00f3n de color en Gutenberg\">mi publicaci\u00f3n sobre el manejo de la configuraci\u00f3n de color en Gutenberg<\/a>. Ambos deben ser de tipo string, y solo aplicados a bloques de 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>Agregue el panel ColorSettings al Inspector<\/h3>\n<p>El segundo paso es agregar un panel de configuraci\u00f3n de color al Inspector para el bloque espaciador 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>Necesitamos usar <code>compose<\/code>para combinar el componente de orden superior devuelto por este filtro y <code>withColors<\/code>. En otras palabras, simplemente envolvemos el componente devuelto en <code>withColors<\/code>. Como par\u00e1metro <code>withColors<\/code>proporcionamos nuestro atributo <code>backgroundColor<\/code>.<\/p>\n<p>Dentro del componente envuelto nos aseguramos de regresar siempre <code>BlockEdit<\/code>(l\u00ednea <code>#9<\/code>y <code>#39<\/code>para bloques espaciadores). Para el bloque de tipo espaciador, tambi\u00e9n enganchamos <code>InspectorControls<\/code>para agregar un <code>PanelColorSettings<\/code>para nuestra elecci\u00f3n de color. Este es el procedimiento est\u00e1ndar para agregar configuraciones de color.<\/p>\n<p>En l\u00ednea <code>#17 - 34<\/code>generamos manualmente la clase necesaria y\/o el estilo en l\u00ednea. Luego, en la l\u00ednea <code>#38<\/code>, agregamos un div envolvente <code>BlockEdit<\/code>con esas clases y estilos en l\u00ednea.<\/p>\n<p>El resultado es un nuevo panel de configuraci\u00f3n de color en Inspector para bloques espaciadores, 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=\"Agregue configuraciones personalizadas a los bloques existentes de WordPress Gutenberg\"><\/a><\/p>\n<p>La elecci\u00f3n de un color de paleta o un color personalizado se ver\u00e1 afectado en el div de envoltura dentro del editor. \u00a1Pero solo puede verlo cuando anula la selecci\u00f3n del bloque espaciador!<\/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=\"Agregue configuraciones personalizadas a los bloques existentes de WordPress Gutenberg\"><\/a><\/p>\n<p>Esto sucede porque WordPress aplica su propio estilo al seleccionar un bloque espaciador. Lo arreglaremos al final, primero solo necesitamos aplicar la misma clase y\/o estilo en l\u00ednea tambi\u00e9n en la interfaz.<\/p>\n<h3>Agregue una clase personalizada y un estilo en l\u00ednea para guardar<\/h3>\n<p>Finalmente, debemos filtrar <code>blocks.getSaveContent.extraProps<\/code>y aplicar la clase necesaria y\/o el estilo en l\u00ednea para la interfaz. Nuevamente, esto es muy similar a lo que hicimos en el ejemplo 1 anterior. Si se eligi\u00f3 un color de paleta, debemos agregar un nombre de clase que siga los est\u00e1ndares de WordPress para la configuraci\u00f3n de color (&quot; <code>has-&lt;PALETTESLUG&gt;-background-color<\/code>&quot;). Si se eligi\u00f3 un color personalizado, debemos agregar un estilo en l\u00ednea con el color hexadecimal.<\/p>\n<p>Nota: si necesita manejar mucho los nombres de clase, le recomiendo importar la <code>classnames<\/code>biblioteca. Esto se utiliza mucho en Gutenberg porque simplifica mucho la configuraci\u00f3n de los nombres de clase adecuados. El siguiente c\u00f3digo asume que no lo ha hecho y compone el nombre de la clase 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>\u00a1Con el c\u00f3digo anterior, la interfaz ahora representar\u00e1 perfectamente los bloques espaciadores con nuestra elecci\u00f3n de color personalizada!<\/p>\n<p>La soluci\u00f3n final (opcional) es agregar algo de CSS al editor. Deber\u00e1 agregar CSS en l\u00ednea o una hoja de estilo del editor. Por ejemplo, podr\u00eda poner en cola una hoja de estilo en el mismo gancho de PHP que usamos para poner en cola nuestro archivo Javascript. No entrar\u00e9 en detalles sobre c\u00f3mo hacer esto; pero el CSS que necesitar\u00e1 es algo como el siguiente. Todo lo que hace es establecer el espaciador <code>background-color<\/code>en el color heredado (se heredar\u00e1 de nuestro div de envoltura) cuando se selecciona el bloque:<\/p>\n<pre><code>.block-library-spacer__resize-container.is-selected { \n    background-color: inherit; \n}<\/code><\/pre>\n<p>PD: Tenga en cuenta que esto est\u00e1 sujeto a cambios en el futuro. Gutenberg todav\u00eda est\u00e1 en gran evoluci\u00f3n.<\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>En esta publicaci\u00f3n, hemos aprendido dos m\u00e9todos para implementar configuraciones personalizadas en los bloques existentes de WordPress Gutenberg. Es totalmente posible para configuraciones simples que quiz\u00e1s solo requieran una clase o un estilo en l\u00ednea. \u00a1Hemos analizado las advertencias, que espero que se solucionen en versiones posteriores de Gutenberg!<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>En esta publicaci\u00f3n, entraremos en detalles sobre c\u00f3mo agregar su configuraci\u00f3n personalizada a los bloques Gutenberg de WordPress existentes con dos c\u00f3digos de ejemplo de casos de uso de la 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":[892,892,716,716,831,935,935,1110,831,840,840,861,861],"tags":[1172],"class_list":["post-233678","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-desarrollador","category-guia-para-principiantes","category-gutenberg-2","category-n-a","category-tutoriales","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/233678","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=233678"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/233678\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/152422"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=233678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=233678"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=233678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}