Skip to content

Commit

Permalink
feat(focus-trap): add focus trap module (#5634)
Browse files Browse the repository at this point in the history
* feat(common): add focus trap module

Add focus trap module to follow accessibility
Add focus trap directive to modal container

* fix(focus-trap): fix moduleWithProviders type issue

* feat(focus-trap): update focus-trap code according to last Angular changes

* feat(focus-trap): add focus-trap module  to build process with nx

* fix(lint): disable eslint for focus-trap  source files

Co-authored-by: Dmitry Danilov <daniloff200@gmail.com>
  • Loading branch information
IraErshova and daniloff200 committed Apr 5, 2021
1 parent 51051bd commit 8bcc900
Show file tree
Hide file tree
Showing 31 changed files with 1,441 additions and 44 deletions.
2 changes: 1 addition & 1 deletion _root/scripts/build-modules.js
Expand Up @@ -28,7 +28,7 @@ async function buildAll() {

// await execa.shell(`npm run link`);

const requiredModules = ['collapse', 'chronos', 'utils', 'positioning', 'component-loader', 'dropdown', 'locale',
const requiredModules = ['focus-trap', 'collapse', 'chronos', 'utils', 'positioning', 'component-loader', 'dropdown', 'locale',
'alert', 'buttons', 'carousel', 'mini-ngrx', 'modal', 'pagination', 'popover', 'progressbar', 'rating',
'sortable', 'tabs', 'timepicker', 'tooltip', 'typeahead', 'datepicker', 'accordion'];

Expand Down
42 changes: 42 additions & 0 deletions angular.json
Expand Up @@ -536,6 +536,48 @@
}
}
},
"focus-trap": {
"projectType": "library",
"root": "src/focus-trap",
"sourceRoot": "src/focus-trap",
"prefix": "ngx-bootstrap-base",
"architect": {
"build": {
"builder": "@nrwl/angular:package",
"outputs": [
"node_modules/ngx-bootstrap/focus-trap"
],
"options": {
"tsConfig": "src/focus-trap/tsconfig.lib.json",
"project": "src/focus-trap/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "src/focus-trap/tsconfig.lib.prod.json"
}
}
},
"lint": {
"builder": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": [
"src/focus-trap/**/*.ts",
"src/focus-trap/**/*.html"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"outputs": [
"coverage/src/focus-trap"
],
"options": {
"jestConfig": "src/focus-trap/jest.config.js",
"passWithNoTests": true
}
}
}
},
"locale": {
"projectType": "library",
"root": "src/locale",
Expand Down
Expand Up @@ -48,7 +48,7 @@ export class DiscoverComponent {
link: 'https://developerhub.io'
},
{
logo: 'https://i.ytimg.com/vi/Em6PAkViyU4/maxresdefault.jpg',
logo: 'https://www.inmopc.com/img/products/acuerdos-trovimap.jpg',
name: 'Trovimap',
description: 'Trovimap - Houses / Apartments / Locals for sale or rent',
link: 'https://trovimap.com/'
Expand Down
7 changes: 7 additions & 0 deletions nx.json
Expand Up @@ -58,6 +58,7 @@
"collapse",
"datepicker",
"dropdown",
"focus-trap",
"locale",
"modal",
"pagination",
Expand Down Expand Up @@ -142,6 +143,11 @@
"component-loader"
]
},
"focus-trap": {
"tags": [
"lib"
]
},
"locale": {
"tags": [
"lib"
Expand All @@ -161,6 +167,7 @@
],
"implicitDependencies": [
"positioning",
"focus-trap",
"component-loader"
]
},
Expand Down
45 changes: 6 additions & 39 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions src/focus-trap/.eslintrc.json
@@ -0,0 +1,22 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"plugin:@nrwl/nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
],
"parserOptions": { "project": ["src/focus-trap/tsconfig.*?.json"] },
"rules": {
"@angular-eslint/no-output-on-prefix": 0
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"rules": {}
}
]
}
7 changes: 7 additions & 0 deletions src/focus-trap/README.md
@@ -0,0 +1,7 @@
# focus-trap

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test focus-trap` to execute the unit tests.
20 changes: 20 additions & 0 deletions src/focus-trap/boolean-property.ts
@@ -0,0 +1,20 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/* eslint-disable */

/**
* Type describing the allowed values for a boolean input.
* @docs-private
*/
export type BooleanInput = string | boolean | null | undefined;

/** Coerces a data-bound value (typically a string) to a boolean. */
export function coerceBooleanProperty(value: any): boolean {
return value != null && `${value}` !== 'false';
}
22 changes: 22 additions & 0 deletions src/focus-trap/configurable-focus-trap-config.ts
@@ -0,0 +1,22 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/**
* Configuration for creating a ConfigurableFocusTrap.
*/

/* eslint-disable */

export class ConfigurableFocusTrapConfig {
/**
* Whether to defer the creation of FocusTrap elements to be
* done manually by the user. Default is to create them
* automatically.
*/
defer: boolean = false;
}
70 changes: 70 additions & 0 deletions src/focus-trap/configurable-focus-trap-factory.ts
@@ -0,0 +1,70 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/* eslint-disable */

import { DOCUMENT } from '@angular/common';
import {
Inject,
Injectable,
Optional,
NgZone
} from '@angular/core';
import { InteractivityChecker } from './interactivity-checker';
import { ConfigurableFocusTrap } from './configurable-focus-trap';
import { ConfigurableFocusTrapConfig } from './configurable-focus-trap-config';
import { FOCUS_TRAP_INERT_STRATEGY, FocusTrapInertStrategy } from './focus-trap-inert-strategy';
import { EventListenerFocusTrapInertStrategy } from './event-listener-inert-strategy';
import { FocusTrapManager } from './focus-trap-manager';

/** Factory that allows easy instantiation of configurable focus traps. */
@Injectable({ providedIn: 'root' })
export class ConfigurableFocusTrapFactory {
private _document: Document;
private _inertStrategy: FocusTrapInertStrategy;

constructor(
private _checker: InteractivityChecker,
private _ngZone: NgZone,
private _focusTrapManager: FocusTrapManager,
@Inject(DOCUMENT) _document: any,
@Optional() @Inject(FOCUS_TRAP_INERT_STRATEGY) _inertStrategy?: FocusTrapInertStrategy) {

this._document = _document;
// TODO split up the strategies into different modules, similar to DateAdapter.
this._inertStrategy = _inertStrategy || new EventListenerFocusTrapInertStrategy();
}

/**
* Creates a focus-trapped region around the given element.
* @param element The element around which focus will be trapped.
* @param config The focus trap configuration.
* @returns The created focus trap instance.
*/
create(element: HTMLElement, config?: ConfigurableFocusTrapConfig): ConfigurableFocusTrap;

/**
* @deprecated Pass a config object instead of the `deferCaptureElements` flag.
* @breaking-change 11.0.0
*/
create(element: HTMLElement, deferCaptureElements: boolean): ConfigurableFocusTrap;

create(element: HTMLElement, config: ConfigurableFocusTrapConfig | boolean =
new ConfigurableFocusTrapConfig()): ConfigurableFocusTrap {
let configObject: ConfigurableFocusTrapConfig;
if (typeof config === 'boolean') {
configObject = new ConfigurableFocusTrapConfig();
configObject.defer = config;
} else {
configObject = config;
}
return new ConfigurableFocusTrap(
element, this._checker, this._ngZone, this._document, this._focusTrapManager,
this._inertStrategy, configObject);
}
}

0 comments on commit 8bcc900

Please sign in to comment.