Rappels
Pivotick vous permet de vous connecter aux interactions des utilisateurs et aux événements de simulation via l'option callbacks. Vous pouvez fournir des fonctions pour divers événements sur le canevas, les nœuds et les bords.
Rappels de canevas
| Rappel | Paramètres | Description |
|---|---|---|
onCanvasClick | (event: PointerEvent) | Lancé lorsque le canevas est cliqué. |
onCanvasContextmenu | (event: PointerEvent) | Tiré sur la toile, faites un clic droit. |
onCanvasMousemove | (event: MouseEvent) | Déclenché lorsque la souris se déplace sur le canevas. |
onCanvasZoom | (event: unknown) | Déclenché lorsque le niveau de zoom du canevas change. |
Rappels de nœuds
| Rappel | Paramètres | Description |
|---|---|---|
onNodeClick | (event: PointerEvent, node: Node, element: TElement) | Lancé lorsqu'un nœud est cliqué. |
onNodeDbclick | (event: PointerEvent, node: Node, element: TElement) | Lancé lorsqu'un nœud est double-cliqué. |
onNodeContextmenu | (event: PointerEvent, node: Node, element: TElement) | Lancé sur le nœud, cliquez avec le bouton droit. |
onNodeHoverIn | (event: PointerEvent, node: Node, element: TElement) | Lancé lorsque la souris entre dans un nœud. |
onNodeHoverOut | (event: PointerEvent, node: Node, element: TElement) | Lancé lorsque la souris quitte un nœud. |
onNodeSelect | (node: Node, element: TElement) | Lancé lorsqu'un nœud est sélectionné. |
onNodeBlur | (node: Node, element: TElement) | Lancé lorsqu'un nœud perd le focus/sélection. |
onNodeDragging | (event: MouseEvent, node: Node) | Lancé en continu pendant qu'un nœud est déplacé. |
onNodeExpansion | (event: PointerEvent, edge: Edge, element: TElement) | Déclenché lorsqu'un nœud est développé ou réduit. |
Rappels Edge
| Rappel | Paramètres | Description |
|---|---|---|
onEdgeClick | (event: PointerEvent, edge: Edge, element: TElement) | Déclenché lorsqu'un bord est cliqué. |
onEdgeDbclick | (event: PointerEvent, edge: Edge, element: TElement) | Déclenché lorsqu'un bord est double-cliqué. |
onEdgeContextmenu | (event: PointerEvent, edge: Edge, element: TElement) | Tiré sur le bord, clic droit. |
onEdgeHoverIn | (event: PointerEvent, edge: Edge, element: TElement) | Lancé lorsque la souris entre dans un bord. |
onEdgeHoverOut | (event: PointerEvent, edge: Edge, element: TElement) | Lancé lorsque la souris quitte un bord. |
onEdgeSelect | (edge: Edge, element: TElement) | Déclenché lorsqu'un bord est sélectionné. |
onEdgeBlur | (edge: Edge, element: TElement) | Déclenché lorsqu'un bord perd le focus/sélection. |
Hooks du cycle de vie du chemin d'écriture
Chaque mutation qu'un utilisateur peut effectuer passe par un before-hook : la bibliothèque propose, votre code décide - de manière asynchrone, et la décision peut échouer. En l'absence de hook, le comportement est inchangé et la mutation programmatic (graph.addNode(), graph.removeNode(), graph.removeEdge()) ne les invoque jamais, donc votre propre code pilotant le modèle n'est pas contrôlé par votre propre hook.
| Rappel | Licencié quand | Retour |
|---|---|---|
onBeforeDelete | L'utilisateur demande de supprimer les nœuds/arêtes/notes, avant que quoi que ce soit ne soit supprimé | false pour opposer son veto, true pour supprimer la demande, { accept, nodes, edges, notes } pour la restreindre |
onBeforeNodeCreate | L'utilisateur crée un nœud (Créer ▸ Ajouter un nœud, canevas ▸ Ajouter un nœud ici) | false pour opposer son veto, ou { accept, id, data, style } |
onBeforeEdgeCreate | Un geste de connexion a résolu une cible, avant que le bord n'existe | false pour opposer son veto, ou { accept, data, style, id, directed } |
isValidConnection | En direct, à chaque survol lors de la connexion (doit être synchronisé + bon marché) | false marque la cible invalide — le hook avant-création n'est pas consulté |
onBeforeNodeEditCommit | Une modification de nœud est validée | false refuse la validation, laissant les données du nœud intactes |
onBeforeEdgeEditCommit | Une modification périphérique est validée | false refuse la validation, laissant les données du Edge intactes |
Un commit d'édition accepté s'annonce sur le bus de données — nodeChange / edgeChange, avec previousData et nextData — et est repeint immédiatement ; un refus ne change rien du tout.
Leurs homologues de l'interface utilisateur — onNodeEdit / onEdgeEdit (renvoie le corps modal) et onNodeEditCancel / onEdgeEditCancel — vous permettent de remplacer l'éditeur plutôt que de le bloquer. En dehors de cela, editors.nodeEditor.fields / editors.edgeEditor.fields déclarent le formulaire comme construction modale par défaut (une liste déroulante de relations au lieu d'un champ de texte libre, par exemple) ; sans eux, un champ de texte par clé de données est déduit. Un corps personnalisé est propriétaire du brouillon - modifiez session.draft au fur et à mesure que l'utilisateur tape, car il n'y a aucun formulaire à lire lors de la soumission.
Suppression
onBeforeDelete reçoit la toute la conséquence du geste, résolue par la bibliothèque : les éléments nommés par l'utilisateur, plus cascadingEdges — les bords que la suppression de ces nœuds détruirait (graph.removeNode cascades). Les deux ne se chevauchent jamais, chacun peut donc être conservé exactement une fois.
Le rétrécissement s'effectue par type : un tableau fourni remplace l'ensemble demandé de ce type, une clé omise le laisse comme demandé (donc { accept: true } correspond à true et { accept: true, nodes: [] } ne supprime aucun nœud). Un veto ne supprime rien, ne déclenche aucun nodeRemove / edgeRemove / noteRemove et laisse la sélection intacte.
callbacks: {
onBeforeDelete: async ({ nodes, edges, cascadingEdges, origin, confirm }) => {
if (!await confirm({
title: 'Delete from event?',
body: `${nodes.length} element(s) and ${edges.length + cascadingEdges.length} link(s).`,
})) return false
const saved = await deleteServerSide(nodes, [...edges, ...cascadingEdges])
// Keep exactly what the server actually deleted.
return { accept: true, nodes: nodes.filter((n) => saved.has(n.id)) }
},
}ctx.confirm(options) ouvre le modal de confirmation de la bibliothèque, résolvant false sur chaque chemin d'annulation. ctx.origin indique quelle capacité a été demandée ('bulk-action' ou 'context-menu').
Pendant qu'un crochet décide
Un hook qui récupère ou enregistre avant de répondre laisse l'utilisateur attendre. Après 200 ms sans réponse, le graphique montre qu'il est en attente : un curseur de progression, et une petite roulette à la fin du bord d'aperçu (onBeforeEdgeCreate), au point de dépôt (onBeforeNodeCreate), ou sous forme de pilule "En attente…" en bas du canevas (suppressions, modifications de validation, onBeforeIngest). Un crochet qui répond plus tôt ne montre rien.
Une invite que le hook ouvre à travers son contexte (promptLabel, promptData, confirm) prend le signal vers le bas pendant qu'il est à l'écran, et l'attente après sa fermeture reçoit le même traitement, donc un hook qui demande puis enregistre les lectures comme étant occupé uniquement lorsqu'il est occupé. S'échapper pendant l'attente d'un geste de connexion quitte le mode de connexion et supprime le signal ; un crochet qui accepte après cela obtient toujours son avantage, car il l'a peut-être déjà enregistré.
UI: {
busyIndicator: { delay: 300, label: 'Saving…' }, // or false, to draw your own
}Pendant que le signal s'affiche, l'élément racine du graphique porte data-pvt-busy.
Supprimer l'affordance à la place
Un veto est la mauvaise réponse lorsqu'une opération est jamais autorisée — pour une intégration dont la vérification ACL est connue avant la construction du graphe, supprimez l'affordance. Chaque indicateur editors.<editor>.enabled (activé sauf explicitement false) supprime ses boutons et entrées de menu :
| Drapeau | Supprime |
|---|---|
editors.deletion.enabled | Le bloc de la barre latérale Delete et les entrées de suppression de nœud/bord/note |
editors.nodeCreator.enabled | Créer ▸ Ajouter un nœud et Ajouter un nœud ici du menu de canevas |
editors.nodeEditor.enabled | Créer ▸ Modifier le nœud |
editors.edgeEditor.enabled | Le menu Edge Edit Edge |
Consultez la carte de galerie Persist supprime, modifie et crée pour les trois hooks sur un backend remplaçant.
Rappels de simulation
| Rappel | Paramètres | Description |
|---|---|---|
onSimulationTick | () | J'ai déclenché chaque tick de simulation. |
onSimulationSlowTick | () | Tiré occasionnellement pendant la simulation (tous les dixièmes de simulationTick). |
infos
Le type element est svg uniquement si l'option render.type == "svg".
Exemple
import Pivotick from './pivotick.es.js'
options = {
callbacks: {
onNodeClick: (event, node) => {
console.log('Node clicked:', node.id)
},
onNodeHoverIn: (event, node) => {
console.log('Mouse entered node:', node.id)
},
onSimulationTick: () => {
console.log('Simulation tick')
}
}
}
const graph = new Pivotick(container, data, options)