Helpers
Los helpers son las funciones de JavaScript a las que llaman tus plantillas para hacer cosas: enviar una consulta, abrir una vista previa, reaccionar a una respuesta, enviar un formulario, mostrar u ocultar la ventana. Los referencias desde los eventos HTML como skdwn.instance.helpers.<name>(...). Son la contrapartida de comportamiento de las plantillas Liquid: la plantilla dibuja el botón y el helper es lo que se ejecuta al hacer clic. En el explorador de ficheros del Advanced editor están en Template Helpers (settings.extensions.helpers).
Cómo se ejecuta un helper
Cada helper es una función normal asociada a skdwn.instance.helpers. Dentro, llega al asistente en ejecución a través del objeto skdwn.instance y controla la interfaz actualizando el estado o creando resultados. Los métodos en los que más se apoya un helper:
| Método de la instancia | Qué hace |
|---|---|
updateState(partial) | Combina campos en el estado en vivo y vuelve a renderizar (p. ej. { isLoading: true }). |
createResult(result) | Añade un nuevo intercambio ({ type, payload }) a la conversación. |
retrieveResult(id) / updateResult(result) | Lee un resultado por id y lo vuelve a escribir tras modificar su payload. |
clearResults() | Borra la conversación guardada. |
sendTrace(event, props?) | Registra un evento de analítica (alimenta el panel). |
getPreviousConversation() | Los turnos anteriores, usados para enviar el contexto de la conversación. |
executeStreamPrompt(request) | Ejecuta una consulta en streaming contra el backend. |
sendFormRequest(formType, values) / executeProxyRequest(id, body, cb, params) | Envía un formulario de leads / llama a un endpoint proxy (params rellena los marcadores {{params.x}} de la URL o las cabeceras del servicio). |
stopQuery() | Cancela la consulta en streaming en curso. |
Valores de type de resultado que crearás: WELCOME (saludo + sugerencias), FORM (un formulario de leads) y ERROR (una burbuja de error). Leer y escribir el payload de un resultado es la forma en que los helpers guardan estado por respuesta, como una reacción.
Helpers integrados
A continuación tienes cada helper integrado, qué espera y cómo se comporta. Las firmas coinciden con el código fuente; cuando un helper no recibe argumentos, los paréntesis están vacíos.
Ciclo de vida de la consulta
sendQuery(): asíncrono, sin argumentos. Lee el texto actual de #skdwn-search-input. Si está vacío, no hace nada. Si no, cambia el estado a { query, isLoading: true }, se desplaza hasta el final y envía la petición en streaming al backend. La petición que construye incluye:
userPrompt: el texto del cuadro.previousConversation: los turnos anteriores, solo cuando
settings.usePreviousConversation está activado; si no, una cadena vacía.
additionalContext: lo que la página anfitriona haya pasado enstartOptions.additionalContext.
Si tiene éxito, vacía el cuadro (query: ''), restablece la altura del textarea y cierra cualquier pestaña abierta. Si falla, conserva el texto para que el usuario pueda reintentarlo, desactiva isLoading, registra el error y añade un resultado ERROR.
onChangeQuery(event): conéctalo a oninput en el textarea. Escribe el valor del campo en state.query y hace crecer automáticamente el textarea. Donde el navegador admite el CSS field-sizing: content, el crecimiento es nativo; en otros (p. ej. Firefox) recurre a ajustar la altura con JS.
onPressEnter(event): conéctalo a onkeydown en el textarea. Enter envía (llama a sendQuery() e impide el salto de línea por defecto); Shift+Enter inserta un salto de línea para que el cuadro crezca con una pregunta de varias líneas.
stopQuery(): sin argumentos. Cancela una consulta que se está transmitiendo.
hintBoxClick(element): pasa el elemento pulsado como this. Lee la pregunta sugerida de su atributo data-hint, la pone en el cuadro de búsqueda, llama a sendQuery() y registra un evento HintBoxClick.
Conversación y reacciones
showHints(): sin argumentos. Vuelve a mostrar el saludo y las sugerencias creando un nuevo resultado WELCOME y registra ShowHints.
clearHistory(): sin argumentos. Borra los resultados guardados, vacía state.results, crea un nuevo WELCOME y registra ClearHistory.
react(resultId, reactionType, element): registra un pulgar arriba/abajo en una respuesta. resultId es el id del resultado de la respuesta; reactionType es 'like' o 'dislike' (element se acepta por simetría pero no se usa). La lógica de alternancia: volver a pulsar la misma reacción no hace nada; pulsar la contraria la restablece a neutral. Registra un evento Reaction y escribe payload.reaction de vuelta en el resultado.
Modal de vista previa
openPreview(event, element): abre la vista previa de la imagen o el documento. Lee data-previewsrc (el segmento de ruta de la fuente) y data-title del elemento, construye ${serviceURL}/api/public/assistants/${previewsrc} (añadiendo el accesstoken como parámetro de consulta cuando existe) y lo muestra en el modal mediante { modalOpen: true, modalContent, modalTitle }.
Los atributos data-* se pasan a minúsculas
El DOM pasa a minúsculas las claves del dataset, así que data-previewSrc en tu Liquid se lee como element.dataset.previewsrc. Respeta las mayúsculas y minúsculas que espera el helper.
closePreview(): sin argumentos. Limpia el modal ({ modalOpen: false, modalContent: '' }).
Ventana y diseño
toggleMaximized(): sin argumentos. Alterna #skdwn-main-container entre sus tamaños minimized y maximized y lo refleja en state.skdwnWindowState.
toggleShowFloatingWindow(show): show es un booleano. true oculta el botón flotante, muestra la ventana (restaurando su último tamaño, o forzando minimized cuando el botón de acción flotante está desactivado), pone el foco en el cuadro de búsqueda y reproduce la animación de apertura. false oculta la ventana, la marca como closed y vuelve a mostrar el botón.
handleScroll(): sin argumentos. Desplaza el contenedor de la conversación (#skdwn-floating-window-main) hasta el final; los helpers lo llaman tras añadir contenido para que la respuesta más reciente quede visible.
Formularios y proxies
showForm(formType): formType es el id del formulario. Establece activeForm: true y crea un resultado FORM (con un UUID generado) que renderiza ese formulario.
sendForm(formType, event): asíncrono, conéctalo al onsubmit de un formulario. Impide el envío por defecto, serializa los campos del formulario en un payload, marca el resultado como en envío y llama a sendFormRequest(formType, payload). Si tiene éxito, el resultado se marca como submitted; si falla, añade un resultado ERROR; en ambos casos desactiva activeForm.
sendProxyForm(proxyId, event, callback): asíncrono, para formularios que llaman a un endpoint proxy. Impide el envío por defecto, serializa los campos, activa isLoading y llama a executeProxyRequest(proxyId, payload, callback). Si el proxy devuelve una respuesta, se añade como resultado; los errores se convierten en un resultado ERROR.
Helpers de renderizado
materialIcon(parameters): devuelve HTML seguro para un icono de Material. A diferencia de los helpers de eventos, este genera marcado, así que lo usas como filtro de Liquid (consulta Los helpers también son filtros). parameters admite:
iconName: el nombre de la ligadura (p. ej.search,close).size: el font-size de CSS (por defecto16px).iconStyle: una variante del icono comooutlinedoround(se corresponde conmaterial-icons-<style>).
{% assign icon = "" | buildIconParams %} {# or pass an object you already have in scope #}
{{ icon | materialIcon }}
El valor que le pasas se convierte en el objeto parameters, así que en la práctica lo llamas con el objeto que tengas disponible. Su salida ya es HTML seguro: no añadas | safe.
greet(parameters): un pequeño helper de ejemplo que devuelve JSON.stringify(parameters). Está ahí como punto de partida cuando añades los tuyos: ábrelo, usa Test code para pasarle JSON de ejemplo y mira el resultado en el panel de depuración.
Llamar a un helper
Asocia los helpers a eventos del DOM directamente desde el Liquid:
<textarea id="skdwn-search-input"
oninput="skdwn.instance.helpers.onChangeQuery(event)"
onkeydown="skdwn.instance.helpers.onPressEnter(event)"></textarea>
<button onclick="skdwn.instance.helpers.sendQuery()">
{{ 'ask' | t: 'Ask' }}
</button>
Pasa datos a un helper mediante atributos data-* y léelos del elemento con this:
<a href="#" onclick="skdwn.instance.helpers.openPreview(event, this)"
data-title="{{ reference.title }}"
data-previewSrc="{{ state.instance.config.key }}/tools/preview/{{ reference.id }}/{{ refPage }}">
Preview
</a>
Para una tarjeta de sugerencia, guarda la pregunta en data-hint y deja que hintBoxClick la recoja:
<button data-hint="{{ hint.text | sanitize }}"
onclick="skdwn.instance.helpers.hintBoxClick(this)">
{{ hint.text }}
</button>
Los helpers también son filtros
Cada helper, integrado y personalizado, se registra dos veces:
- Como método en
skdwn.instance.helpers.<name>, paraonclick/oninput/onsubmit. - Como filtro de Liquid con el mismo nombre, para usarlo dentro de
{{ … }}.
Cuál usas depende de lo que haga el helper. Los helpers de eventos (sendQuery, react, openPreview, …) van en eventos del DOM. Los helpers que devuelven un valor (como materialIcon, que devuelve HTML) se usan como filtros, donde el valor que se le pasa se convierte en el primer argumento del helper:
{{ someValue | myFormatter }} {# equivalent to myFormatter(someValue) #}
Por eso un helper personalizado que añadas para dar formato se puede usar directamente dentro de {{ }} sin cableado adicional.
Tus propios helpers
El Advanced editor te permite añadir helpers personalizados: JavaScript guardado en settings.extensions.helpers. Cada entrada puede ser una sola función o un objeto de funciones; Seekdown los evalúa al arrancar y los combina en skdwn.instance.helpers, así que los llamas exactamente igual que a los integrados. Si un helper no se puede evaluar, se omite (con un aviso en la consola) en lugar de romper el widget.
// A helper named "trackClick"
(ref) => { window.analytics?.track('reference_click', { id: ref }); }
<a onclick="skdwn.instance.helpers.trackClick('{{ reference.id }}')">{{ reference.title }}</a>
Dentro de un helper personalizado tienes la misma API de instancia que usan los integrados. Para cambiar lo que se ve en pantalla, llama a skdwn.instance.updateState({ ... }); para añadir un mensaje, llama a skdwn.instance.createResult({ type: 'ERROR', payload: { reply: 'Something went wrong' } }); para registrar un evento de analítica, llama a skdwn.instance.sendTrace('MyEvent', { ... }).
Prueba antes de guardar
Usa Test code en la barra de herramientas del editor para ejecutar un helper con parámetros JSON de ejemplo e inspeccionar su valor devuelto en el panel de depuración: la forma más rápida de comprobar que un helper se comporta bien antes de conectarlo a una plantilla.