Skip to content

Instantly share code, notes, and snippets.

@celsowm
Created May 5, 2025 01:42
Show Gist options
  • Save celsowm/c31056606d8e4df4c8d280d65a657876 to your computer and use it in GitHub Desktop.
Save celsowm/c31056606d8e4df4c8d280d65a657876 to your computer and use it in GitHub Desktop.
ballon prompt plugin
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