import { FieldSchema, StructureSchema } from '@ephox/boulder'; import { Fun, type Optional } from '@ephox/katamari'; import type { SugarElement } from '@ephox/sugar'; import type { NamedConfiguredBehaviour } from '../api/behaviour/Behaviour'; import { Receiving } from '../api/behaviour/Receiving'; import { Sandboxing } from '../api/behaviour/Sandboxing'; import type { AlloyComponent } from '../api/component/ComponentApi'; import * as AlloyTriggers from '../api/events/AlloyTriggers'; import * as SystemEvents from '../api/events/SystemEvents'; import * as Channels from '../api/messages/Channels'; import type { ReceivingChannelSpec, ReceivingConfig, ReceivingConfigSpec } from '../behaviour/receiving/ReceivingTypes'; interface DismissalReceivingDetail { isExtraPart: (sandbox: AlloyComponent, target: SugarElement) => boolean; fireEventInstead: Optional<{ event: string; }>; } export interface DismissalReceivingSpec { isExtraPart?: (sandbox: AlloyComponent, target: SugarElement) => boolean; fireEventInstead?: { event?: string; }; } const schema = StructureSchema.objOfOnly([ FieldSchema.defaulted('isExtraPart', Fun.never), FieldSchema.optionObjOf('fireEventInstead', [ FieldSchema.defaulted('event', SystemEvents.dismissRequested()) ]) ]); const receivingConfig = (rawSpec: DismissalReceivingSpec): NamedConfiguredBehaviour => { const c = receivingChannel(rawSpec); return Receiving.config({ channels: c }); }; const receivingChannel = (rawSpec: DismissalReceivingSpec): Record => { const detail: DismissalReceivingDetail = StructureSchema.asRawOrDie('Dismissal', schema, rawSpec); return { [Channels.dismissPopups()]: { schema: StructureSchema.objOfOnly([ FieldSchema.required('target') ]), onReceive: (sandbox: AlloyComponent, data: { target: SugarElement }) => { if (Sandboxing.isOpen(sandbox)) { const isPart = Sandboxing.isPartOf(sandbox, data.target) || detail.isExtraPart(sandbox, data.target); if (!isPart) { detail.fireEventInstead.fold( () => Sandboxing.close(sandbox), (fe) => AlloyTriggers.emit(sandbox, fe.event) ); } } } } }; }; export { receivingChannel, receivingConfig };