You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe
Currently, the Graph.defaultLoopStyle property directly references the EdgeStyle.Loop implementation. This hardcoded link limits flexibility and makes tree shaking impossible for users who do not rely on loop edges in their application.
Warning
This request assumes that missing a loop edge style won't break rendering. This needs to be verified when stories covering loop behavior are implemented (see the related issue's task for that check).
Describe the solution you'd like
We’d like to make Graph.defaultLoopStyle accept a string name referring to a registered edge style, not the direct function reference. For example: "loopEdgeStyle" instead of EdgeStyle.Loop.
It should support both a string or a function (like other edge-related props).
The default value can stay "loopEdgeStyle", to ensure backward compatibility.
This change would reduce unnecessary bundle size for apps that don’t use loops.
Notes
this will introduce a breaking change for people relying on the default loop implementation
now, they will have to be sure that the loop edge style is registered when using BaseGraph
when using Graph, there will be no change as the loop edge style is registered in that case
this is not a new constraint in practice: since 0.20.0, the loop edge style already has to be registered for the current function-reference configuration to behave correctly (see below)
Passing a function reference is already broken when the edge style is not registered
EdgeStyleRegistry keys its metadata (handlerKind, isOrthogonal, allowIntermediateHandles) by the EdgeStyleFunction reference itself. Loop styles are resolved through the very same path as regular edge styles (GraphView.getEdgeStyle), so an unregistered loop function silently falls back to the registry defaults: getHandlerKind returns 'default', isOrthogonal returns false, allowsIntermediateHandles returns true.
This is a regression introduced by #809, released in 0.20.0 (May 2025). Before that version, the edge handler selection compared the resolved edge style against hard-coded EdgeStyle references, so EdgeStyle.Loop always got the ElbowEdgeHandler whether or not it was registered:
#809 replaced those hard-coded references with EdgeStyleRegistry.getHandlerKind(edgeStyle) to enable tree-shaking, which makes registration mandatory for the metadata to be found. registerLoopEdgeStyle declares handlerKind: 'elbow' for EdgeStyle.Loop, so today, setting defaultLoopStyle = EdgeStyle.Loop without registering it makes a selected loop edge use the default EdgeHandler instead of the ElbowEdgeHandler, and the edge handles are wrong. The same applies to any custom loop style passed as a function.
This is the same constraint that the CellStateStyle.edgeStyle JSDoc already documents ("IMPORTANT: when using an EdgeStyleFunction, be sure that is correctly registered in the EdgeStyleRegistry. Otherwise, the function may not be correctly configured."), except that loopStyle and defaultLoopStyle do not carry that warning today.
Switching to a string is therefore not a real restriction: the edge style has to be registered anyway for the behavior to be correct. The string form just makes that requirement explicit and impossible to get wrong, instead of failing silently.
Describe alternatives you've considered
Keeping the function reference in place hardcodes the dependency and prevents tree shaking.
This is not the same as the default edge, vertex, and label shapes defined in CellRenderer. Those are critical default implementations: without defaultVertexShape, defaultEdgeShape, or defaultTextShape, cells wouldn’t render at all.
These are the only concrete shape implementations that should be part of the codebase. Everything else - including loop styles - should ideally be configurable through registration.
defaultVertexShape = RectangleShape
defaultEdgeShape = ConnectorShape
defaultTextShape = TextShape
But unlike these core shapes, the loop edge style is not essential and shouldn’t be hardcoded.
Additional context
Allow string values for Graph.defaultLoopStyle. This would make the loop style consistent with other configurable elements via registration.
Add a Storybook story showing different loop configurations:
default loop from Graph
custom style with loopStyle
custom style with noLoop
custom style with orthogonalLoop
⚠️ Fix mismatch in the CellStateStyle.orthogonalLoop JSDoc: currently mentions OrthConnector, but it's not used. Either the code or the JSDoc should be updated to reflect the actual implementation.
Document the registration requirement in the JSDoc, for the function form too:
AbstractGraph.defaultLoopStyle (packages/core/src/view/AbstractGraph.ts, moving to GraphView with Refactor Graph class and mixins to improve modularity and tree-shaking #762): add the warning that even when passing an EdgeStyleFunction instead of a registered name, the edge style must be registered in the EdgeStyleRegistry, otherwise its metadata (handlerKind, isOrthogonal, allowIntermediateHandles) is not found and the behavior is incorrect.
CellStateStyle.loopStyle (packages/core/src/types.ts): same warning.
Reuse the wording already present on CellStateStyle.edgeStyle, which documents exactly this constraint.
Align CellStateStyle.loopStyle with CellStateStyle.edgeStyle: type it as StyleEdgeStyleValue so a registered name can be used per cell too, instead of only an EdgeStyleFunction.
Important
Be aware that it is planned to move Graph.defaultLoopStyle to GraphView.defaultLoopStyle as part of #762
Is your feature request related to a problem? Please describe
Currently, the
Graph.defaultLoopStyleproperty directly references theEdgeStyle.Loopimplementation. This hardcoded link limits flexibility and makes tree shaking impossible for users who do not rely on loop edges in their application.Warning
This request assumes that missing a
loopedge style won't break rendering. This needs to be verified when stories covering loop behavior are implemented (see the related issue's task for that check).Describe the solution you'd like
We’d like to make
Graph.defaultLoopStyleaccept a string name referring to a registered edge style, not the direct function reference. For example:"loopEdgeStyle"instead ofEdgeStyle.Loop."loopEdgeStyle", to ensure backward compatibility.Notes
Passing a function reference is already broken when the edge style is not registered
EdgeStyleRegistrykeys its metadata (handlerKind,isOrthogonal,allowIntermediateHandles) by theEdgeStyleFunctionreference itself. Loop styles are resolved through the very same path as regular edge styles (GraphView.getEdgeStyle), so an unregistered loop function silently falls back to the registry defaults:getHandlerKindreturns'default',isOrthogonalreturnsfalse,allowsIntermediateHandlesreturnstrue.This is a regression introduced by #809, released in 0.20.0 (May 2025). Before that version, the edge handler selection compared the resolved edge style against hard-coded
EdgeStylereferences, soEdgeStyle.Loopalways got theElbowEdgeHandlerwhether or not it was registered:#809 replaced those hard-coded references with
EdgeStyleRegistry.getHandlerKind(edgeStyle)to enable tree-shaking, which makes registration mandatory for the metadata to be found.registerLoopEdgeStyledeclareshandlerKind: 'elbow'forEdgeStyle.Loop, so today, settingdefaultLoopStyle = EdgeStyle.Loopwithout registering it makes a selected loop edge use the defaultEdgeHandlerinstead of theElbowEdgeHandler, and the edge handles are wrong. The same applies to any custom loop style passed as a function.This is the same constraint that the
CellStateStyle.edgeStyleJSDoc already documents ("IMPORTANT: when using anEdgeStyleFunction, be sure that is correctly registered in theEdgeStyleRegistry. Otherwise, the function may not be correctly configured."), except thatloopStyleanddefaultLoopStyledo not carry that warning today.Switching to a string is therefore not a real restriction: the edge style has to be registered anyway for the behavior to be correct. The string form just makes that requirement explicit and impossible to get wrong, instead of failing silently.
Describe alternatives you've considered
Keeping the function reference in place hardcodes the dependency and prevents tree shaking.
This is not the same as the default edge, vertex, and label shapes defined in
CellRenderer. Those are critical default implementations: withoutdefaultVertexShape,defaultEdgeShape, ordefaultTextShape, cells wouldn’t render at all.These are the only concrete shape implementations that should be part of the codebase. Everything else - including loop styles - should ideally be configurable through registration.
defaultVertexShape = RectangleShapedefaultEdgeShape = ConnectorShapedefaultTextShape = TextShapeBut unlike these core shapes, the loop edge style is not essential and shouldn’t be hardcoded.
Additional context
Graph.defaultLoopStyle. This would make the loop style consistent with other configurable elements via registration.GraphloopStylenoLooporthogonalLoopCellStateStyle.orthogonalLoopJSDoc: currently mentionsOrthConnector, but it's not used. Either the code or the JSDoc should be updated to reflect the actual implementation.AbstractGraph.defaultLoopStyle(packages/core/src/view/AbstractGraph.ts, moving toGraphViewwith Refactor Graph class and mixins to improve modularity and tree-shaking #762): add the warning that even when passing anEdgeStyleFunctioninstead of a registered name, the edge style must be registered in theEdgeStyleRegistry, otherwise its metadata (handlerKind,isOrthogonal,allowIntermediateHandles) is not found and the behavior is incorrect.CellStateStyle.loopStyle(packages/core/src/types.ts): same warning.CellStateStyle.edgeStyle, which documents exactly this constraint.CellStateStyle.loopStylewithCellStateStyle.edgeStyle: type it asStyleEdgeStyleValueso a registered name can be used per cell too, instead of only anEdgeStyleFunction.Important
Be aware that it is planned to move
Graph.defaultLoopStyletoGraphView.defaultLoopStyleas part of #762