Created
May 5, 2025 01:42
-
-
Save celsowm/c31056606d8e4df4c8d280d65a657876 to your computer and use it in GitHub Desktop.
ballon prompt plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Plugin, ButtonView, ContextualBalloon, clickOutsideHandler, View } from 'ckeditor5'; | |
export class HelloWorldView extends View { | |
constructor( locale ) { | |
super( locale ); | |
// Cria o template com textarea e botão | |
this.setTemplate( { | |
tag: 'div', | |
attributes: { | |
class: [ 'ck', 'ck-hello-world-panel' ], | |
tabindex: '-1' | |
}, | |
children: [ | |
{ | |
tag: 'textarea', | |
attributes: { | |
class: [ 'ck', 'ck-hello-world-textarea' ], | |
placeholder: 'Digite seu prompt aqui…', | |
rows: '4' | |
} | |
}, | |
{ | |
tag: 'button', | |
attributes: { | |
class: [ 'ck', 'ck-hello-world-send-button' ], | |
type: 'button' | |
}, | |
children: [ | |
{ | |
tag: 'span', | |
attributes: { | |
class: [ 'ck', 'ck-icon' ] | |
}, | |
// você pode substituir por um ícone SVG inline | |
children: [ { text: '🡆' } ] | |
}, | |
{ | |
text: 'Enviar' | |
} | |
] | |
} | |
] | |
} ); | |
} | |
/** | |
* Obtém referência ao textarea DOM. | |
*/ | |
get textareaElement() { | |
return this.element.querySelector( '.ck-hello-world-textarea' ); | |
} | |
/** | |
* Obtém referência ao botão de envio. | |
*/ | |
get sendButtonElement() { | |
return this.element.querySelector( '.ck-hello-world-send-button' ); | |
} | |
/** | |
* Define um listener para o clique no botão. | |
* @param {Function} callback Função a ser chamada com o conteúdo da textarea. | |
*/ | |
onSend( callback ) { | |
this.listenTo( this, 'render', () => { | |
this.sendButtonElement.addEventListener( 'click', () => { | |
callback( this.textareaElement.value ); | |
} ); | |
} ); | |
} | |
} | |
export class HelloWorldUI extends Plugin { | |
static get requires() { | |
return [ ContextualBalloon ]; | |
} | |
static get pluginName() { | |
return 'HelloWorldUI'; | |
} | |
init() { | |
const editor = this.editor; | |
const t = editor.t; | |
// Cria a view do balão e estado interno | |
this._helloWorldView = this._createHelloWorldView(); | |
this._button = null; | |
this._isPanelVisible = false; | |
// Registra o botão na toolbar | |
editor.ui.componentFactory.add( 'robotPluginButton', locale => { | |
const button = new ButtonView( locale ); | |
button.set({ | |
label: '🤖', | |
tooltip: false, | |
icon: '<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.5 4a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zM10.5 16a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9z"/><path d="M10.5 7a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/><path d="M10.5 9.5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 1 .5-.5z"/></svg>', | |
isOn: false | |
}); | |
this._button = button; | |
this.listenTo( button, 'execute', () => { | |
if ( this._isPanelVisible ) { | |
this._hidePanel(); | |
} else { | |
this._showPanel( button ); | |
} | |
}); | |
return button; | |
}); | |
} | |
_createHelloWorldView() { | |
return new HelloWorldView( this.editor.locale ); | |
} | |
_showPanel( buttonView ) { | |
const balloon = this.editor.plugins.get( ContextualBalloon ); | |
// Marca o botão e estado interno | |
buttonView.set({ isOn: true }); | |
this._isPanelVisible = true; | |
// Habilita o handler, incluindo o botão como elemento de contexto | |
this._enableClickOutsideHandler( buttonView.element ); | |
// Adiciona o balão apontando para o botão | |
balloon.add({ | |
view: this._helloWorldView, | |
position: { target: buttonView.element } | |
}); | |
} | |
_hidePanel() { | |
const balloon = this.editor.plugins.get( ContextualBalloon ); | |
const view = this._helloWorldView; | |
this._disableClickOutsideHandler(); | |
if ( balloon.hasView( view ) ) { | |
balloon.remove( view ); | |
} | |
this._isPanelVisible = false; | |
if ( this._button ) { | |
this._button.set({ isOn: false }); | |
} | |
} | |
_enableClickOutsideHandler( buttonElement ) { | |
const balloon = this.editor.plugins.get( ContextualBalloon ); | |
const view = this._helloWorldView; | |
this._clickOutsideHandler = clickOutsideHandler({ | |
emitter: view, | |
activator: () => balloon.hasView( view ), | |
// Inclui tanto o balão quanto o botão como "dentro" | |
contextElements: [ | |
balloon.view.element, | |
buttonElement | |
], | |
callback: () => this._hidePanel() | |
}); | |
} | |
_disableClickOutsideHandler() { | |
if ( this._clickOutsideHandler ) { | |
this._clickOutsideHandler.cancel(); | |
} | |
} | |
} | |
export default class RobotPlugin extends Plugin { | |
static get requires() { | |
return [ HelloWorldUI ]; | |
} | |
static get pluginName() { | |
return 'HelloWorld'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment