Refactor Insertion API #65290
Labels
[Package] Block editor
/packages/block-editor
[Package] Editor
/packages/editor
[Type] Code Quality
Issues or PRs that relate to code quality
Insertion point can mean a lot of different things, and it's very easy to get confused about which action to dispatch or which selector to use. For example, here's what we have in the block editor and editor packages for insertion points:
showInsertionPoint
hideInsertionPoint
getBlockInsertionPoint
isBlockInsertionPointVisible
setInserterIsOpened
__experimentalSetIsInserterOpened
getInsertionPoint
__experimentalGetInsertionPoint
useInsertionPoint
These can be broken down into separate concepts:
There's overlap as they need to communicate with each other.
Insertion Cues: Current state of the API
One of example of these is the blue lines on the canvas that show when you hover around the canvas or hover a block in the inserter. It shows you where you'll be inserting to. To show an insertion point on the canvas, you'd emit the
showInsertionPoint
action. To hide it,hideInsertionPoint
.If you need to know where this insertion point is showing up on the page, which selector do you use?
If you guessed
getInsertionPoint
, you'd be wrong. That's for the state of the sidebar inserter. You usegetBlockInsertionPoint
to access what was set inshowInsertionPoint
.But, if there's no data set from
showInsertionPoint
, thengetBlockInsertionPoint
will return the next best place to insert.With
getBlockInsertionPoint
we're starting to blur the canvas insertion cues with where a block will insert.To check if an insertion cue is showing or not, use
isBlockInsertionPointVisible
.For example, if I want to know where the block might insert, I can use
getBlockInsertionPoint
. If I want to know if the block insertion point is showing and where it's showing, I'd have to useisBlockInsertionPointVisible() && getBlockInsertionPoint()
.Insertion Location: Current state of the API
You can insert blocks in plenty of ways, but for this we'll focus on inserting via the quick inserter and the sidebar inserter.
If you hover the canvas to show the blue line and inserter, you can click the
+
button that shows up to open the inserter. If you insert a block there, then it uses its own internalgetInsertionIndex
function to determine where to insert. No interaction with the store.If you click the "Browse all" button, it emits the
setInserterIsOpened
to the editor store with an object defining where we should insert.These insertion points are passed down into the inserter via the editor as
getInsertionPoint
(which is reading fromsetInserterIsOpened
). This point is passed down as a prop into the inserter sidebar touseInsertionPoint
when we click on a block to insert.When we hover blocks, we see the location they'll insert on the canvas with the inserter cues above. Hovering a block emits the
showInsertionPoint
which will make the blue line appear on the canvas. However, that point might be different than what is returned fromgetInsertionPoint
, as that's only the location the inserter initialized to.Not only that, but when you click the block, it goes through logic in
useInsertionPoint
that may be a spot different thangetBlockInsertionPoint
ORgetInsertionPoint
. There isn't a way to know whereuseInsertionPoint
will insert something unless you directly pass it aclientId
orroot
andindex
to insert into.Issues with the current API
Naming
The big one here is
getInsertionPoint
vsgetBlockInsertionPoint
.getInsertionPoint
does not return the values fromshowInsertionPoint
. That'sgetBlockInsertionPoint
(maybe, if the insertion point is set).Insertion Point is in the editor store
setIsInserterOpened
in theeditor
package opens and sets the insertion point. We can't change this insertion point from theblock-editor
store, and most of the time that's where we need to access this info. The information around insertion should be stored within theblock-editor
store, not the editor store. We ran into an issue of not being able to clear the insertion point when selecting a new block, because block selection is in the editor package and insertion point is in the editor package.getBlockInsertionPoint muddles concepts of insertion cue and insertion point
getBlockInsertionPoint
is either returning:insertionPoint
(which is the state ofSHOW/HIDE_INSERTION_POINT
, not the actual point of insertion)Neither of these means "the place where a block where will be inserted." It means, "a place a block inserter might be showing or a place it might fallback to being inserted into."
Separating out the actual insertion point vs the insertion cue will be really helpful.
Also, because hovering blocks updates
SHOW_INSERTION_POINT
,getBlockInsertionPoint
is constantly firing. We don't need to update an insertion point, we're just wanting to show a cue at an insertion point.Potential Changes
While this is all confusing, it worked well enough until we recently allowed the inserter to stay open. This means you can now change your insertion point with the inserter still open. For example, if you:
we should now be inserting after the selected block, not where you initially opened the inserter.
Here's my potential ideal. I don't know how feasible it is or if this is a good idea. But I'd like it to start the conversation.
Block Editor Store
setInsertionPoint
: Sets where we want block insertion to happen.getInsertionPoint
: Gets the place we want a block to be inserted. Should this also receive an optionalblockName
? It will return the closest available place that block could be inserted. Includes the fallbacks if there is no explicit insertion point. This is the source of truth for inserting, and will be used byuseInsertionPoint
unless it is given a specific point.showInsertionCue( index, rootClientId, blockName )
: Show blue line at a specific location for an optional blockName. If no insertion point or block is passed, then show it wherever is returned fromgetInsertionPoint
.hideInsertionCue
: Hide the cue.isInsertionCueVisible
: Is it showing?Editor Store
setInserterIsOpened
: Open the inserter and optionally specify the open state of the inserter, like do you want the pattern or block tab showing?Implementation Changes
useInsertionPoint
relies ongetInsertionPoint
unless passed a specific index rather than having its own fallback logic.setInsertionPoint
happens when you click the inline insertion cue +, not after "browse all" and relies ongetInsertionPoint
to reduce duplicated logic.To Refactor or Not Refactor?
I would not want to move forward with such a refactor unless there were clear benefits. In this case, I think there are. There are have been a lot of bugs recently come up that are traced back to confusion over
getInsertionPoint
vsgetBlockInsertionPoint
and making a mistake can cause serious performance issues. For example, to know where a block will be inserted, it makes sense to usegetBlockInsertionPoint
, however, this value updates rapidly when hovering around the canvas.The text was updated successfully, but these errors were encountered: