Opciones de interfaz de usuario
Pivotick proporciona una capa de interfaz de usuario flexible encima de su gráfico, lo que le permite controlar cómo los usuarios interactúan con los nodos, los bordes y el lienzo. Usando las opciones UI, puedes:
- Configure el modo general de la interfaz de usuario (completa, visor, estática, etc.).
- Personalice sidebar y los paneles para mostrar propiedades o información adicional.
- Defina tooltips para nodos y bordes, con renderizadores personalizados opcionales.
- Configure menús contextuales para nodos, bordes y el lienzo.
- Declare las facetas del panel filter o permita que se deriven de sus datos.
- Coloque una legend en el lienzo: una clave para sus colores que también funciona como filtro y que aparece por sí sola cuando sus colores se explican mediante un tipo de nodo declarado.
- Complete cualquiera de esas superficies asincrónicamente, a partir de los datos que recupera a pedido.
- Desactiva cualquier característica que tu integración no sirva para nada.
- Coloque el texto propio de la biblioteca en el idioma de sus usuarios: consulte Traducción de la interfaz de usuario.
Modo de interfaz de usuario
La opción mode controla el comportamiento general y el nivel de interacción de la interfaz de usuario del gráfico.
fullpredeterminado: interfaz de usuario completa con todos los paneles, menús e interacciones habilitados.light: interfaz de usuario mínima con interacciones esenciales habilitadas.viewer: solo permite navegar por el gráfico (desplazar, hacer zoom, arrastrar) sin mostrar ningún panel de interfaz de usuario.static: gráfico estático, sin paneles de interfaz de usuario ni interacciones; el gráfico es de sólo lectura.
Para el uso de estilo de imagen de Pivotick, use lo siguiente:
const container = document.getElementById('graph-container')
const options = {
UI: {
mode: 'viewer'
},
}
const graph = Pivotick(container, options)Otros componentes de la interfaz de usuario se pueden configurar a través de su respectivo espacio de nombres.
const options = {
UI: {
sidebar: {},
mainHeader: {},
propertiesPanel: {},
extraPanels: [],
tooltip: {},
contextMenu: {},
filter: {},
}
}La superficie de control del modo full
En el modo full, el cromo es un diseño basado en modos: un carril de modo ** izquierdo** (Seleccionar / Crear / Ver / Física), un panel de herramientas contextual para los activos modo puntero, dos menús laterales de configuración: Ver (fondo del lienzo y interruptores) y Física (diseño + simulación) — la barra superior (búsqueda, filtro, notas, deshacer/rehacer), la selección barra lateral (propiedades, facetas, vecinos y una fila de acción masiva), y un carril de ventana gráfica del lado derecho (ajuste y centrado, zoom, configuración, pantalla completa) y un minimapa en la esquina inferior derecha libre, que se pliega cuando el lienzo es demasiado pequeño para dejar espacio en la habitación (UI.minimap: false para dejarlo caer). light el modo elimina la barra lateral y el minimapa; viewer mantiene solo el riel de la ventana gráfica; static Es un lienzo desnudo.
Migrando desde la esquina cromada
Se eliminaron las superposiciones flotantes GraphControls y GraphToolbar. Diseño y la física pasó al menú lateral Física (UIManager.physicsFlyout): se enviaron en el Ver menú lateral (UIManager.viewFlyout) en 1.5.0, que ahora contiene el fondo del lienzo y la red cambia. Seleccionar/Crear herramientas en vivo en el panel de herramientas (UIManager.toolPanel) y modo carril (UIManager.modeRail). el La opción UI.selectionMenu desapareció: use contextMenu para acciones por nodo y el fila de acción masiva de la barra lateral para acciones de selección múltiple. UIManager.graphNaviation era renombrado a graphNavigation. La opción UI.modeRail y está deshabilitada Explore / Enrich se eliminaron las ranuras: registre un modo real con addRailMode en su lugar. Ver el CHANGELOG.
Los cuatro modos del riel están integrados, pero no son los únicos que puede contener: un complemento agrega su propio con addRailMode, que es como un modo Explorar o Enriquecer que sabe lo que significan tus datos.
Desactivar funciones
El modo UI decide cuánto cromo obtiene un gráfico. Cada característica dentro de ese cromo También se pueden desactivar uno a la vez, que es la forma en que una integración elimina lo que es backend o sus usuarios no tienen ningún uso.
Una característica apagada toma todo que llega a ella: el botón, el panel, la entrada del menú contextual y el método abreviado de teclado van juntos, por lo que no queda nada detrás para hacer clic o presionar y negarse silenciosamente.
const options = {
UI: {
mode: 'full',
notes: { enabled: false },
history: { enabled: false },
inspector: { enabled: false },
editors: { deletion: { enabled: false } },
},
}los interruptores
| Opción | ¿Qué va con eso? |
|---|---|
UI.topBar.enabled | La franja superior, la altura que reservó, los accesos directos que poseen sus controles (Shift+J, Shift+K, Shift+N, Mod+Z) y cualquier acciones de host. Utilice los interruptores a continuación para dejar caer una pastilla y conservar el resto. |
UI.search.enabled | La píldora de búsqueda, su selector de nodos y Shift+J. |
UI.filter.enabled | La píldora Filter Graph, su panel y Shift+K. graph.queryEngine todavía filtra del código. |
UI.notes.enabled | La píldora y el panel de Notas, Shift+N, la herramienta Agregar nota, Agregar nota del menú del lienzo, N, el menú contextual de notas y noteManager.addNote, que se niega. |
UI.history.enabled | Los botones deshacer/rehacer, su menú desplegable de historial y Mod+Z/Mod+Shift+Z. graph.history continúa grabando. |
UI.inspector.enabled | La entrada Inspeccionar propiedades del menú del nodo y I. |
UI.notifications.enabled | Brindis. graph.notifier.* se convierte en un no operativo que regresa a undefined. |
UI.sidebar.enabled | Toda la columna lateral y el ancho que ocupaba. |
UI.propertiesPanel.enabled | El panel de propiedades de la barra lateral y su separador. |
UI.neighborsPanel.enabled | El panel vecino de la barra lateral y su separador. |
UI.viewFlyout.enabled | El botón Ver carril y su panel. |
UI.physicsFlyout.enabled | El botón del carril Física y su panel. |
UI.tooltip.enabled | Información sobre herramientas al pasar el cursor, incluidas las fijadas. También toma { nodes, edges, groups } o (element, kind) => boolean, consulte Información sobre herramientas. |
UI.contextMenu.enabled | Cada menú contextual. |
UI.navigation.enabled | El carril de la ventana gráfica: ajuste, zoom y pantalla completa. |
UI.legend: false | La leyenda del lienzo, incluida la que derivaría por sí misma. |
UI.minimap: false | El minimapa. |
UI.emptyState: false | La tarjeta muestra un lienzo vacío. |
UI.table: false | El muelle de datos y su Shift+T. |
UI.pivotMode: false | La modalidad ferroviaria Pivot, cualquiera que esté registrado. |
Las funciones de ruta de escritura tienen el mismo interruptor en UI.editors, por lo que una función de solo lectura La integración elimina la posibilidad de acceso en lugar de vetar cada clic: nodeCreator, edgeCreator, nodeEditor, edgeEditor y deletion.
El comportamiento del renderizador se desactiva en render: zoomEnabled (que también toma los botones de zoom del riel, manteniendo el ajuste y el centro), dragEnabled, selectionBox.enabled (el marco y la herramienta Seleccionar ▸ Lazo), enableNodeExpansion (el galón, su Enter y el guión colapsado esquema), enableFocusMode, y interactionEnabled para todo a la vez. simulation.enabled detiene el diseño de correr.
El modo Crear sigue sus herramientas.
El modo Crear carril contiene exactamente cuatro herramientas: Agregar nodo, Agregar borde, Agregar nota y Editar. nodo. Apaga los cuatro y el modo sale del carril, junto con su atajo C, en lugar de abrirse a un panel vacío. Seleccionar siempre permanece.
Tus propias acciones en la barra superior
Una acción en todo el lienzo, como guardarlo, pertenece a la barra superior al lado del grupo deshacer-rehacer. UI.topBar.actions declara pastillas dibujadas con el mismo estilo que la Búsqueda, Filtro y Notas, por lo que un tema que cambia el estilo de esos también cambia el estilo de estos.
const options = {
UI: {
topBar: {
actions: [{
id: 'save-graph',
text: () => storedId ? 'Update graph' : 'Save as graph',
async onclick(_event, ctx) {
if (storedId) return updateGraph(storedId, ctx.graph)
const values = await ctx.promptData({
fields: [{ key: 'name', label: 'Name', type: 'text' }],
})
if (values) storedId = await createGraph(values.name, ctx.graph)
},
menu: () => storedId
? [{ text: 'Save as new graph…', onclick: saveAsNew }]
: [],
}],
},
},
}- Dónde.
placement: 'end'(el valor predeterminado) coloca la pastilla justo antes de deshacer-rehacer grupo;'start'lo coloca después de las pastillas incorporadas a la izquierda. Las pastillas mantienen el orden. fueron declarados en. - Lo que dice.
text,title,visibleyenabledtoman un valor o una función de el gráfico. Las funciones se leen de nuevo después de cada cambio de datos, engraph.UIManager.refreshTopBar(), y una vez que se liquida una promesa devuelta poronclick. Mientras esa promesa esté vigente, la píldora estará desactivada, por lo que no se puede iniciar un guardado lento dos veces. - Lo que obtiene.
onclick(event, ctx)recibe el gráfico y dos ayudantes que abren el modal de la biblioteca:ctx.promptData({ fields })se resuelve en los valores onullen cancelar yctx.confirm({ body })resuelvetruesolo en el botón de confirmación.ctx.refresh()relee cada acción. - Un cursor. Con
menu, la pastilla se convierte en un botón dividido: la etiqueta diceonclick, y un cursor abre las filas, en el mismo formato de fila que los menús contextuales (sin submenús). Una forma de función se entrega de la misma maneractxy se llama en cada actualizar y cada apertura; Si bien no devuelve filas, la píldora no tiene ningún signo de intercalación. escapar o un hacer clic en otro lugar cierra las filas. - Un atajo.
shortcutdibuja una insignia en la pastilla. Es sólo una etiqueta: registre el atándote a ti mismo.
Un complemento agrega una pastilla con ctx.addTopBarAction(action), que devuelve un triturador (ver Complementos). Las pastillas siguen la tira: ninguna en viewer o static modo, y ninguno con UI.topBar.enabled: false.
Un lienzo vacío
Un gráfico sin nodos ni notas muestra una tarjeta en el medio del lienzo, por lo que una fuente sin nada que dibujar no se lee como un gráfico que no se pudo cargar. Dice "Nada en el lienzo todavía" a menos que le des algo más que decir:
const options = {
UI: {
emptyState: {
render: ({ initial, graph }) => {
const box = document.createElement('div')
box.textContent = initial ? 'Nothing is related to this record.' : 'The canvas is empty.'
const button = document.createElement('button')
button.textContent = 'Find related'
button.onclick = () => graph.UIManager.openPivotMode()
box.append(button)
return box
},
},
},
}La tarjeta sigue los datos. Agregar un nodo o una nota lo elimina y eliminar el último de ellos, con la mano o deshaciendo la ingesta que los trajo, lo trae de vuelta. Nodos el Los filtros ocultan el recuento aún: el gráfico se reduce, no está vacío.
render se ejecuta cada vez que aparece la tarjeta, no en cada cambio mientras está activa. initial es true hasta que el gráfico haya mantenido un nodo, por lo que un analista que vació un lienzo completo puede que se le diga algo distinto de lo que se le dice a una fuente vacía. Una cadena devuelta se representa como texto sin formato, y render puede ser async como los ganchos a continuación.
La tarjeta utiliza la superficie y el borde del cromo, por lo que sigue el tema. Le permite al los gestos del lienzo, por lo que la panorámica, el zoom y el menú del lienzo funcionan en él, excepto sobre contenido interactivo: un botón, un enlace, un control de formulario o cualquier cosa con un tabindex obtiene sus propios clics. UI.emptyState: false no muestra nada en absoluto.
Contenido asincrónico
Cada gancho de contenido proporcionado por el consumidor puede devolver un Promise en lugar del contenido en sí. Eso cubre la barra lateral. mainHeader.render, propertiesPanel.render / nodePropertiesMap / edgePropertiesMap, neighborsPanel.render, un panel adicional title y render, la información sobre herramientas render, renderNodeExtra, renderEdgeExtra y mapas de propiedades, y el lienzos vacíos render.
Esto existe para el caso en el que los datos de un nodo son una referencia a un registro en lugar de que el registro en sí, y el contenido interesante está detrás de una llamada HTTP:
const options = {
UI: {
tooltip: {
renderNodeExtra: async (node, { signal }) => {
const res = await fetch(`/enrich/${node.getData().uuid}`, { signal })
return renderChips(await res.json()) // an HTMLElement
},
},
},
}Agregue async, reenvíe signal y la biblioteca se encarga del resto:
| Marcador de posición | Mientras la promesa está pendiente, un esqueleto temático ocupa la ranura. |
| Intercambiar | Al resolverse, el contenido reemplaza el marcador de posición existente. |
| Estancamiento | Un resultado que llega después de que su espacio ha desaparecido (colocó el cursor sobre otro nodo, cambió la selección, actualizó el panel) es eliminado. Solo se puede confirmar el renderizado más reciente de una superficie, independientemente del orden en que se resuelvan. |
| Cancelación | ctx.signal se cancela cuando se reemplaza un renderizado o se elimina el gráfico, por lo que un fetch reenviado se cancela en lugar de filtrarse. |
| Fallo | Una promesa rechazada genera una línea de error compacta en lugar de dejar una rueda giratoria para siempre. Un renderizado abortado no es un error y no muestra nada. |
El contexto de renderizado
Cada gancho de contenido recibe un RenderContext como su último argumento. Los ganchos sincrónicos existentes simplemente lo ignoran.
render: async (element, { signal, isStale }) => {
const rows = await fetchRows(element, signal)
if (isStale()) return '' // cheap guard for non-abortable work
return renderRows(rows)
}Personalizando el marcador de posición
UI.asyncContent anula lo que se muestra mientras está pendiente y en caso de error. ambos acepte una cadena, un HTMLElement o una función de la superficie:
const options = {
UI: {
asyncContent: {
placeholder: (surface) => surface === 'tooltip' ? 'Loading…' : mySkeleton(),
error: 'Could not load',
},
},
}surface es uno de 'tooltip', 'properties', 'neighbors', 'mainHeader', 'extraPanel' o 'emptyState'.
Los ganchos sincrónicos están intactos.
El contenido devuelto se comporta directamente exactamente como siempre: la misma llamada, la misma marco, sin marcador de posición ni elemento contenedor. Nada sobre un existente cambios de integración.
¿Qué no puede ser asíncrono?
Dos grupos permanecen sincrónicos a propósito:
HeaderMapEntry.title/subtitlealimenta la ranura de título de ajuste automático y búsqueda de nodos (resolveNodeByName), los cuales necesitan el texto ahora. Utilice un asyncmainHeader.rendersi necesita obtener detalles en el encabezado.PropertyEntry.name/value- busca las filas en su lugar: un asíncrononodePropertiesMapresuelve una vez y luego devuelve las entradas simples, en lugar de que poner una ruleta en cada celda.
Los ganchos del renderizador por cuadro (render.renderNode, renderLabel, renderCluster y NodeStyle.html) también son solo de sincronización: se ejecutan dentro de la ruta de dibujo, según nodo, por tick. Si necesita un nodo asíncrono decoración, busque los datos del nodo y deja que el renderizador síncrono lo lea.