Repository URL to install this package:
|
Version:
1.0.0-next.10 ▾
|
/**
* @license
* FOURBURNER CONFIDENTIAL
* Unpublished Copyright (C) 2021 FourBurner Technologies, Inc. All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of FOURBURNER TECHNOLOGIES,
* INC. The intellectual and technical concepts contained herein are proprietary to FOURBURNER
* TECHNOLOGIES, INC. and may be covered by U.S. and Foreign Patents, patents in process, and are
* protected by trade secret or copyright law. Dissemination of this information or reproduction of
* this material is strictly forbidden unless prior written permission is obtained from FOURBURNER
* TECHNOLOGIES, INC. Access to the source code contained herein is hereby forbidden to anyone
* except current FOURBURNER TECHNOLOGIES, INC. employees, managers or contractors who have executed
* Confidentiality and Non-disclosure agreements explicitly covering such access.
*
* The copyright notice above does not evidence any actual or intended publication or disclosure of
* this source code, which includes information that is confidential and/or proprietary, and is a
* trade secret, of FOURBURNER TECHNOLOGIES, INC. ANY REPRODUCTION, MODIFICATION, DISTRIBUTION,
* PUBLIC PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS
* WRITTEN CONSENT OF FOURBURNER TECHNOLOGIES, INC. IS STRICTLY PROHIBITED, AND IN VIOLATION OF
* APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR
* RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS
* CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
*/
import {BooleanInput} from '@angular/cdk/coercion';
import {
ChangeDetectionStrategy,
Component,
InjectionToken,
Input,
ViewEncapsulation,
Directive,
Inject,
Optional,
} from '@angular/core';
import {CanDisable, mixinDisabled} from '../common/disabled';
import {TWNDOptionParentComponent, TWND_OPTION_PARENT_COMPONENT} from './option.parent';
// Notes on the accessibility pattern used for `twnd-optgroup`.
// The option group has two different "modes": regular and inert. The regular mode uses the
// recommended a11y pattern which has `role="group"` on the group element with `aria-labelledby`
// pointing to the label. This works for `twnd-select`, but it seems to hit a bug for autocomplete
// under VoiceOver where the group doesn't get read out at all. The bug appears to be that if
// there's __any__ a11y-related attribute on the group (e.g. `role` or `aria-labelledby`),
// VoiceOver on Safari won't read it out.
// We've introduced the `inert` mode as a workaround. Under this mode, all a11y attributes are
// removed from the group, and we get the screen reader to read out the group label by mirroring it
// inside an invisible element in the option. This is sub-optimal, because the screen reader will
// repeat the group label on each navigation, whereas the default pattern only reads the group when
// the user enters a new group. The following alternate approaches were considered:
// 1. Reading out the group label using the `LiveAnnouncer` solves the problem, but we can't control
// when the text will be read out so sometimes it comes in too late or never if the user
// navigates quickly.
// 2. `<twnd-option aria-describedby="groupLabel"` - This works on Safari, but VoiceOver in Chrome
// won't read out the description at all.
// 3. `<twnd-option aria-labelledby="optionLabel groupLabel"` - This works on Chrome, but Safari
// doesn't read out the text at all. Furthermore, on
// Boilerplate for applying mixins to TWNDOptgroup.
/** @docs-private */
const _TWNDOptgroupMixinBase = mixinDisabled(class {});
// Counter for unique group ids.
let _uniqueOptgroupIdCounter = 0;
@Directive() export class _TWNDOptgroupBase extends _TWNDOptgroupMixinBase implements CanDisable
{
/** Label for the option group. */
@Input() label: string;
/** Unique id for the underlying label. */
_labelId: string = `twnd-optgroup-label-${_uniqueOptgroupIdCounter++}`;
/** Whether the group is in inert a11y mode. */
_inert: boolean;
constructor(@Inject(TWND_OPTION_PARENT_COMPONENT) @Optional() parent?: TWNDOptionParentComponent)
{
super();
this._inert = parent?.inertGroups ?? false;
}
static ngAcceptInputType_disabled: BooleanInput;
}
/**
* Injection token that can be used to reference instances of `TWNDOptgroup`. It serves as
* alternative token to the actual `TWNDOptgroup` class which could cause unnecessary
* retention of the class and its component metadata.
*/
export const TWND_OPTGROUP = new InjectionToken<TWNDOptgroup>('TWNDOptgroup');
/**
* Component that is used to group instances of `twnd-option`.
*/
@Component({
selector : 'twnd-optgroup',
exportAs : 'twndOptgroup',
templateUrl : 'optgroup.html',
encapsulation : ViewEncapsulation.None,
changeDetection : ChangeDetectionStrategy.OnPush,
inputs : [ 'disabled' ],
host : {
'class' : 'twnd-optgroup',
'[attr.role]' : '_inert ? null : "group"',
'[attr.aria-disabled]' : '_inert ? null : disabled.toString()',
'[attr.aria-labelledby]' : '_inert ? null : _labelId',
'[class.twnd-optgroup-disabled]' : 'disabled',
},
providers : [ {provide : TWND_OPTGROUP, useExisting : TWNDOptgroup}
],
})
export class TWNDOptgroup extends _TWNDOptgroupBase
{}