I noticed the rescroll was implement in a way designed to be agnostic to
arcade-machine. However this induces a very great cost to performance. Instead,
I introduce a new component and ArcScrollable HOC. arcade-machine will only
attempt to rescroll these marked containers. I also noticed that we were running
the full rescroll algorithm, even if the element being scrolled to was already
on the screen! Fixing these leads to substantial speed improvements,
particularly in the deeply-nested case.
Overall this pplies the same treatment to scrolling as has been applied
elsewhere in the project. The scrolling algorithm is now a dependency-injected
class. We also try to use the browser's native scrollTo with `smooth` behavior
if possible, rather than animating scroll ourselves. Overall this leads to a
5-6x performance improvement in the deeply nested benchmark cases.
This is a general refactor around the focus service. Previously, a lot
of the focusing logic was within the focus service, and there were special
casing around arc-focus-inside and arc-exclude*.
This PR breaks the focus strategies out to their own classes, who implement
the IFocusStrategy interface. Focusing is done via a FocusContext instantiated
by the FocusService, which encapsulates the logic for getting the next
focusable element for the current navigation. The really cool thing this
lets us do is actually pass that context down through the ArcEvent, so now
focus exclusions and arc-focus-inside logic can be handled entirely generically
by components who register themselves into the focus store. This method also
makes exclusion much more efficient now.