import { AlloyComponent, Gui } from '@ephox/alloy'; import { Optional, Singleton } from '@ephox/katamari'; export interface SinkAndMothership { readonly sink: AlloyComponent; readonly mothership: Gui.GuiSystem; } export interface MainUi { readonly mothership: Gui.GuiSystem; readonly outerContainer: AlloyComponent; } export interface ReadyUiReferences { readonly dialogUi: SinkAndMothership; readonly popupUi: SinkAndMothership; readonly mainUi: MainUi; readonly uiMotherships: Gui.GuiSystem[]; } export interface LazyUiReferences { readonly dialogUi: Singleton.Value; readonly popupUi: Singleton.Value; readonly mainUi: Singleton.Value; // TINY-9226: We abstract over all "UI Motherships" for things like // * showing / hiding on editor focus/blur // * destroying on remove // * broadcasting events for dismissing popups on mousedown etc. readonly getUiMotherships: () => Array; readonly setupDialogUi: (ui: { sink: AlloyComponent; mothership: Gui.GuiSystem }) => void; readonly lazyGetInOuterOrDie: (label: string, f: (oc: AlloyComponent) => Optional) => () => A; } export const LazyUiReferences = (): LazyUiReferences => { const dialogUi = Singleton.value(); const popupUi = Singleton.value(); const mainUi = Singleton.value<{ mothership: Gui.GuiSystem; outerContainer: AlloyComponent }>(); const setupDialogUi = (ui: SinkAndMothership): void => { dialogUi.set(ui); }; const lazyGetInOuterOrDie = (label: string, f: (oc: AlloyComponent) => Optional): () => A => () => mainUi.get().bind( (oc) => f(oc.outerContainer) ).getOrDie( `Could not find ${label} element in OuterContainer` ); return { dialogUi, popupUi, mainUi, // TINY-9226: We need to return the popup mothership here once it has been added to the code getUiMotherships: () => [ ...dialogUi.get().map((e) => e.mothership).toArray() ], setupDialogUi, lazyGetInOuterOrDie }; };