Bug fixes and refactoring regarding

This commit is contained in:
Aleksi Lassila
2024-01-27 20:33:23 +02:00
parent 14eae0fa9b
commit b14bf78292
14 changed files with 252 additions and 295 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import I18n from './lib/components/Lang/I18n.svelte';
import { Link, Route, Router } from 'svelte-navigator';
import { handleKeyboardNavigation } from './lib/actions/focusAction';
import { handleKeyboardNavigation, Selectable } from './lib/selectable';
import { onMount } from 'svelte';
import Container from './Container.svelte';
import NavbarItem from './lib/components-new/NavbarItem.svelte';
@@ -14,35 +14,18 @@
import ManagePage from './lib/pages/ManagePage.svelte';
import SearchPage from './lib/pages/SearchPage.svelte';
// const navBarContainer = mainContainer.createChild('nav').setDirection('vertical');
// const isNavBarOpen = navBarContainer.hasFocusWithin;
//
// const contentContainer = mainContainer.createChild('content').setDirection('vertical');
Selectable.focusedObject.subscribe((s) => console.log('FocusedObject', s));
let mainContent: Selectable;
// onMount(() => {
// contentContainer.focus();
// });
onMount(() => {
mainContent.focus();
});
onMount(() => console.log('didmount'));
let mount = false;
$: console.log('mount', mount);
let isNavBarOpen: Readable<boolean>;
</script>
<I18n />
<Container horizontal class="bg-stone-950 text-white flex flex-1 w-screen">
<!-- <Container class="flex flex-col">-->
<!-- <Container tag="button" on:click={() => (mount = !mount)}>Button 1</Container>-->
<!-- <Container tag="button" on:click={() => console.log('Button 2 clicked')}>Button 2</Container>-->
<!-- <Container tag="button" on:click={() => console.log('Button 3 clicked')}>Button 3</Container>-->
<!-- </Container>-->
<!-- <div>-->
<!-- <Container tag="button" on:click={() => console.log('test')}>Test</Container>-->
<!-- </div>-->
<!-- {#if mount}-->
<!-- <TestElement />-->
<!-- {/if}-->
<Router>
<Container
class={classNames('flex flex-col', 'p-4', {
@@ -58,7 +41,7 @@
</div>
<div class="flex flex-col flex-1 justify-center">
<NavbarItem to="series">
<NavbarItem to="/">
<Laptop class="w-8 h-8 mr-3" slot="icon" />
<span class="text-xl" slot="text"> Series</span>
</NavbarItem>
@@ -84,7 +67,7 @@
</div>
</Container>
<Container class="flex-1 flex flex-col min-w-0">
<Container bind:container={mainContent} class="flex-1 flex flex-col min-w-0">
<Route>
<SeriesPage />
</Route>

View File

@@ -1,21 +1,28 @@
<script lang="ts">
import { onMount } from 'svelte';
import { Container } from './lib/actions/focusAction';
import { Selectable } from './lib/selectable';
import type { Readable } from 'svelte/store';
export let name: string = '';
export let horizontal = false;
export let focusOnMount = false;
const { registerer, ...rest } = new Container(name)
const { registerer, ...rest } = new Selectable(name)
.setDirection(horizontal ? 'horizontal' : 'vertical')
.getStores();
export const container = rest.container;
export const hasFocus = rest.hasFocus;
export const hasFocusWithin = rest.hasFocusWithin;
export const focusIndex = rest.focusIndex;
export let tag = 'div';
onMount(() => {
rest.container._initializeContainer();
rest.container._initializeSelectable();
if (focusOnMount) {
rest.container.focus();
}
return () => {
rest.container._unmountContainer();

View File

@@ -1,17 +1,17 @@
<script lang="ts">
import { onMount } from 'svelte';
import { Container, type FlowDirection } from './lib/actions/focusAction';
import { Selectable, type FlowDirection } from './lib/selectable';
export let name: string = '';
export let direction: FlowDirection = 'vertical';
const { registerer, ...rest } = new Container(name).setDirection(direction).getStores();
const { registerer, ...rest } = new Selectable(name).setDirection(direction).getStores();
export const container = rest.container;
export const hasFocus = rest.hasFocus;
export const hasFocusWithin = rest.hasFocusWithin;
onMount(() => {
rest.container._initializeContainer();
rest.container._initializeSelectable();
});
</script>

View File

@@ -1,9 +1,8 @@
<script lang="ts">
import classNames from 'classnames';
import { useNavigate } from 'svelte-navigator';
import { get, type Readable } from 'svelte/store';
import { type Readable } from 'svelte/store';
import Container from '../../Container.svelte';
import { Container as Cont } from '../../lib/actions/focusAction';
export let to: string;
let hasFocus: Readable<boolean>;
@@ -12,7 +11,6 @@
function handleClick() {
navigate(to);
get(Cont.focusedObject)?.giveFocus('right');
}
</script>

View File

@@ -1,73 +1,73 @@
<script lang="ts">
import { fade } from 'svelte/transition';
import IconButton from '../IconButton.svelte';
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
import classNames from 'classnames';
import type { Registerer } from '../../actions/focusAction';
export let gradientFromColor = 'from-stone-950';
export let heading = '';
let carousel: HTMLDivElement | undefined;
let scrollX = 0;
export let scrollClass = '';
</script>
<div class={classNames('flex flex-col gap-4 group/carousel', $$restProps.class)}>
<div class={'flex justify-between items-center gap-4 ' + scrollClass}>
<slot name="title">
<div class="font-semibold text-xl">{heading}</div>
</slot>
<div
class={classNames(
'flex gap-2 sm:opacity-0 transition-opacity sm:group-hover/carousel:opacity-100',
{
hidden: (carousel?.scrollWidth || 0) === (carousel?.clientWidth || 0)
}
)}
>
<IconButton
on:click={() => {
carousel?.scrollTo({ left: scrollX - carousel?.clientWidth * 0.8, behavior: 'smooth' });
}}
>
<ChevronLeft size={20} />
</IconButton>
<IconButton
on:click={() => {
carousel?.scrollTo({ left: scrollX + carousel?.clientWidth * 0.8, behavior: 'smooth' });
}}
>
<ChevronRight size={20} />
</IconButton>
</div>
</div>
<div class="relative">
<div
class={classNames(
'flex overflow-x-scroll items-center overflow-y-visible gap-4 relative scrollbar-hide p-1',
scrollClass
)}
bind:this={carousel}
tabindex="-1"
on:scroll={() => (scrollX = carousel?.scrollLeft || scrollX)}
>
<slot />
</div>
{#if scrollX > 50}
<div
transition:fade={{ duration: 200 }}
class={'absolute inset-y-0 left-0 w-0 sm:w-16 md:w-24 bg-gradient-to-r ' +
gradientFromColor}
/>
{/if}
{#if carousel && scrollX < carousel?.scrollWidth - carousel?.clientWidth - 50}
<div
transition:fade={{ duration: 200 }}
class={'absolute inset-y-0 right-0 w-0 sm:w-16 md:w-24 bg-gradient-to-l ' +
gradientFromColor}
/>
{/if}
</div>
</div>
<script lang="ts">
import { fade } from 'svelte/transition';
import IconButton from '../IconButton.svelte';
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
import classNames from 'classnames';
import type { Registerer } from '../../selectable';
export let gradientFromColor = 'from-stone-950';
export let heading = '';
let carousel: HTMLDivElement | undefined;
let scrollX = 0;
export let scrollClass = '';
</script>
<div class={classNames('flex flex-col gap-4 group/carousel', $$restProps.class)}>
<div class={'flex justify-between items-center gap-4 ' + scrollClass}>
<slot name="title">
<div class="font-semibold text-xl">{heading}</div>
</slot>
<div
class={classNames(
'flex gap-2 sm:opacity-0 transition-opacity sm:group-hover/carousel:opacity-100',
{
hidden: (carousel?.scrollWidth || 0) === (carousel?.clientWidth || 0)
}
)}
>
<IconButton
on:click={() => {
carousel?.scrollTo({ left: scrollX - carousel?.clientWidth * 0.8, behavior: 'smooth' });
}}
>
<ChevronLeft size={20} />
</IconButton>
<IconButton
on:click={() => {
carousel?.scrollTo({ left: scrollX + carousel?.clientWidth * 0.8, behavior: 'smooth' });
}}
>
<ChevronRight size={20} />
</IconButton>
</div>
</div>
<div class="relative">
<div
class={classNames(
'flex overflow-x-scroll items-center overflow-y-visible gap-4 relative scrollbar-hide p-1',
scrollClass
)}
bind:this={carousel}
tabindex="-1"
on:scroll={() => (scrollX = carousel?.scrollLeft || scrollX)}
>
<slot />
</div>
{#if scrollX > 50}
<div
transition:fade={{ duration: 200 }}
class={'absolute inset-y-0 left-0 w-0 sm:w-16 md:w-24 bg-gradient-to-r ' +
gradientFromColor}
/>
{/if}
{#if carousel && scrollX < carousel?.scrollWidth - carousel?.clientWidth - 50}
<div
transition:fade={{ duration: 200 }}
class={'absolute inset-y-0 right-0 w-0 sm:w-16 md:w-24 bg-gradient-to-l ' +
gradientFromColor}
/>
{/if}
</div>
</div>

View File

@@ -1,31 +1,30 @@
<script lang="ts">
import CardPlaceholder from '../Card/CardPlaceholder.svelte';
import classNames from 'classnames';
import Container from '../../../Container.svelte';
import type { Readable } from 'svelte/store';
export let size: 'dynamic' | 'md' | 'lg' = 'md';
export let orientation: 'landscape' | 'portrait' = 'landscape';
let focusIndex: Readable<number>;
let focusWithin: Readable<boolean>;
</script>
<p
class={classNames({
'bg-blue-500': $focusWithin
})}
>
Index: {$focusIndex}
</p>
{#each Array(10) as _, i (i)}
<Container
bind:focusIndex
bind:focusWithin
class={classNames({
'bg-red-500': $focusIndex === i && $focusWithin
})}
>
<CardPlaceholder {size} index={i} {orientation} />
</Container>
{/each}
<script lang="ts">
import CardPlaceholder from '../Card/CardPlaceholder.svelte';
import classNames from 'classnames';
import Container from '../../../Container.svelte';
import type { Readable, Writable } from 'svelte/store';
export let size: 'dynamic' | 'md' | 'lg' = 'md';
export let orientation: 'landscape' | 'portrait' = 'landscape';
export let focusIndex: Readable<number>;
let focusWithin: Writable<boolean>;
</script>
<p
class={classNames({
'bg-blue-500': $focusWithin
})}
>
Index: {$focusIndex}
</p>
{#each Array(10) as _, i (i)}
<Container
bind:focusWithin
class={classNames({
'bg-red-500': $focusIndex === i && $focusWithin
})}
>
<CardPlaceholder {size} index={i} {orientation} />
</Container>
{/each}

View File

@@ -1,14 +1,14 @@
<script lang="ts">
import { Container } from '../actions/focusAction';
export let container: Container;
const registerer = container.getRegisterer();
export let handleClick = () => {
container.focus();
};
</script>
<button use:registerer on:click={handleClick} class="outline-none ring-0">
<slot />
</button>
<script lang="ts">
import { Selectable } from '../selectable';
export let container: Selectable;
const registerer = container.getRegisterer();
export let handleClick = () => {
container.focus();
};
</script>
<button use:registerer on:click={handleClick} class="outline-none ring-0">
<slot />
</button>

View File

@@ -1,22 +1,22 @@
<script lang="ts">
import { Container } from '../actions/focusAction';
import Carousel from '../components/Carousel/Carousel.svelte';
import CarouselPlaceholderItems from '../components/Carousel/CarouselPlaceholderItems.svelte';
import classNames from 'classnames';
export let container: Container;
const focusWithin = container.hasFocusWithin;
</script>
<div
class={classNames('flex flex-col', {
'bg-green-100': $focusWithin
})}
>
<Carousel>
<CarouselPlaceholderItems {container} />
</Carousel>
<Carousel>
<CarouselPlaceholderItems {container} />
</Carousel>
</div>
<script lang="ts">
import { Selectable } from '../selectable';
import Carousel from '../components/Carousel/Carousel.svelte';
import CarouselPlaceholderItems from '../components/Carousel/CarouselPlaceholderItems.svelte';
import classNames from 'classnames';
export let container: Selectable;
const focusWithin = container.hasFocusWithin;
</script>
<div
class={classNames('flex flex-col', {
'bg-green-100': $focusWithin
})}
>
<Carousel>
<CarouselPlaceholderItems {container} />
</Carousel>
<Carousel>
<CarouselPlaceholderItems {container} />
</Carousel>
</div>

View File

@@ -4,6 +4,7 @@
import Carousel from '../components/Carousel/Carousel.svelte';
import CarouselPlaceholderItems from '../components/Carousel/CarouselPlaceholderItems.svelte';
import Container from '../../Container.svelte';
import type { Readable } from 'svelte/store';
settings.update((prev) => ({
...prev,
@@ -19,13 +20,15 @@
jellyfinItemsStore.subscribe((items) => {
console.warn('GOT ITEMS', items.data);
});
let focusIndex: Readable<number>;
</script>
<Container>
<Container focusOnMount>
<div>LibraryPage</div>
<Container horizontal>
<Container horizontal bind:focusIndex>
<Carousel>
<CarouselPlaceholderItems />
<CarouselPlaceholderItems {focusIndex} />
</Carousel>
</Container>
</Container>

View File

@@ -2,4 +2,4 @@
import Container from '../../Container.svelte';
</script>
<Container>MoviesPage</Container>
<Container focusOnMount>MoviesPage</Container>

View File

@@ -2,4 +2,4 @@
import Container from '../../Container.svelte';
</script>
<Container>SearchPage</Container>
<Container focusOnMount>SearchPage</Container>

View File

@@ -2,4 +2,4 @@
import Container from '../../Container.svelte';
</script>
<Container>SeriesPage</Container>
<Container focusOnMount>SeriesPage</Container>

View File

@@ -5,13 +5,13 @@ export type Registerer = (htmlElement: HTMLElement) => { destroy: () => void };
export type Direction = 'up' | 'down' | 'left' | 'right';
export type FlowDirection = 'vertical' | 'horizontal';
export class Container {
export class Selectable {
id: symbol;
name: string;
private parent?: Container;
private children: Container[] = [];
private parent?: Selectable;
private children: Selectable[] = [];
private htmlElement?: HTMLElement;
private neighbors: Record<Direction, Container | undefined> = {
private neighbors: Record<Direction, Selectable | undefined> = {
up: undefined,
down: undefined,
left: undefined,
@@ -22,27 +22,26 @@ export class Container {
private direction: FlowDirection = 'vertical';
static focusedObject: Writable<Container | undefined> = writable(undefined);
static focusedObject: Writable<Selectable | undefined> = writable(undefined);
focusIndex: Writable<number> = writable(0);
hasFocus: Readable<boolean> = derived(Container.focusedObject, ($focusedObject) => {
console.log('Updating hasFocus', $focusedObject, this);
hasFocus: Readable<boolean> = derived(Selectable.focusedObject, ($focusedObject) => {
return $focusedObject === this;
});
hasFocusWithin: Readable<boolean> = derived(Container.focusedObject, ($focusedObject) => {
let currentContainer: Container | undefined = $focusedObject;
hasFocusWithin: Readable<boolean> = derived(Selectable.focusedObject, ($focusedObject) => {
let currentSelectable: Selectable | undefined = $focusedObject;
while (currentContainer) {
if (currentContainer === this) {
while (currentSelectable) {
if (currentSelectable === this) {
return true;
}
currentContainer = currentContainer.parent;
currentSelectable = currentSelectable.parent;
}
return false;
});
static objects = new Map<HTMLElement, Container>();
static objects = new Map<HTMLElement, Selectable>();
constructor(name: string = '') {
this.id = Symbol();
@@ -56,37 +55,26 @@ export class Container {
return this;
}
setFocusByDefault(focusByDefault: boolean) {
this.focusByDefault = focusByDefault;
return this;
}
setHtmlElement(htmlElement: HTMLElement) {
this.htmlElement = htmlElement;
Container.objects.set(htmlElement, this);
Selectable.objects.set(htmlElement, this);
return this;
}
// createChild(htmlElement: HTMLElement, name: string = '') {
// const child = new Container(htmlElement, name);
// this.addChild(child);
// return child;
// }
focus() {
if (this.children.length > 0) {
this.children[get(this.focusIndex)]?.focus();
} else if (this.htmlElement) {
this.htmlElement.focus({ preventScroll: true });
this.htmlElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
Container.focusedObject.set(this);
Selectable.focusedObject.set(this);
this.updateFocusIndex();
}
}
updateFocusIndex(container?: Container) {
if (container) {
const index = this.children.indexOf(container);
updateFocusIndex(selectable?: Selectable) {
if (selectable) {
const index = this.children.indexOf(selectable);
this.focusIndex.update((prev) => (index === -1 ? prev : index));
}
if (this.parent) {
@@ -106,7 +94,7 @@ export class Container {
}
}
getFocusableNeighbor(direction: Direction): Container | undefined {
getFocusableNeighbor(direction: Direction): Selectable | undefined {
const canLoop =
(this.direction === 'vertical' &&
((direction === 'up' && get(this.focusIndex) !== 0) ||
@@ -114,6 +102,7 @@ export class Container {
(this.direction === 'horizontal' &&
((direction === 'left' && get(this.focusIndex) !== 0) ||
(direction === 'right' && get(this.focusIndex) !== this.children.length - 1)));
if (this.children.length > 0 && canLoop) {
if (direction === 'up' || direction === 'left') {
let index = get(this.focusIndex) - 1;
@@ -137,11 +126,12 @@ export class Container {
} else {
return this.parent?.getFocusableNeighbor(direction);
}
console.warn('How did we end up here');
}
giveFocus(direction: Direction) {
private giveFocus(direction: Direction) {
const neighbor = this.getFocusableNeighbor(direction);
// console.log('Giving focus to', direction, 'neighbor: ', neighbor?.name, neighbor);
if (neighbor) {
neighbor.focus();
return true;
@@ -150,45 +140,30 @@ export class Container {
}
}
// getChildRegisterer(): Registerer {
// return (htmlElement: HTMLElement) => {
// if (this.htmlElement) console.warn('Registering to a container that has an element.');
//
// this.createChild().addHtmlElement(htmlElement);
//
// if (!get(Container.focusedObject) && this.shouldFocusByDefault()) {
// this.focus();
// }
//
// return {
// destroy: () => {
// this.removeHtmlElement();
// }
// };
// };
// }
//
// getHtmlElementRegisterer(): Registerer {
// return (htmlElement: HTMLElement) => {
// if (this.children.length > 0) {
// console.warn('Registering an html element to a container that has children.');
// for (const child of this.children) {
// this.removeChild(child);
// }
// }
// this.addHtmlElement(htmlElement);
// return {
// destroy: () => {
// this.removeHtmlElement();
// }
// };
// };
// }
static focusUp() {
const currentlyFocusedObject = get(Selectable.focusedObject);
return currentlyFocusedObject?.giveFocus('up');
}
_initializeContainer() {
const getParentContainer = (htmlElement: HTMLElement): Container | undefined => {
if (Container.objects.get(htmlElement)) return Container.objects.get(htmlElement);
else if (htmlElement.parentElement) return getParentContainer(htmlElement.parentElement);
static focusDown() {
const currentlyFocusedObject = get(Selectable.focusedObject);
return currentlyFocusedObject?.giveFocus('down');
}
static focusLeft() {
const currentlyFocusedObject = get(Selectable.focusedObject);
return currentlyFocusedObject?.giveFocus('left');
}
static focusRight() {
const currentlyFocusedObject = get(Selectable.focusedObject);
return currentlyFocusedObject?.giveFocus('right');
}
_initializeSelectable() {
const getParentSelectable = (htmlElement: HTMLElement): Selectable | undefined => {
if (Selectable.objects.get(htmlElement)) return Selectable.objects.get(htmlElement);
else if (htmlElement.parentElement) return getParentSelectable(htmlElement.parentElement);
else return undefined;
};
@@ -196,29 +171,31 @@ export class Container {
console.error('No html element found for', this);
return;
} else if (this.isInitialized) {
console.warn('Container already initialized', this);
console.warn('Selectable already initialized', this);
}
const parentContainer = this.htmlElement.parentElement
? getParentContainer(this.htmlElement.parentElement)
console.log('Initializing', this.htmlElement);
const parentSelectable = this.htmlElement.parentElement
? getParentSelectable(this.htmlElement.parentElement)
: undefined;
if (parentContainer) {
parentContainer.addChild(this);
if (parentSelectable) {
parentSelectable.addChild(this);
} else {
console.error('No parent container found for', this.htmlElement);
console.error('No parent selectable found for', this.htmlElement);
}
if (!get(Container.focusedObject) && this.shouldFocusByDefault()) {
if (!get(Selectable.focusedObject) && this.shouldFocusByDefault()) {
this.focus();
}
}
_unmountContainer() {
console.log('Unmounting container', this);
console.log('Unmounting selectable', this);
const isFocusedWithin = get(this.hasFocusWithin);
if (this.htmlElement) {
Container.objects.delete(this.htmlElement);
Selectable.objects.delete(this.htmlElement);
}
const parent = this.parent;
@@ -231,19 +208,19 @@ export class Container {
}
private static createRegisterer(
_container?: Container,
_selectable?: Selectable,
flowDirection: FlowDirection = 'vertical'
): Registerer {
const container = _container || new Container().setDirection(flowDirection);
const selectable = _selectable || new Selectable().setDirection(flowDirection);
return (htmlElement: HTMLElement) => {
console.log('Registering', htmlElement, container);
container.setHtmlElement(htmlElement);
console.log('Registering', htmlElement, selectable);
selectable.setHtmlElement(htmlElement);
return {
destroy: () => {
container.parent?.removeChild(container);
Container.objects.delete(htmlElement);
selectable.parent?.removeChild(selectable);
Selectable.objects.delete(htmlElement);
}
};
};
@@ -255,62 +232,57 @@ export class Container {
}
getRegisterer(): Registerer {
return (htmlElement: HTMLElement) => Container.createRegisterer(this)(htmlElement);
return (htmlElement: HTMLElement) => Selectable.createRegisterer(this)(htmlElement);
}
static getStores(element: HTMLElement) {
return Container.objects.get(element)?.getStores();
return Selectable.objects.get(element)?.getStores();
}
getStores(): {
container: Container;
container: Selectable;
hasFocus: Readable<boolean>;
hasFocusWithin: Readable<boolean>;
registerer: Registerer;
focusIndex: Writable<number>;
} {
return {
container: this,
hasFocus: this.hasFocus,
hasFocusWithin: this.hasFocusWithin,
registerer: this.getRegisterer()
registerer: this.getRegisterer(),
focusIndex: this.focusIndex
};
}
private addChild(child: Container) {
private addChild(child: Selectable) {
this.children.push(child);
child.parent = this;
return this;
}
private removeChild(child: Container) {
private removeChild(child: Selectable) {
if (this.children.indexOf(child) < get(this.focusIndex)) {
this.focusIndex.update((prev) => prev - 1);
}
this.children = this.children.filter((c) => c !== child);
child.parent = undefined;
return this;
}
// private addHtmlElement(htmlElement: HTMLElement) {
// if (this.children.length > 0) {
// console.warn('Adding an html element to a container that has children.');
// for (const child of this.children) {
// this.removeChild(child);
// }
// }
// this.htmlElement = htmlElement;
// return this;
// }
private shouldFocusByDefault(): boolean {
return this.focusByDefault || this.parent?.shouldFocusByDefault() || false;
}
}
export function handleKeyboardNavigation(event: KeyboardEvent) {
const currentlyFocusedObject = get(Container.focusedObject);
const currentlyFocusedObject = get(Selectable.focusedObject);
if (!currentlyFocusedObject) {
console.error('No focused object!!!');
// Find object that can be focused
Container.objects.forEach((container) => {
Selectable.objects.forEach((container) => {
if (container.isFocusable()) {
container.focus();
}
@@ -321,19 +293,12 @@ export function handleKeyboardNavigation(event: KeyboardEvent) {
// console.log('Currently focused object: ', currentlyFocusedObject.name, currentlyFocusedObject);
if (event.key === 'ArrowUp') {
if (currentlyFocusedObject.giveFocus('up')) event.preventDefault();
if (Selectable.focusUp()) event.preventDefault();
} else if (event.key === 'ArrowDown') {
if (currentlyFocusedObject.giveFocus('down')) event.preventDefault();
if (Selectable.focusDown()) event.preventDefault();
} else if (event.key === 'ArrowLeft') {
if (currentlyFocusedObject.giveFocus('left')) event.preventDefault();
if (Selectable.focusLeft()) event.preventDefault();
} else if (event.key === 'ArrowRight') {
if (currentlyFocusedObject.giveFocus('right')) event.preventDefault();
if (Selectable.focusRight()) event.preventDefault();
}
}
export const focusedObject = Container.focusedObject;
// export const mainContainer = new Container('main')
// .setDirection('horizontal')
// .setFocusByDefault(true);
export const registerer = Container.getRegisterer();