Una de las características de Pulse Editor es que podemos configurar cuáles botones de todos los que nos provee el editor queremos usar. Pero no solo podemos usar esos botones, también podemos crear botones propios.
Si ya vieron como implementar Pulse Editor pueden luego crear botones propios. Vamos a ver cómo hacer esto.
El editor nos provee de un editor base que podemos usar. Este es un simple wrapper de la etiqueta <button />
para colocar siempre ciertos atributos. Pueden acceder a este componente simplemente con un import
.
import { Base } from 'pulse-editor/buttons`
Luego ya pueden hacer render y pasarle lo que quieran, al final del día es un botón, lo únicos props
que deben pasar sí o sí son:
children
=> los componentes hijos, pueden ser lo que quieran.name
=> el nombre del botón, en el componente <Bold />
este es bold
, así que pueden darse una idea.onClick
=> la función que se va a ejecutar cuando el usuario haga click sobre el botón.El botón además define un className
por defecto llamado PulseEditor-button
(que pueden cambiar si pasan su propio className
), define disabled
como false
(también sobre escribible) y fuerza que el type
sea button
. Porque por defecto las etiquetas <button />
son de tipo submit
. Así evitamos que cualquier botón del editor envíe un posible formulario que envuelva al editor.
Vamos a crear un botón para la aplicación de escritorio Pulse. Este botón va a encargarse de crear un nuevo archivo en el editor. Como Pulse usa Next.js no necesitamos importar React
, pero como vamos a crear un componente de clase entonces sí vamos a importar Component
.
import { Component } from'react';
Luego importamos el botón base como vimos antes y vamos a iniciar a crear nuestro componente.
import { Component } from'react'import { Base } from'pulse-editor/buttons'exportdefaultclassNewButtonextendsComponent{
render = () => (
<BaseonClick={this.handleClick}name='new'><spantitle='New file [CMD+N]'>
New
</span></Base>
)
}
Con eso nuestro botón ya hace render de un botón normal de nuestro editor y definimos dos cosas extras sobre este: la primera es que tenemos que crear un handleClick
y la segunda es que vamos a usar el atajo de teclado cmd+n
en Mac o ctrl+n
en Windows y Linux.
Vamos primero a definir nuestro atajo de teclado. Para eso necesitamos acceder a dos funciones desde el contexto de React a los cuales vamos a tener acceso siempre que nuestro botón se renderice dentro del componente <Editor />
.
import { Component } from'react'import { Base } from'pulse-editor/buttons'import { func } from'prop-types'// importamos el prop-type func para definir funcionesexportdefaultclassNewButtonextendsComponent{
static contextTypes = {
setShortcut: func.isRequired, // esta función nos permite definir un shortcut
removeShortcut: func.isRequired, // esta función nos permite quitar un shortcut
}
render = () => (
<BaseonClick={this.handleClick}name='new'><spantitle='New file [CMD+N]'>
New
</span></Base>
)
}
Con eso tenemos acceso a la función. Ahora vamos a usar estas funciones, la primera se usa en componentDidMount
para agregar nuestro atajo de teclado y la segunda se usa en componentWillUnmount
cuando el componente se vaya a desmontar.
import { Component } from'react'import { Base } from'pulse-editor/buttons'import { func } from'prop-types'import isMac from'pulse-editor/built/utils/is-mac'// importamos un util interno de pulse-editor para saber si estamos en MacexportdefaultclassNewButtonextendsComponent{
static contextTypes = {
setShortcut: func.isRequired,
removeShortcut: func.isRequired,
}
componentDidMount() {
this.context.setShortcut({
ctrlKey: !isMac(), // si no estamos en Mac usamos la tecla control
metaKey: isMac(), // si estamos en Mac usamos la tecla meta (command)
altKey: false, // no vamos a usar la tecla alt
shiftKey: false, // no vamos a usar la tecla shift
keyName: 'n', // vamos a usar la tecla N (cmd+n o ctrl+n)
updater: selected => selected, // nuestra función updater (más abajo vemos que es)
handler: event => event.selection, // nuestro función handler (más abajo vemos que es)
})
}
componentWillUnmount() {
// eliminamos el atajo de teclado que usa la tecla N al desmontar el componentethis.context.removeShortcut({ keyName: 'n' })
}
render = () => (
<BaseonClick={this.handleClick}name='new'><spantitle='New file [CMD+N]'>
New
</span></Base>
)
}
Así configuramos atajos de teclados. Como vemos al momento de definir uno indicamos que atajo se va a usar, si vamos a usar las teclas ctrl
, meta
, alt
y shift
y otra tecla. Le tecla meta
puede significar cmd
(command) en Mac o win
(windows) en teclados no-mac en Windows y Linux.
Luego definimos dos funciones, updater
y handler
. Esta es probablemente la parte más complicada. La función updater recibe los siguientes datos:
selected
=> el texto seleccionado por el usuario al momento de ejecutarse updater
value
=> el valor completo actual del editorselection
=> un objeto que nos indica la posición de selected
dentro de value
Esta función updater
devuelve un nuevo string que sobreescribe selected
dentro de value
.
Por ejemplo si tenemos el texto
hola
comovalue
yol
comoselected
entonces el objetoselection
va a venir con{ start: 1, end: 3 }
. Siupdater
devuelve**ol**
entonces el valor completo nuevo va a serh**ol**a
.
La función handler
se ejecuta luego de aplicar updater
y actualizar el contenido del editor. Esto nos permite modificar la posición del cursor del usuario (para cambiar el texto seleccionado) o hacer cualquier cosa, por ejemplo mandar eventos de analytics.
Esta función debe devolver un objeto similar a selection
, con las propiedades start
y end
y recibe un objeto event
con las siguientes propiedades.
value
=> el valor completo actualizadofield
=> el elemento del DOM del textareaupdated
=> el valor generado por la función updater
selected
=> el texto seleccionado originalselection
=> la posición del selected
dentro del valor originalLuego de convertir
ol
a**ol**
podemos decidir entre mantener seleccionadool
o**ol**
, para el primero casohandler
debe devolver{ start: 3, end: 5 }
y para el segundo{ start: 1, end: 7 }
.
Vamos a programar la funcionalidad propia del botón, ya que hasta ahora el botón no hace nada de verdad.
import { Component } from'react'import { Base } from'pulse-editor/buttons'import { ipcRenderer } from'electron'// módulo para de Electron para comunicarse con el proceso principalimport { func } from'prop-types'import isMac from'pulse-editor/built/utils/is-mac'import Icon from'react-icons/lib/fa/file-o'// componente de ícono que renderiza un SVG directoexportdefaultclassNewButtonextendsComponent{
static contextTypes = {
setShortcut: func.isRequired,
setFileName: func.isRequired, // función propia de la aplicación de escritorio Pulse para definir el nombre del archivo abierto actualmente
removeShortcut: func.isRequired,
writeValue: func.isRequired // función de Pulse Editor para sobreescribir el valor actual del editor
}
componentDidMount() {
// escuchamos el evento `new-file` que llega desde el proceso main
ipcRenderer.on('new-file', this.createFile)
this.context.setShortcut({
ctrlKey: !isMac(),
metaKey: isMac(),
altKey: false,
shiftKey: false,
keyName: 'n',
updater: selected => selected,
handler: event => event.selection,
})
}
componentWillUnmount() {
// dejamos de escuchar el evento `new-file` que llega desde el proceso main
ipcRenderer.removeListener('new-file', this.createFile)
this.context.removeShortcut({ keyName: 'n' })
}
createFile = () => {
// cuando creamos un nuevo archivo// limpiamos el nombre del archivo actual de la aplicación de escritoriothis.context.setFileName(undefined)
// cambiamos el valor actual del editor a un string vacíothis.context.writeValue({ target: { value: '' } })
}
handleClick = () => this.createFile() // cuando se haga click ejecutamos la función `createFile`
render = () => (
<BaseonClick={this.handleClick}name='new'><spantitle='New file [CMD+N]'>
New
</span></Base>
)
}
Ese es el botón completo, la funcionalidad principal del editor está definida en createFile
, en la que limpiamos el nombre de archivo y el valor actual del editor. La razón de limpiar el nombre de archivo es porque en nuestra aplicación de escritorio si abrimos un archivo o guardamos uno mantenemos la ruta completa del archivo para poder volver a guardarlo en el mismo lugar. Y vaciamos el valor del editor para limpiarlo.
Luego tenemos una conexión con el proceso main
de Electron para enterarnos cuando este nos pida crear un nuevo archivo.
Con lo que hicimos ya tenemos nuestro botón programado. Ahora para usarlo es tan simple como renderizarlo dentro del componente <Editor />
.
import { Component } from'react'import { Editor, ButtonBar, ButtonGroup, Field, Preview, EmojiBar } from'pulse-editor'import { Bold, Italic, Underline } from'pulse-editor/buttons'import Head from'next/head'// importamos nuestro botónimport New from'../components/buttons/new-button.js'exportdefault () => (
<Editor>
<Head>
<link
rel='stylesheet'
href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css'
/>
<link
rel='stylesheet'
href='https://raw.githubusercontent.com/PlatziDev/pulse-editor/master/examples/full-usage/static/styles.css'
/>
</Head>
<ButtonBar>
<ButtonGroup>
<Bold><i className="fa fa-bold" /></Bold>
<Italic><i className="fa fa-italic" /></Italic>
<Underline><i className="fa fa-underline" /></Underline>
</ButtonGroup>
<ButtonGroup>
<New /> {/* renderizamos nuestro botón */}
</ButtonGroup>
</ButtonBar>
<div className="PulseEditor-content">
<Field>
<Preview />
</div>
<EmojiBar />
</Editor>
)
Como se ve, usar un botón personalizado es tan simple como cualquier otro botón, con eso pueden empezar a crear botones propios para cualquier funcionalidad extra que deseen incluir.
Crear un botón puede parecer complicado pero en general depende de que tantas cosas queremos hacer con nuestro botón, un botón de bold es super simple, un botón como este que se conecta con Electron es claramente mucho más complejo y así y todo no es tanto código al final del día.
I really amazed to read this blog post. It is so unique and informative Black Leather Jackets
Many, many thanks for sharing this post with us, and I really do hope that you will share more of your posts with us in the future, so please do not stop sharing, and I wish you the best of luck with your job… teknopediia
It is great to see that some people still put in an effort into managing their website. I’ll be sure to check back again real soon
Good job. Excellent article, and your website is quite user-friendly. Your website and post are fantastic. I own a fashion blog. This website contains examples of my work.
Is this good ?
<a href=“https://smmxp.com/”>Trusted SMM Panel<a/>
It’s really an amazing blog great to get the relatives information through your site for all the people, I appreciate your efforts. Thank you for sharing your knowledge and experience with me https://letslearnirish.com/
Wow! Such an amazing and helpful post this is. I really really love it. It’s so good and so awesome. I am just amazed. I hope that you continue to do your work like this in the future also. https://sydneyheadshot.net/
The jacket of Roman Reigns Black Tracksuit is made of fleece, which absorbs all of your sweat when working out, and the inside viscose lining makes it more breathable to wear.
Many of his outfits are already popular and well-liked by the public. The Rupert Friend Blue Coat from Anatomy of a Scandal Rupert Friend Coat has gotten the most attention from the crowd. This coat has a comfortable inner viscose lining and is composed of a superior wool blend.
Thanks for sharing this informative guide!
Best dog food for Small Breeds
best outdoor dog house
Best flea collar for dogs
best cages for birds
Best food for birds
Thanks for sharing this great and informative content good work keep it up
Thanks for sharing this great and informative content good work keep it up <a href=“https://www.thewordcount.net/”>Word counter</a>
That’s really informative article and really helps me out,
https://www.headsmm.com/
Your article is great and rewarding. word counter
brawl stars hack download
Gaming is fun and an activity that involves people from every walk of life. It works perfectly well in uniting people, even those living in different parts of the world through online gaming. Although not all games can be played online, you can still enjoy a perfect moment with your friends during your free time.
thanks my issue has been fixed.
thanks
https://ometv.onlhttps://chatroulette.tophttps://omegle.wtfhttps://bazoocam.cam
Do you have thoughts on changing Anchor Replacement to a pulse editor version? I have tried the code with my own installed operating system which is raspberry and it just doesn’t run. How else shall do this?