From e01203cedb6425c2143aa038355eed0a3eadd1a9 Mon Sep 17 00:00:00 2001 From: Sam Reid Date: Mon, 29 Apr 2024 14:16:38 -0600 Subject: [PATCH] Add TInteractiveHighlighting, see https://github.com/phetsims/tasks/issues/1132 --- .../voicing/InteractiveHighlighting.ts | 38 +++++++++++++++---- js/accessibility/voicing/Voicing.ts | 5 +++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/js/accessibility/voicing/InteractiveHighlighting.ts b/js/accessibility/voicing/InteractiveHighlighting.ts index 8952fa04d..a42f48062 100644 --- a/js/accessibility/voicing/InteractiveHighlighting.ts +++ b/js/accessibility/voicing/InteractiveHighlighting.ts @@ -32,12 +32,36 @@ type SelfOptions = { export type InteractiveHighlightingOptions = SelfOptions; -const InteractiveHighlighting = memoize( >( Type: SuperType ) => { +export type TInteractiveHighlighting = { + + // @mixin-protected - made public for use in the mixin only + displays: Record; + + interactiveHighlightChangedEmitter: TEmitter; + readonly isInteractiveHighlightActiveProperty: TReadOnlyProperty; + readonly isInteractiveHighlighting: boolean; + setInteractiveHighlight( interactiveHighlight: Highlight ): void; + interactiveHighlight: Highlight; + getInteractiveHighlight(): Highlight; + setInteractiveHighlightLayerable( interactiveHighlightLayerable: boolean ): void; + interactiveHighlightLayerable: boolean; + getInteractiveHighlightLayerable(): boolean; + setInteractiveHighlightEnabled( enabled: boolean ): void; + getInteractiveHighlightEnabled(): boolean; + interactiveHighlightEnabled: boolean; + handleHighlightActiveChange(): void; + onChangedInstance( instance: Instance, added: boolean ): void; + + // @mixin-protected - made public for use in the mixin only + getDescendantsUseHighlighting( trail: Trail ): boolean; +}; + +const InteractiveHighlighting = memoize( >( Type: SuperType ): SuperType & Constructor => { // @ts-expect-error assert && assert( !Type._mixesInteractiveHighlighting, 'InteractiveHighlighting is already added to this Type' ); - const InteractiveHighlightingClass = DelayedMutate( 'InteractiveHighlightingClass', INTERACTIVE_HIGHLIGHTING_OPTIONS, class InteractiveHighlightingClass extends Type { + const InteractiveHighlightingClass = DelayedMutate( 'InteractiveHighlightingClass', INTERACTIVE_HIGHLIGHTING_OPTIONS, class InteractiveHighlightingClass extends Type implements TInteractiveHighlighting { // Input listener to activate the HighlightOverlay upon pointer input. Uses exit and enter instead of over and out // because we do not want this to fire from bubbling. The highlight should be around this Node when it receives @@ -54,7 +78,8 @@ const InteractiveHighlighting = memoize( >( // Displays to activate the Focus Property associated with highlighting, and to add/remove listeners when // features that require highlighting are enabled/disabled. Note that this is updated asynchronously // (with updateDisplay) since Instances are added asynchronously. - protected displays: Record = {}; + // @mixin-protected - made public for use in the mixin only + public displays: Record = {}; // The highlight that will surround this Node when it is activated and a Pointer is currently over it. When // null, the focus highlight will be used (as defined in ParallelDOM.js). @@ -605,8 +630,9 @@ const InteractiveHighlighting = memoize( >( * Returns true if any nodes from this Node to the leaf of the Trail use Voicing features in some way. In * general, we do not want to activate voicing features in this case because the leaf-most Nodes in the Trail * should be activated instead. + * @mixin-protected - made public for use in the mixin only */ - protected getDescendantsUseHighlighting( trail: Trail ): boolean { + public getDescendantsUseHighlighting( trail: Trail ): boolean { const indexOfSelf = trail.nodes.indexOf( this ); // all the way to length, end not included in slice - and if start value is greater than index range @@ -647,9 +673,7 @@ const InteractiveHighlighting = memoize( >( return InteractiveHighlightingClass; } ); -// Provides a way to determine if a Node is composed with InteractiveHighlighting by type -const wrapper = () => InteractiveHighlighting( Node ); -export type InteractiveHighlightingNode = InstanceType>; +export type InteractiveHighlightingNode = Node & TInteractiveHighlighting; scenery.register( 'InteractiveHighlighting', InteractiveHighlighting ); export default InteractiveHighlighting; \ No newline at end of file diff --git a/js/accessibility/voicing/Voicing.ts b/js/accessibility/voicing/Voicing.ts index 4e0febc96..0744a2ddf 100644 --- a/js/accessibility/voicing/Voicing.ts +++ b/js/accessibility/voicing/Voicing.ts @@ -475,6 +475,8 @@ const Voicing = >( Type: SuperType ) => { // this.cleanVoicingUtterance(); } + // TODO: Fix the type for VoicingNode, see https://github.com/phetsims/tasks/issues/1132 + // @ts-expect-error Voicing.registerUtteranceToVoicingNode( utterance, this ); this._voicingUtterance = utterance; } @@ -626,6 +628,9 @@ const Voicing = >( Type: SuperType ) => { // this._voicingUtterance.dispose(); } else if ( this._voicingUtterance && !this._voicingUtterance.isDisposed ) { + + // TODO: Fix the type for VoicingNode, see https://github.com/phetsims/tasks/issues/1132 + // @ts-expect-error Voicing.unregisterUtteranceToVoicingNode( this._voicingUtterance, this ); } }